My getView method in my custom array adapter is not working - android

can you give me some advice about my getView methood;
I have custom adapter that extends ArrayAdapter(context, id, list)
public class myCustomAdapter extends ArrayAdapter{
private List obj = null;
public myCustomAdapter(#NonNull Context context, #LayoutRes int resource, #NonNull List objects) {
super(context, resource, objects);
obj = objects;
}
#Override
public int getCount() {
return obj.size();
}
#Nullable
#Override
public Object getItem(int position) {
return super.getItem(position);
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
Task myTask = (Task) getItem(position);
if(convertView==null){
convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent);
}
TextView myTextView = (TextView) convertView.findViewById(R.id.textView);
myTextView.setText(myTask.getTaskText());
CheckBox myCheckBox = (CheckBox) convertView.findViewById(R.id.checkBox);
myCheckBox.setChecked(myTask.getChecked());
return convertView;
}
}
problem 1 : super: Unchecked call to ArrayAdapter(..) as member of raw type
problem 3 : getTaskText //methood from my Task class// may produce NPE
I would appreciate any help if possible.

if(convertView!=null){
convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent);
}
should be
if(convertView==null){
convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent);
}
you have to inflate when the convertview is null. not when its not null. And then return this from your getView() method
Also i can not see getCount() method. It is also very important to tell the adapter about how many items to inflate

Change this
return super.getView(position, convertView, parent)
to
return convertView;

You have to inflate convertview when it is null.
if(convertView==null){
convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent);
}
Also return convertview instead of super

I suggest use BaseAdapter, it's basic, ArrayAdapter is BaseAdapter' subclass, In most cases, you do not need to inherit the BaseAdapter, use it directly.
ArrayAdapter adapter = new ArrayAdapter(context, R.layout.list_item, R.id.text, stringList);
public class MyCustomAdapter extends BaseAdapter {
private List<Task> listData;
public MyCustomAdapter(List<Task> list) {
listData = list;
}
#Override
public int getCount() {
return listData.size();
}
#Override
public Object getItem(int position) {
return listData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
}
Task data = getItem(position);
TextView text = (TextView) convertView.findViewById(R.id.text);
return convertView;
}
}

Related

ListView Custom Adapter repeat items

Whats wrong with this adapter, when i scroll down i see repeated rows at the bottom and then when scroll up again i see also repeated rows at the top that were not exist before, and the rest of Data items does not appear
the adapter:
public class ClassesListViewAdapter extends BaseAdapter {
private Context mContext;
ArrayList<String> Data = new ArrayList<>();
public ClassesListViewAdapter(Context context, ArrayList<String> data) {
Data = data;
mContext = context;
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getCount() {
return Data.size();
}
private class ViewHolder{
TextView ClassDataTV;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = ((Activity)mContext).getLayoutInflater();
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.classes_list_view_item, parent, false);
holder = new ViewHolder();
holder.ClassDataTV = (TextView) convertView.findViewById(R.id.ClassDataTV);
holder.ClassDataTV.setText(Data.get(position));
convertView.setTag(holder);
}else{
holder=(ViewHolder)convertView.getTag();
}
return convertView;
}
}
and here how i use it:
ArrayList<String> v = new ArrayList<>();
v.add("AAAAAAA");
v.add("WWWWWwW");
v.add("VVVVVVV");
v.add("SSSSSSSSS");
v.add("QQQQQQQQQ");
v.add("YYYYYYYY");
v.add("TTTTTTT");
v.add("UUUUUUUUUU");
v.add("zzzzzzzzzzzz");
v.add("CCCCCCCCCC");
v.add("HHHHHHHHHHH");
v.add("IIIIIIIIII");
v.add("PPPPPPPPP");
mListView.setAdapter(new ClassesListViewAdapter(getActivity(), v));
Put following part of your code outside if-block and it will be fixed :
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = ((Activity)mContext).getLayoutInflater();
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.classes_list_view_item, parent, false);
holder = new ViewHolder();
holder.ClassDataTV = (TextView) convertView.findViewById(R.id.ClassDataTV);
convertView.setTag(holder);
}else{
holder=(ViewHolder)convertView.getTag();
}
// initialize your view here
holder.ClassDataTV.setText(Data.get(position));
return convertView;
}
The logic behind ViewHolder pattern tells that you should do it in this way. when you scroll some of reference will not created again and else block called so this cause your list not updated as you expected.

Android set items into Spinner by custom Adapter

