I am having a problem in customlist view.
I have two buttons and one textView . Add and Subtract Buttons.
when click Add button the counter should be +1 and -1 respectively.
I have used a dummy string for checking whether it is actually updating the textView or not. But the problem is when I scroll down some of the items are having same value.
For example
1st item TextView is set to "HIII"
then if I scroll down the 11th ,21th ... is also set to "HIII"
Note: the max number that display can contain is 10 items so when I scroll down to 11th it is set to "HII".
public class CustomAdapter extends ArrayAdapter {
Context context;
LayoutInflater inflater;
int resource;
//ArrayList<Integer> count = new ArrayList<>();
public CustomAdapter(Context context, int resource) {
super(context, resource);
this.context = context;
this.resource = resource;
}
#Override
public int getCount() {
return 100;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder mainHolder = null;
if (convertView == null) {
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(resource, parent, false);
Log.e("GET-VIEW", " Creating Views");
final ViewHolder holder = new ViewHolder();
holder.add = (Button) convertView.findViewById(R.id.add);
holder.sub = (Button) convertView.findViewById(R.id.sub);
holder.textView = (TextView) convertView.findViewById(R.id.numberTV);
holder.add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.textView.setText("HIII");
}
});
convertView.setTag(holder);
} else {
mainHolder = (ViewHolder) convertView.getTag();
}
return convertView;
}
}
class ViewHolder {
Button add, sub;
TextView textView;
}
Please Help me. I want to know how to set tag of one with other(I mean how you know you need to set the tag with the other object or view)
Thanks
ListView recycles Views. It creates Views that will be re-used when scrolling down.
Thus, you have to call setText() and setOnClickListener() every time getView() is called, not only when button is clicked.
To achieve what you want, you have to store set text data in a model, like a SparseArray which maps positions to data.
public class CustomAdapter extends ArrayAdapter {
Context context;
LayoutInflater inflater;
int resource;
//ArrayList<Integer> count = new ArrayList<>();
// Your data map by position
SparseArray<String> data = new SparseArray<>();
public CustomAdapter(Context context, int resource) {
super(context, resource);
this.context = context;
this.resource = resource;
}
#Override
public int getCount() {
return 100;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(resource, parent, false);
Log.e("GET-VIEW", " Creating Views");
holder = new ViewHolder();
holder.add = (Button) convertView.findViewById(R.id.add);
holder.sub = (Button) convertView.findViewById(R.id.sub);
holder.textView = (TextView) convertView.findViewById(R.id.numberTV);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.textView.setText(data.get(position));
holder.add.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View v) {
final String text = "HIII";
data.put(position, text);
holder.textView.setText(text);
notifyDataSetChanged();
}
});
return convertView;
}
}
class ViewHolder {
Button add, sub;
TextView textView;
}
write your onclick listener after else condition.
holder.add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.textView.setText("HIII");
}
});
Take a look at your getView function:
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder mainHolder = null;
if (convertView == null) {
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(resource, parent, false);
Log.e("GET-VIEW", " Creating Views");
final ViewHolder holder = new ViewHolder();
holder.add = (Button) convertView.findViewById(R.id.add);
holder.sub = (Button) convertView.findViewById(R.id.sub);
holder.textView = (TextView) convertView.findViewById(R.id.numberTV);
holder.add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.textView.setText("HIII");
}
});
convertView.setTag(holder);
} else {
mainHolder = (ViewHolder) convertView.getTag();
}
return convertView;
}
You edit the content of your holder textView and add Button only when you create a new Viewholder.
The first time your listview shows its items, there will be always a new view created (and a new Viewholder, too) for all visible cells.
As soon as you scroll down, the adapter will take a now-invisble cell (maybe the frist cell) and recycle it to show a now-visible cell. In this case, your convertView in getView won't be null anymore, as the view was recycled.
So you should handle all your text changes an Listener and so on outside of your if statement to manage both cases (recycled and new).
For example:
if (convertView == null) {
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(resource, parent, false);
Log.e("GET-VIEW", " Creating Views");
final ViewHolder holder = new ViewHolder();
holder.add = (Button) convertView.findViewById(R.id.add);
holder.sub = (Button) convertView.findViewById(R.id.sub);
holder.textView = (TextView) convertView.findViewById(R.id.numberTV);
convertView.setTag(holder);
} else {
mainHolder = (ViewHolder) convertView.getTag();
}
holder.textView.setText("");
holder.add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.textView.setText("HIII");
}
});
Edit
To save your data in a sparse array like Yaroslav Mytkalyk suggested would be a better approach.
Anyway, you have to handle recycled views.
Related
I am trying to implement my custom adapter but I am facing performance issues. It seems that every time I scroll the list it is loaded all over again. I want it to hold the view and display only the visible part. My list item has imageview and textview.
My code:
class CustomAdapter extends BaseAdapter {
private Context context;
private ArrayList<CounselorInfo> counselors;
private static LayoutInflater inflater = null;
CustomAdapter(Context context, ArrayList<CounselorInfo> counselors) {
this.context = context;
this.counselors = counselors;
inflater = ( LayoutInflater )context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return counselors.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
private class Holder
{
TextView textView;
ImageView imageView;
}#Override
public View getView(final int position, View convertView, ViewGroup parent) {
Holder holder = new Holder();
View rowView = inflater.inflate(R.layout.counselors_list, null);
holder.textView = (TextView) rowView.findViewById(R.id.nameCounselor);
holder.imageView = (ImageView) rowView.findViewById(R.id.imageCounselor);
holder.textView.setText(counselors.get(position).getName());
ImageLoadTask imageLoad = new ImageLoadTask(" http:// " + counselors.get(position).getImageURL(), holder.imageView);
imageLoad.execute();
rowView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// do something
}
});
return rowView;
}
}
Android studio gives suggestion on this row:
View rowView = inflater.inflate(R.layout.counselors_list, null);
it says: Unconditional layout inflation from view adapter: Should use View Holder pattern (use recycled view passed into this method as the second parameter) for smoother scrolling.
But I use inner class Holder so I don't know how to solve it.
add this on getView():
final Holder holder;
if (convertView == null) {
holder = new Holder();
View rowView = inflater.inflate(R.layout.counselors_list, null);
holder.textView = (TextView) rowView.findViewById(R.id.nameCounselor);
holder.imageView = (ImageView) rowView.findViewById(R.id.imageCounselor);
convertView.setTag(holder);
} else
{
holder = (Holder) convertView.getTag();
}
I have implemented a custom listview in which I have two textviews and checkbox. These are encapsulated into a linear layout on whoms click I check/uncheck the checkbox. The problem I am facing is that when I click the linear layout, it checks the checkbox but it also checks other checkboxes on a fixed pattern i.e every 7-8 rows. I read many problems regarding it and found out that implementing a view holder would solve the problem but that's also not working for me. Following is my code:
CustomListAdapter:
public class ContactsListAdapter extends BaseAdapter{
private Context context;
private List<ContactInfo> contacts;
private List<ContactInfo> selectedContacts;
public ContactsListAdapter(Context context, List<ContactInfo> contacts) {
this.context = context;
this.contacts = contacts;
selectedContacts = new ArrayList<ContactInfo>();
}
public List<ContactInfo> getSelectedContacts() {
return selectedContacts;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return contacts.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return contacts.get(position);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return Long.parseLong(contacts.get(position).id);
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final ViewHolder holder;
if(convertView == null) {
convertView = inflater.inflate(R.layout.contacts_list_row_item, null);
holder = new ViewHolder();
holder.view = (LinearLayout) convertView.findViewById(R.id.llContactRow);
holder.name = (TextView) convertView.findViewById(R.id.tvContactName);
holder.number = (TextView) convertView.findViewById(R.id.tvContactNumber);
holder.checkbox = (CheckBox) convertView.findViewById(R.id.cbMultipleSelect);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.name.setText(contacts.get(position).name);
holder.number.setText(contacts.get(position).number);
holder.view.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ContactInfo contact = new ContactInfo();
contact.id = contacts.get(position).id;
contact.name = contacts.get(position).name;
contact.number = contacts.get(position).number;
holder.checkbox.setChecked(!holder.checkbox.isChecked());
if(holder.checkbox.isChecked()) {
selectedContacts.add(contact);
} else {
selectedContacts.remove(contact);
}
}
});
return convertView;
}
private static class ViewHolder {
LinearLayout view;
CheckBox checkbox;
TextView name;
TextView number;
}
}
What am I doing wrong? Please help.
EDIT:
After doing what #vinitius asked me to do the problem was resolved but the checks are disappearing when I scroll the list. Here is my new getView():
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final ViewHolder holder;
if(convertView == null) {
convertView = inflater.inflate(R.layout.contacts_list_row_item, null);
holder = new ViewHolder();
holder.view = (LinearLayout) convertView.findViewById(R.id.llContactRow);
holder.name = (TextView) convertView.findViewById(R.id.tvContactName);
holder.number = (TextView) convertView.findViewById(R.id.tvContactNumber);
holder.checkbox = (CheckBox) convertView.findViewById(R.id.cbMultipleSelect);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.name.setText(contacts.get(position).name);
holder.number.setText(contacts.get(position).number);
holder.checkbox.setChecked(selectedContacts.contains(contacts.get(position)));
holder.view.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ContactInfo contact = new ContactInfo();
contact.id = contacts.get(position).id;
contact.name = contacts.get(position).name;
contact.number = contacts.get(position).number;
holder.checkbox.setChecked(!holder.checkbox.isChecked());
if(holder.checkbox.isChecked()) {
selectedContacts.add(contact);
} else {
selectedContacts.remove(contact);
}
}
});
return convertView;
}
You are not showing your content in your getView(). Do the following:
#Override
public void onClick(View v) {
//remove the other stuff. You don't want to create new instances here, otherwise you won't be able to remove them later
holder.checkbox.setChecked(!holder.checkbox.isChecked());
if(holder.checkbox.isChecked()) {
selectedContacts.add(contact.get(position));
} else {
selectedContacts.remove(contact.get(position));
}
}
And do it before you set OnClickListener for your LinearLayout:
holder.checkbox.setChecked(selectedContacts.contains(contacts.get(position)));
And if you want the same behaviour when hitting the CheckBox, just add to your CheckBox xml:
android:clickable="false"
So the linearLayout can intercept it
your issue is that you need to set holder.checkbox.setChecked() to a value underneath the line:
holder.number.setText(contacts.get(position).number);
Currently you are changing the value of it when it is checked but you need to set the value when your getview method is called otherwise it will just keep whatever value it had before.
It would probably be best if you had a 'selected' value in your contactinfo rather than managing a new list. This way you could do something like:
holder.checkbox.setChecked(contacts.get(position).isSelected);
I have a listview with a custom adapter like this:
I would like to set different actions for every button in listview, for example switching by position in the listview. How can i do that?
This is my custom adapter:
public class Customadapter extends ArrayAdapter<Formazionicontainer>{
Context context;
public Customadapter(Context context, int resourceId,
List<Formazionicontainer> items) {
super(context, resourceId, items);
this.context = context;
}
/*private view holder class*/
private class ViewHolder {
ImageView imageView;
TextView txtTitle;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
Formazionicontainer rowItem = getItem(position);
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_group, null);
holder = new ViewHolder();
holder.txtTitle = (TextView) convertView.findViewById(R.id.text1);
holder.imageView = (ImageView) convertView.findViewById(R.id.image1);
convertView.setTag(holder);
} else
holder = (ViewHolder) convertView.getTag();
holder.txtTitle.setText(rowItem.getTitle());
holder.imageView.setImageResource(rowItem.getImageId());
return convertView;
}
One solution is use the ViewHolder as the Button click listener:
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
Formazionicontainer rowItem = getItem(position);
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_group, null);
holder = new ViewHolder();
holder.txtTitle = (TextView) convertView.findViewById(R.id.text1);
holder.imageView = (ImageView) convertView.findViewById(R.id.image1);
holder.button = (ImageView) convertView.findViewById(R.id.button1);
// Set the ViewHolder to handle the Button click
holder.button.setOnClickListener(holder);
convertView.setTag(holder);
} else
holder = (ViewHolder) convertView.getTag();
holder.txtTitle.setText(rowItem.getTitle());
holder.imageView.setImageResource(rowItem.getImageId());
// Update the holder item
holder.item = rowItem;
return convertView;
}
private class ViewHolder implements View.OnClickListener {
TextView txtTitle;
ImageView imageView;
Button button;
Formazionicontainer item;
#Override
public void onClick(View view) {
// Handle the button click here...
// The item attribute contains the information about the Button's item clicked.
}
}
Lets say you have an array that you passed to your list view adapter:
String[] values = {"Inter","Juventus"};
then you can do something like:
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
switch(position){
case 0: // Inter
break;
case 1: // Juventus
break;
}
}
});
//EDIT
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
Formazionicontainer rowItem = getItem(position);
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_group, null);
holder = new ViewHolder();
holder.button = (Button) convertView.findViewById(R.id.button1);
holder.button.setOnClickListener(holder);
holder.txtTitle = (TextView) convertView.findViewById(R.id.text1);
holder.imageView = (ImageView) convertView.findViewById(R.id.image1);
convertView.setTag(holder);
} else
holder = (ViewHolder) convertView.getTag();
holder.item = rowItem;
holder.txtTitle.setText(rowItem.getTitle());
holder.imageView.setImageResource(rowItem.getImageId());
/* you can also add on click listener this way to your views
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(YourActivityName.this,
"I am here at position: " + position,
Toast.LENGTH_LONG).show();
}
});
*/
return convertView;
}
private class ViewHolder implements View.OnClickListener {
Button button;
Formazionicontainer item;
TextView txtTitle;
ImageView imageView;
#Override
public void onClick(View view) {
// Your things here
}
}
So I populate a ListView from the local database using Custom Adapter. What I want to do now is when I click a button the lists in the listview will change its order like what shown in the image. Can someone help me. Here's my code.
This is the current ListView --> SEE IMAGE
This is what I want to do --> SEE IMAGE
CustomAdapter.java
public CustomAdaper(Context context,ArrayList<SampleObj> items) {
super(context,0, items);
this.context = context;
this.items = items;
vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View v = convertView;
final ViewHolder holder;
final SampleObj i = items.get(position);
if (i != null) {
final SampleObj ei = (SampleObj)i;
if (v == null) {
v = vi.inflate(R.layout.log_row, null);
holder = new ViewHolder();
holder.date = (TextView)v.findViewById(R.id.date);
holder.time = (TextView)v.findViewById(R.id.time);
holder.buttonID = (TextView)v.findViewById(R.id.buttonID);
v.setTag(holder);
}
else {
holder = (ViewHolder)v.getTag();
}
holder.date.setText(ei.date);
holder.time.setText(ei.time);
holder.buttonID.setText(ei.buttonID);
}
return v;
}
private static class ViewHolder {
public TextView date;
public TextView time;
public TextView buttonID;
}
}
you need to use Expandale List
First see this
then this
then this
I have found a mysterious problem that may be a bug!
I have a list in my fragment. Each row has a button. List shouldn't respond to click however buttons are clickable.
In order to get which button has clicked I have created a listener and implement it in my fragment. This is the code of my adapter.
public class AddFriendsAdapter extends BaseAdapter {
public interface OnAddFriendsListener {
public void OnAddUserClicked(MutualFriends user);
}
private final String TAG = "*** AddFriendsAdapter ***";
private Context context;
private OnAddFriendsListener listener;
private LayoutInflater myInflater;
private ImageDownloader imageDownloader;
private List<MutualFriends> userList;
public AddFriendsAdapter(Context context) {
this.context = context;
myInflater = LayoutInflater.from(context);
imageDownloader = ImageDownloader.getInstance(context);
}
public void setData(List<MutualFriends> userList) {
this.userList = userList;
Log.i(TAG, "List passed to the adapter.");
}
#Override
public int getCount() {
try {
return userList.size();
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = myInflater.inflate(R.layout.list_add_friends_row, null);
holder = new ViewHolder();
Typeface font = Typeface.createFromAsset(context.getAssets(), "fonts/ITCAvantGardeStd-Demi.ttf");
holder.tvUserName = (TextView) convertView.findViewById(R.id.tvUserName);
holder.tvUserName.setTypeface(font);
holder.ivPicture = (ImageView) convertView.findViewById(R.id.ivPicture);
holder.btnAdd = (Button) convertView.findViewById(R.id.btnAdd);
holder.btnAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.e(TAG, "Item: " + position);
listener.OnAddUserClicked(userList.get(position));
}
});
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tvUserName.setText(userList.get(position).getName());
imageDownloader.displayImage(holder.ivPicture, userList.get(position).getPhotoUrl());
return convertView;
}
public void setOnAddClickedListener(OnAddFriendsListener listener) {
this.listener = listener;
}
static class ViewHolder {
TextView tvUserName;
ImageView ivPicture;
Button btnAdd;
}
}
When I run the app, I can see my rows however since my list is long and has over 200 items when i goto middle of list and click an item then returned position is wrong (it's something like 7, sometimes 4 and etc.).
Now what is the mystery?
If I active on item listener of list from my fragment and click on row then correct row position will be displayed while on that row if I click on button then wrong position will be displayed.
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.e(TAG, "item " + position + " clicked.");
}
});
Result in logcat:
05-09 10:22:25.228: E/AddFriendsFragment(20296): item 109 clicked.
05-09 10:22:34.453: E/*** AddFriendsAdapter ***(20296): Item: 0
Any suggestion would be appreciated. Thanks
Because the convertView and holder will be recycled to use, move your setOnClickListener out of the if else statement:
if (convertView == null) {
convertView = myInflater.inflate(R.layout.list_add_friends_row, null);
holder = new ViewHolder();
Typeface font = Typeface.createFromAsset(context.getAssets(), "fonts/ITCAvantGardeStd-Demi.ttf");
holder.tvUserName = (TextView) convertView.findViewById(R.id.tvUserName);
holder.tvUserName.setTypeface(font);
holder.ivPicture = (ImageView) convertView.findViewById(R.id.ivPicture);
holder.btnAdd = (Button) convertView.findViewById(R.id.btnAdd);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.btnAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
Log.e(TAG, "Item: " + position);
listener.OnAddUserClicked(userList.get(position));
}
});
It is not the best solution for that,because there will be some performance issue. I suggest you create a Map for your view and create a new view for your item then just use the relative view for each view.
I think it will be a better solution with best performance:
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = myInflater.inflate(R.layout.list_add_friends_row, null);
holder = new ViewHolder();
Typeface font = Typeface.createFromAsset(context.getAssets(), "fonts/ITCAvantGardeStd-Demi.ttf");
holder.tvUserName = (TextView) convertView.findViewById(R.id.tvUserName);
holder.tvUserName.setTypeface(font);
holder.ivPicture = (ImageView) convertView.findViewById(R.id.ivPicture);
holder.btnAdd = (Button) convertView.findViewById(R.id.btnAdd);
holder.btnAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Integer pos = (Integer)v.getTag();
Log.e(TAG, "Item: " + pos);
listener.OnAddUserClicked(userList.get(pos));
}
});
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tvUserName.setText(userList.get(position).getName());
imageDownloader.displayImage(holder.ivPicture, userList.get(position).getPhotoUrl());
holder.btnAdd.setTag(position);
return convertView;
}
You can also manage your view by yourself. Create every unique view for your item, don't recycle view.
//member various
private Map<Integer, View> myViews = new HashMap<Integer, View>();
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View view = myViews.get(position);
if (view == null) {
view = myInflater.inflate(R.layout.list_add_friends_row, null);
//don't need use the holder anymore.
Typeface font = Typeface.createFromAsset(context.getAssets(), "fonts/ITCAvantGardeStd-Demi.ttf");
holder.tvUserName = (TextView) convertView.findViewById(R.id.tvUserName);
holder.tvUserName.setTypeface(font);
holder.ivPicture = (ImageView) convertView.findViewById(R.id.ivPicture);
holder.btnAdd = (Button) convertView.findViewById(R.id.btnAdd);
holder.btnAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Integer pos = (Integer)v.getTag();
Log.e(TAG, "Item: " + pos);
listener.OnAddUserClicked(userList.get(pos));
}
});
holder.tvUserName.setText(userList.get(position).getName());
imageDownloader.displayImage(holder.ivPicture,
userList.get(position).getPhotoUrl());
myViews.put(position, view);
}
return view;
}
Did you tried doing something like this:
holder.btnAdd.setTag(Integer.valueOf(position));
And then retrieve wich row was clicked in the callback for the button, like this:
public void btnAddClickListener(View view)
{
position = (Integer)view.getTag();
Foo foo = (Foo)foos_adapter.getItem(position); //get data of row(position)
//do some
}
Another approach I found useful (if you are using the ViewHolder pattern of course) is to set the index on a separate attribute whenever getView() is called, then inside your onClickListener you just have to reference your holder's position attribute, something like this:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if(convertView == null){
convertView = View.inflate(mContext, R.layout.contact_picker_row,null);
holder = new ViewHolder();
holder.body = (RelativeLayout)convertView.findViewById(R.id.numberBody);
convertView.setTag(holder);
}else{
holder = (ViewHolder)convertView.getTag();
}
holder.position = position;
holder.body.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(mContext,"Clicked on: "+holder.position,Toast.LENGTH_LONG).show();
}
});
return convertView;
}
private class ViewHolder{
RelativeLayout body;
int position;
}