I have a listview, which shows the picture, type/description of car and a checkbox. When the user now selected a car/s, I want to show them in another listview. When he unselected him from the CarListAdapter, it should also disappear from the new listview. Can I realize this with using the same Viewholder?
class CarListAdapter extends BaseAdapter
{
ArrayList<ItemsHolder> holderList;
BitmapHelper bitmapHelper = BitmapHelper.getInstance();
public CarListAdapter(ArrayList<ItemsHolder> holderList)
{
this.holderList = holderList;
}
#Override
public int getCount()
{
return holderList.size();
}
#Override
public Object getItem(int position)
{
return null;
}
#Override
public long getItemId(int position)
{
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
final ViewHolder holder;
if (convertView == null)
{
LayoutInflater inflater = LayoutInflater.from(RentingDataActivity.this);
convertView = inflater.inflate(R.layout.listview_renting_entry, null, true);
holder = new ViewHolder();
holder.rowCarId = (TextView) convertView.findViewById(R.id.rowCarId);
holder.rowImageView = (ImageView) convertView
.findViewById(R.id.rowImageView);
holder.rowCarType = (TextView) convertView.findViewById(R.id.rowCarType);
holder.rowCarDescription = (TextView) convertView
.findViewById(R.id.rowCarDescription);
holder.rowCheckbox = (CheckBox) convertView.findViewById(R.id.rowCheckBox);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
// holder.rowCheckbox.setOnCheckedChangeListener(null);
// holder.rowCheckbox.setTag(R.id.rowCheckBox, position);
}
// auto = holderList.get(position);
final ItemsHolder ih = holderList.get(position);
holder.rowImageView.setImageBitmap(bitmapHelper.getBigImage(ih.getImagePath(), 248));
holder.rowCarType.setText(ih.getCarType());
holder.rowCarDescription.setText(ih.getCarDescription());
// holder.rowCheckbox.setTag(ih);
holder.rowCarId.setText(ih.getCarId());
holder.rowCheckbox.setChecked(ih.isSelected());
holder.rowCheckbox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CheckBox checkbox = (CheckBox)v.findViewById(R.id.rowCheckBox);
// Toast.makeText(getApplicationContext(), holder.rowCarType.getText().toString(),
// Toast.LENGTH_LONG).show();
ih.setSelected(checkbox.isChecked());
}
});
return convertView;
}
}
I would add this as a comment but alas I haven't got enough points:
add to your adapter;
notifyDataSetChanged( );
This refreshes the list asynchronously.
Related
Good day,
I'm doing a listview, baseadapter with checkbox that is able to delete multiple selected rows.
here is my onCreate :
ArrayList<Memos> list;
list = new ArrayList<Memos>();
list.add(new Memos(1, "s", "s"));
list.add(new Memos(2, "x", "aaa"));
list.add(new Memos(3, "v", "aesf"));
final ListView lv = (ListView) findViewById(R.id.myList);
lv.setAdapter(new MemoListAdapter(list, this));
deletebutton
#Override
public void onClick(View v) {
MemoListAdapter myAdapter = (MemoListAdapter)lv.getAdapter();
myAdapter.remove();
}
then here is my complete baseadapter :
public class MemoListAdapter extends BaseAdapter {
private List<Memos> listComment;
private Context context;
private LayoutInflater inflater = null;
private ArrayList<Memos> deleteMemos;
public MemoListAdapter(List<Memos> listComment, Context context) {
super();
this.listComment = listComment;
this.context = context;
inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
deleteMemos = new ArrayList<Memos>();
}
#Override
public int getCount() {
return listComment.size();
}
#Override
public Memos getItem(int position) {
return listComment.get(position);
}
#Override
public long getItemId(int arg0) {
return 0;
}
#Override
public int getViewTypeCount() {
return getCount();
}
#Override
public int getItemViewType(int position) {
return position;
}
public class ViewHolder
{
TextView body;
TextView date;
CheckBox checkBox;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_view, null);
holder = new ViewHolder();
holder.body = (TextView) convertView.findViewById(R.id.big_text);
holder.date = (TextView) convertView.findViewById(R.id.small_text);
holder.checkBox = (CheckBox) convertView.findViewById(R.id.checkbox);
holder.body.setText(listComment.get(position).getMessageBody());
holder.date.setText(listComment.get(position).getMessageDate());
holder.checkBox.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//is chkIos checked?
if(listComment.get(position).isCheckbox()) {
holder.checkBox.setChecked(false);
deleteMemos.remove(listComment.get(position));
}
else {
// Do invisible or gone stuff here
holder.checkBox.setChecked(true);
deleteMemos.add(listComment.get(position));
}
}
});
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
return convertView;
}
public void remove() {
for(Memos memo : deleteMemos) {
listComment.remove(memo);
}
this.notifyDataSetChanged();
}
}
after selecting rows to delete (4 rows)
the list adjusted but the contents and the check value of the checkbox is still the same.
I am wondering what part of the notifyDataSetChanged is wrong.
Thanks in advance!
Your views are reused that's why it happen . Try adding below codes into your getView()
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_view, null);
holder = new ViewHolder();
holder.body = (TextView) convertView.findViewById(R.id.big_text);
holder.date = (TextView) convertView.findViewById(R.id.small_text);
holder.checkBox = (CheckBox) convertView.findViewById(R.id.checkbox);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
if(listComment.get(position).isCheckbox()) {
holder.checkBox.setChecked(true);
}else {
holder.checkBox.setChecked(false);
}
holder.body.setText(listComment.get(position).getMessageBody());
holder.date.setText(listComment.get(position).getMessageDate());
holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
listComment.get(position).setIsCheckbox(isChecked);
if (isChecked){
deleteMemos.add(listComment.get(position));
}else{
deleteMemos.remove(listComment.get(position));
}
}
});
return convertView;
}
I am creating a custom list view with favorite functionality, but I don't know how to change favorite image background on click. When I simply change the background of favorite icon than it automatically change background of another favorite image background at the time of scrolling. Please check below code :
public class CustomArrayAdapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater = null;
ArrayList<Customlist> list;
DecimalFormat formatter = new DecimalFormat("#,##,###");
public CustomArrayAdapter(Activity a, ArrayList<Customlist> list) {
activity = a;
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.list = list;
}
public int getCount() {
return list.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView,
final ViewGroup parent) {
TextView txt_unit, txt_state, txt_price, term_left, customr;
TextView install_date;
final ImageView fav;
View view = convertView;
if (convertView == null)
view = inflater.inflate(R.layout.list_item, null);
customr = (TextView) view.findViewById(R.id.customr);
txt_state = (TextView) view.findViewById(R.id.txt_state);
install_date = (TextView) view.findViewById(R.id.install_date);
term_left = (TextView) view.findViewById(R.id.term_left);
txt_price = (TextView) view.findViewById(R.id.txt_price);
fav = (ImageView) view.findViewById(R.id.fav);
txt_unit = (TextView) view.findViewById(R.id.txt_unit);
fav.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
// fav = (ImageView)v.findViewById(R)
fav.setBackgroundResource(R.drawable.favourite_select);
Toast.makeText(activity, "click", 1).show();
}
});
// set values
customr.setText(list.get(position).getCUSTOMER());
txt_state.setText(list.get(position).getSTATE_NAME());
install_date.setText(list.get(position).getINSTALL_DATE());
term_left.setText(list.get(position).getTREM_LEFT());
String price = formatter.format(Integer.parseInt(list.get(position)
.getRUPEES()));
return view;
}
}
First, you need to implement the adapter on ViewHolder pattern:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHoldler holder = null;
if (convertView == null) {
convertView = LayoutInflater.from(ctx).inflate(
R.layout.frag_home_gridview_item, null, false);
holder = new ViewHoldler();
holder.iv = (ImageView) convertView
.findViewById(R.id.gridview_item_label);
holder.tv = (TextView) convertView
.findViewById(R.id.gridview_item_name);
convertView.setTag(holder);
} else {
holder = (ViewHoldler) convertView.getTag();
}
holder.tv.setText(getItem(position));
holder.iv.setImageResource(this.ids[position]);
return convertView;
}
private class ViewHoldler {
ImageView iv;
TextView tv;
}
Second, use partial refreshment mechanism to change the target View's background:
private void refreshPartially(int position){
int firstVisiblePosition = listview.getFirstVisiblePosition();
int lastVisiblePosition = listview.getLastVisiblePosition();
if(position>=firstVisiblePosition && position<=lastVisiblePosition){
View view = listview.getChildAt(position - firstVisiblePosition);
if(view.getTag() instanceof ViewHolder){
ViewHolder vh = (ViewHolder)view.getTag();
//holder.play.setBackgroundResource(resId);//Do something here.
...
}
}
}
Third, add AdapterView.OnItemClickListener to your ListView:
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
refreshPartially(position);
}
});
You need to implement the adapter on ViewHolder pattern:
http://www.vogella.com/tutorials/AndroidListView/article.html
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);
Well i have a listview populated with BaseAdapter. In listview i have 2 textviews and 2 buttons that i want to be clickable and i did set it class and works fine but problem is when i click one textview, 4th, 8th list item below is clicked too and i just find out that they have same position by printing position with toast.
How can i make that positions go ++ and every of them be uniqe?
Adapter Class
public class CustomListAdapter extends BaseAdapter
{
private ArrayList<FeedItem> listData;
private LayoutInflater layoutInflater;
private Context mContext;
protected ListView feedListView;
public CustomListAdapter(Context context, ArrayList<FeedItem> listData)
{
this.listData = listData;
layoutInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mContext = context;
}
public void addItem(final FeedItem item) {
listData.add(item);
notifyDataSetChanged();
}
#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;
}
public View getView( final int position, View convertView, ViewGroup parent)
{
final ViewHolder holder;
View row=convertView;
if (row == null)
{
convertView = layoutInflater.inflate(R.layout.list_row_layout, null);
holder = new ViewHolder();
holder.headlineView = (TextView)convertView.findViewById(R.id.name);
holder.reportedDateView = (TextView) convertView.findViewById(R.id.confid);
holder.approve = (TextView) convertView.findViewById(R.id.approveTV);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
FeedItem newsItem = (FeedItem) listData.get(position);
holder.approve.setFocusable(true);
holder.approve.setClickable(true);
holder.headlineView.setText(Html.fromHtml(newsItem.getTitle()));
holder.reportedDateView.setText(Html.fromHtml(newsItem.getContent()));
holder.approve.setTag(position);
holder.approve.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v)
{
Toast.makeText(mContext, String.valueOf(v.getTag()), Toast.LENGTH_LONG).show();
holder.approve.setTag(v);
holder.approve.setText("Approved");
}
});
return convertView;
}
static class ViewHolder
{
TextView approve;
TextView headlineView;
TextView reportedDateView;
ImageView imageView;
FeedItem newsItem;
}
}
Listview recycles views.
How ListView's recycling mechanism works
Change getView
public View getView( final int position, View convertView, ViewGroup parent)
{
ViewHolder holder;
if (convertView == null)
{
convertView = layoutInflater.inflate(R.layout.list_row_layout, null);
holder = new ViewHolder();
holder.headlineView = (TextView)convertView.findViewById(R.id.name);
holder.reportedDateView = (TextView) convertView.findViewById(R.id.confid);
holder.approve = (TextView) convertView.findViewById(R.id.approveTV);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
FeedItem newsItem = (FeedItem) listData.get(position);
holder.approve.setFocusable(true);
holder.approve.setClickable(true);
holder.headlineView.setText(Html.fromHtml(newsItem.getTitle()));
holder.reportedDateView.setText(Html.fromHtml(newsItem.getContent()));
holder.approve.setTag(position);
holder.approve.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v)
{
Toast.makeText(mContext, String.valueOf(v.getTag()), Toast.LENGTH_LONG).show();
}
});
return convertView;
}
As you are reusing the view by
else{
holder = (ViewHolder) convertView.getTag();
}
so multiple textView using same listener. So Take your onclickListener outside of the if condition.
if (convertView == null)
{
convertView = layoutInflater.inflate(R.layout.list_row_layout, null);
holder = new ViewHolder();
holder.headlineView = (TextView)convertView.findViewById(R.id.name);
holder.reportedDateView = (TextView) convertView.findViewById(R.id.confid);
holder.approve = (TextView) convertView.findViewById(R.id.approveTV);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.approve.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v)
{
Toast.makeText(mContext, String.valueOf(position), Toast.LENGTH_LONG).show();
}
});
Add this code in your list adapter :
#Override
public int getViewTypeCount() {
// TODO Auto-generated method stub
return questionsClassArrayList_.size();
}
#Override
public int getItemViewType(int position) {
// TODO Auto-generated method stub
return position;
}
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;
}