in my application i have custom BaseAdapter for Spinner for insert data from List into that,
in this method i can return List as an data:
public List<String> getSmsNumberList() {
return Arrays.asList(smsNumbers.split("\\s*,\\s*"));
}
after geting successfull data from that i'm prepare to insert into Spinner:
smsNumbers = G.getInfo().getSmsNumberList();
panel_numbers = (String[]) smsNumbers.toArray(new String[smsNumbers.size()]);
SpinnerArrayAdapter dataAdapter = new SpinnerArrayAdapter(this);
spinner_panel_numbers.setAdapter(dataAdapter);
smsNumbers have some data returned by getSmsNumberList() function, now i'm using this below custom BaseAdapter for view data into Spinner :
Adapter code UPDATED
private class SpinnerArrayAdapter extends BaseAdapter {
private final LayoutInflater mInflater;
List<String> list;
public SpinnerArrayAdapter(ActivitySmsSendGroup con, List<String> list) {
mInflater = LayoutInflater.from(con);
this.list = list;
}
#Override
public int getCount() {
return list.length;
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ListContent holder;
View v = convertView;
if (v == null) {
v = mInflater.inflate(R.layout.panel_number_spinner_style, null);
holder = new ListContent();
holder.name = (TextView) v.findViewById(R.id.textView1);
v.setTag(holder);
} else {
holder = (ListContent) v.getTag();
}
holder.name.setText(list[position] + "");
return v;
}
}
static class ListContent {
TextView name;
}
unfortunately my Spinner dialog dont have data and that empty
Here:
panel_numbers = (String[]) smsNumbers.toArray(new
String[smsNumbers.size()]);
Because already have List so no need to convert it to Array just add one more parameter to constructor of SpinnerArrayAdapter class :
List<String> list;
public SpinnerArrayAdapter(ActivitySmsSendGroup con,List<String> list) {
mInflater = LayoutInflater.from(con);
this.list=list;
}
Now use list instead of panel_numbers everywhere in SpinnerArrayAdapter class
Pass List from Activity in SpinnerArrayAdapter class constructor when create object:
SpinnerArrayAdapter dataAdapter = new SpinnerArrayAdapter(this,smsNumbers);
In your adapter you should add a method, and variable for your ArrayList (add your own object here)
public static ArrayList<ListObject> listItems;
public void addItems(ArrayList<ListObject> mListItems) {
listItems = new ArrayList<ListObject>();
listItems.clear();
listItems.addAll(mListItems);
notifyDataSetChanged();
}
Then in your main class call
SpinnerArrayAdapter.addItems(myList);
Note: Ensure within getView that your'e setting variables based on listItem in the class ie. title.setText(listItems.get(position).name);
Your adapter should look like this:
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent){
return getCustomView(position, convertView, parent);
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
return getCustomView(position, convertView, parent);
}
public View getCustomView(final int position, View convertView, ViewGroup parent){
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
View rowView = inflater.inflate(R.layout.spinner_row, parent, false);
spnItemName = (TextView) rowView.findViewById(R.id.spnItemName);
spnItemDel = (TextView) rowView.findViewById(R.id.spnItemDel);
spnItemName.setText(iName.get(position)+"");
spnItemDel.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context, "Deleted", Toast.LENGTH_SHORT).show();
//iName[position] = null;
iName.remove(position);
notifyDataSetChanged();
}
});
return rowView;
}
For full source code please see my github project

Custom spinner adapter simple_spinner_dropdown_item not displaying correctly

I am getting data from an SQLite database and assigning them to data objects. I am using a custom spinner adapter (implements SpinnerAdapter) to put them in spinners so as to override the getItem() and getItemId() methods. However, the android.R.layout.simple_spinner_dropdown_item is not displaying correctly (screenshots from my Galaxy Tab 2 10.1):
By contrast this is a spinner which is populated from an array in R.array (the correct look/size):
Done by this code:
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getActivity(), R.array.quote_prices, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
I am unable to get this look by implementing/extending some sort of adapter (I have also tried extending BaseAdapter to no avail). This is the code for my spinner adapter as it stands:
public class MySpinnerAdapter implements SpinnerAdapter {
private Context context;
/**
* The internal data (the ArrayList with the Objects).
*/
private List<? extends BaseDO> data;
public MySpinnerAdapter(Context context, List<?extends BaseDO> data){
this.context = context;
this.data = data;
}
/**
* Returns the Size of the ArrayList
*/
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int position) {
return data.get(position);
}
#Override
public long getItemId(int position) {
return data.get(position).getId();
}
#Override
public int getItemViewType(int position) {
return 0;
}
#Override
public int getViewTypeCount() {
return 1;
}
#Override
public boolean hasStableIds() {
return false;
}
#Override
public boolean isEmpty() {
return false;
}
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(android.R.layout.simple_spinner_dropdown_item, null);
}
((TextView) convertView).setText(data.get(position).toString());
return convertView;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView textView = (TextView) View.inflate(context, android.R.layout.simple_spinner_item, null);
textView.setText(data.get(position).toString());
return textView;
}
#Override
public void registerDataSetObserver(DataSetObserver observer) {
}
#Override
public void unregisterDataSetObserver(DataSetObserver observer) {
}
public List<? extends BaseDO> getData() {
return data;
}
}
Any help would be appreciated.
EDIT: I forgot to mention that this is called using
spnnrTerm.setAdapter(new MySpinnerAdapter(getActivity(), termList));
I know this question is old but I've been having the same issue and have just figured out the problem. After examining the source for ArrayAdapter.java I noticed it was passing the ViewGroup to the inflater and I wasn't. This was the problem all along.
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(android.R.layout.simple_spinner_dropdown_item, parent, false);
}
((TextView) convertView).setText(data.get(position).toString());
return convertView;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView textView = (TextView) View.inflate(context, android.R.layout.simple_spinner_item, null);
textView.setText(data.get(position).toString());
return textView;
}

ArrayAdapter goes beyond bounds

I have an ArrayAdapter with ArrayList filled. Each time I click on any of its item I re-fill the ArrayList and send notifyOnDataSetChange() to the adapter. But for unknown for me reason it goes out of ArrayList bounds in it's getView() method where it populates its items. I don't understand why this happens. Can you guys explain the theory of getView() invokation so I understand why this going on. Thanks in advance!
Here it is:
class MAdapter extends ArrayAdapter<String> {
public MAdapter(Context context, int textViewResourceId, List<String> objects) {
super(context, textViewResourceId, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.file_explorer_row, null);
} else {
}
String txt = itemsList.get(position); // Out of bounds happens here
if (!txt.equals("")) {
TextView tt = (TextView) v.findViewById(R.id.file_explorer_tv_filename);
tt.setText(txt);
}
return v;
}
itemsList is declared in Outer Class.
change like this
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null)
{
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.file_explorer_row, parent, false);
}
Though i am not getting a clear view of what you are asking..i am assuming that , you are refilling the entire ArrayAdapter again....
So try this.........
Use removeView() on ListView before setting the adapter to it...
Eg:
ListView.removeView();
ListView.setAdapter(yourAdapter);
String txt = itemsList.get(position);
itemsList.get(position) returns a Integer Value and that you are try to store in a String..this might be the reason.
Try this code:
class MAdapter extends BaseAdapter {
List<String> objects;
Context context;
public MAdapter(Context context,List<String> objects) {
super();
this.context=context;
this.objects=objects;
}
public int getCount() {
return objects.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return 0;
}
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
Holder holder;
LayoutInflater vi;
if (v == null) {
holder=new Holder();
vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.file_explorer_row, null);
holder.tt= (TextView) v.findViewById(R.id.file_explorer_tv_filename);
v.setTag(holder);
} else {
holder = (Holder) v.getTag();
}
String txt = objects.get(position); // Out of bounds happens here
if (!txt.equals("")) {
holder.tt.setText(txt);
}
return v;
}
static class Holder{
TextView tt;
}
}

How put <Spanned> into list.setAdapter?

Simple but little tricky, if I have
list.setAdapter(new ArrayAdapter<String>(this,R.layout.double_row, R.id.doubleRow, articleItemsHelper));
it works if articleItemsHelper is String, but I wanna have HTML formatting in there so when articleItemsHelper is type Spanned this (adapter) doesn't work.
ArrayList<Spanned> articleItemsHelper = new ArrayList<Spanned>();
What's the solution?
EDIT: here is the solution - custom adapter
private static class SpannedAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private ArrayList<Spanned> mArticleList;
public SpannedAdapter(Context context, ArrayList<Spanned> articleList) {
mInflater = LayoutInflater.from(context);
mArticleList = articleList;
}
public int getCount() {
return mArticleList.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.single_row, null);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.singleRow);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.text.setText(mArticleList.get(position));
return convertView;
}
static class ViewHolder {
TextView text;
}
}
Then just regularly call
list.setAdapter(new SpannedAdapter(this, articleItemsHelper));
where
articleItemsHelper
is
ArrayList<Spanned>
Old thread but I found an other way to do it, it can help people:
simpleAdpt = new ArrayAdapter<Note>(this, R.layout.notelist, listeNotes ){
public View getView(int position, View view, ViewGroup viewGroup)
{
View v = super.getView(position, view, viewGroup);
Note n = (Note) this.getItem(position);
((TextView)v).setText(Html.fromHtml("<b>"+n.getTitre() + "</b> <br/>"+n.getNote()));
return v;
}
};
This is how ArrayAdapter set the text of the rows:
T item = getItem(position);
if (item instanceof CharSequence) {
text.setText((CharSequence)item);
} else {
text.setText(item.toString());
}
As you can see, what it would do in your case is to call the toString method, and that's why it does not work. So, go ahead and write your own adapter, you have no choice in this case.

Categories

Resources