How I implement a view holder in an activity - android

How I implement a view holder?
private class ViewHolder {
TextView code, txtv;
CheckBox name;
Button btnnn;
}
#Override
public View getView(final int position, View convertView,
ViewGroup parent) {
ViewHolder holder = null;
Log.v("ConvertView", String.valueOf(position));
if (convertView == null) {
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.abb_list, null);
holder = new ViewHolder();
holder.code = (TextView) convertView.findViewById(R.id.code);
holder.name = (CheckBox) convertView
.findViewById(R.id.checkBox1);
holder.btnnn = (Button) convertView.findViewById(R.id.btn);
holder.txtv = (TextView) convertView.findViewById(R.id.txt);
convertView.setTag(holder);
holder.name.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
CheckBox cb = (CheckBox) v;
checkTable country = (checkTable) cb.getTag();
country.setSelected(cb.isChecked());
}
});
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.btnnn.setOnClickListener(new OnClickListener() {
int counter = 0;
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
counter++;
holder.txtv.setText(String.valueOf(counter));
}
});
checkTable checkTable = itemsList.get(position);
holder.code.setText(" (" + checkTable.getitemprice() + ")");
holder.name.setText(checkTable.getitemname());
holder.name.setChecked(checkTable.isSelected());
holder.name.setTag(checkTable);
return convertView;
}
}
when i'm doing holder.txtv.setText(String.valueOf(counter)); so it show me an error Cannot refer to the non-final local variable holder defined in an enclosing scope suggest me how I solve this issue.

You could use a final TextView for the Listener:
final TextView counterTxt = holder.txtv;
holder.btnnn.setOnClickListener(new OnClickListener() {
int counter = 0;
#Override
public void onClick(View v) {
counter++;
counterTxt.setText(String.valueOf(counter));
}
});

Declare a few variables outside the method, as private variables:
private TextView counterTx;
private int counter;
private ViewHolder holder;
EDIT: I believe this would be a better implementation that declaring these variables as final, as you would not be able to change their values afterwards.

I recommend you moving findViewById and View.OnClickListener to ViewHolder. Also keep a checkTable reference inside it. This will make the code cleaner.
This kind of style is learned from RecylerView.ViewHolder. RecylerView aims to replace ListView and should be used in the future projects.
#Override
public View getView(final int position, View convertView,
ViewGroup parent) {
ViewHolder holder = null;
Log.v("ConvertView", String.valueOf(position));
if (convertView == null) {
LayoutInflater vi = LayoutInflater.from(parent.getContext());
convertView = vi.inflate(R.layout.abb_list, parent, false);
holder = new ViewHolder(convertView);
} else {
holder = (ViewHolder) convertView.getTag();
}
checkTable checkTable = itemsList.get(position);
holder.country = checkTable;
holder.code.setText(" (" + checkTable.getitemprice() + ")");
holder.name.setText(checkTable.getitemname());
holder.name.setChecked(checkTable.isSelected());
return convertView;
}
// Try to use static inner class as possible as you can, this will eliminate
// many strange issues.
private static class ViewHolder implments View.OnClickListener {
checkTable country;
TextView code, txtv;
CheckBox name;
Button btnnn;
public ViewHolder(View view) {
view.setTag(this);
code = (TextView) convertView.findViewById(R.id.code);
name = (CheckBox) convertView.findViewById(R.id.checkBox1);
btnnn = (Button) convertView.findViewById(R.id.btn);
txtv = (TextView) convertView.findViewById(R.id.txt);
name.setOnClickListener(this);
btnnn.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (v == btnnn) {
// ViewHolder will be reused, you better move counter to checkTable
checkTable.counter++;
txtv.setText(String.valueOf(checkTable.counter));
} else if (v == name) {
country.setSelected(name.isChecked());
}
}
}

Related

Confusion with getview android imagebuttons

I have a listview which has two image buttons in the row. Tapping image button change the background color. When I tap on the first list item, image button background change and the view is saved but scrolling bottom of the listview, background color of image button of another list item changes as well. Below is the getView of Custom Adapter. How can I avoid this problem?
public View getView(final int i, View view, ViewGroup viewGroup) {
ViewHolder holder = new ViewHolder();
holder = null;
//view=null;
if (inflater == null) {
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
if (view == null) {
view = inflater.inflate(R.layout.student_list, null);
holder = new ViewHolder();
holder.presentButton = (ImageButton) view.findViewById(R.id.imageView);
holder.absentButton = (ImageButton) view.findViewById(R.id.imageView2);
holder.presentButton.setBackgroundColor(0);
holder.absentButton.setBackgroundColor(0);
view.setTag(holder);
}
else {
holder = (ViewHolder) view.getTag();
}
final SQLiteStudents db1 = new SQLiteStudents(activity.getApplicationContext());
final TextView tvName = (TextView) view.findViewById(R.id.tv_name);
final TextView tvRoll = (TextView) view.findViewById(R.id.tv_roll);
final studentInfo s = students.get(i);
tvRoll.setText(s.getRoll() + ".");
tvName.setText(s.getName());
final Integer roll = Integer.parseInt(s.getRoll());
//ivpresent.setBackgroundColor(0);
final ViewHolder finalHolder1 = holder;
//final ViewHolder finalHolder = holder;
holder.presentButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
db1.updateUser(roll,"present");
finalHolder1.presentButton.setBackgroundColor(GREEN);
finalHolder1.absentButton.setBackgroundColor(0);
//v1.setTag(v.getTag());
//Log.d("present","Roll No: "+String.valueOf(roll));
finalHolder1.presentButton.setTag(Integer.toString(i));
notifyDataSetChanged();
}
});
holder.absentButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
db1.updateUser(roll,"absent");
finalHolder1.presentButton.setBackgroundColor(0);
finalHolder1.absentButton.setBackgroundColor(RED);
//view=null;
//Log.d("absent","Roll No: "+String.valueOf(roll));
finalHolder1.presentButton.setTag(Integer.toString(i));
notifyDataSetChanged();
}
});
return view;
}
public static class ViewHolder {
public ImageButton presentButton;
public ImageButton absentButton;
}
public class CustomListAdapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
private List<studentInfo> students;
private boolean presentButton = false;
private boolean absentButton = false;
You need to add an else accordingly in your code, see below:
public View getView(final int i, View view, ViewGroup viewGroup) {
ViewHolder holder = new ViewHolder();
holder = null;
//view=null;
if (inflater == null) {
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
if (view == null) {
view = inflater.inflate(R.layout.student_list, null);
holder = new ViewHolder();
holder.presentButton = (ImageButton) view.findViewById(R.id.imageView);
holder.absentButton = (ImageButton) view.findViewById(R.id.imageView2);
holder.presentButton.setBackgroundColor(0);
holder.absentButton.setBackgroundColor(0);
view.setTag(holder);
}
else {
holder = (ViewHolder) view.getTag();
}
final SQLiteStudents db1 = new SQLiteStudents(activity.getApplicationContext());
final TextView tvName = (TextView) view.findViewById(R.id.tv_name);
final TextView tvRoll = (TextView) view.findViewById(R.id.tv_roll);
final studentInfo s = students.get(i);
tvRoll.setText(s.getRoll() + ".");
tvName.setText(s.getName());
final Integer roll = Integer.parseInt(s.getRoll());
//ivpresent.setBackgroundColor(0);
final ViewHolder finalHolder1 = holder;
//final ViewHolder finalHolder = holder;
holder.presentButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
db1.updateUser(roll,"present");
presentButton = true;
}
});
holder.absentButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
db1.updateUser(roll,"absent");
absentButton = true;
}
});
if(presentButton){
finalHolder1.presentButton.setBackgroundColor(GREEN);
finalHolder1.absentButton.setBackgroundColor(0);
//v1.setTag(v.getTag());
//Log.d("present","Roll No: "+String.valueOf(roll));
finalHolder1.presentButton.setTag(Integer.toString(i));
notifyDataSetChanged();
} else {
//set button to some default button like black
}
if(absentButton){
finalHolder1.presentButton.setBackgroundColor(0);
finalHolder1.absentButton.setBackgroundColor(RED);
//view=null;
//Log.d("absent","Roll No: "+String.valueOf(roll));
finalHolder1.presentButton.setTag(Integer.toString(i));
notifyDataSetChanged();
} else {
//set button to some default button like black
}
return view;
}

ListView with Button, Using ViewHolder within OnClick

I am attempting to create a list of buttons paired with text. Whenever a button in the list is clicked, I want to increment the integer value in the associated text view. My plan was to use the following code, but I'm having an error using viewHolder within the OnClickListener because viewHolder is not final, and it can't be in order to manipulate it within the onClick. How can I modify the associated text value?
public View getView(final int position, View convertView, ViewGroup parent){
ViewHolder viewHolder = null;
if (convertView == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
convertView = inflater.inflate(R.layout.row, null);
viewHolder = new ViewHolder();
viewHolder.text = (TextView) convertView.findViewById(R.id.playerScore);
viewHolder.button = (Button) convertView.findViewById(R.id.playerButton);
viewHolder.button.setOnClickListener(new View.OnClickListener() {
protected String scoreToSet;
#Override
public void onClick(View v) {
viewHolder.text.setText(Integer.toString(modelList.get(position).getScore() + 1)); //Error is occurring here
}
});
convertView.setTag(viewHolder);
}
else{
viewHolder = (ViewHolder) convertView.getTag();
viewHolder.button.setText(modelList.get(position).getPlayer());
}
return convertView;
}
Thanks for the help!
Change the code like this ,
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder ;
if (convertView == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
convertView = inflater.inflate(R.layout.row, null);
viewHolder = new ViewHolder();
viewHolder.text = (TextView) convertView.findViewById(R.id.playerScore);
viewHolder.button = (Button) convertView.findViewById(R.id.playerButton);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
viewHolder.button.setText(modelList.get(position).getPlayer());
}
viewHolder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//TODO UPDATE the model here
int newScore = modelList.get(position).getScore() + 1;
modelList.get(position).setScore(newScore);
viewHolder.text.setText(Integer.toString(newScore);
}
});
return convertView;
}
You should add listeners or set values to your views outside if-else blocks -
public View getView(final int position, View convertView, ViewGroup parent){
ViewHolder viewHolder = null;
if (convertView == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
convertView = inflater.inflate(R.layout.row, null);
viewHolder = new ViewHolder();
viewHolder.text = (TextView) convertView.findViewById(R.id.playerScore);
viewHolder.button = (Button) convertView.findViewById(R.id.playerButton);
convertView.setTag(viewHolder);
}
else{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.button.setText(modelList.get(position).getPlayer());
viewHolder.button.setOnClickListener(new View.OnClickListener() {
protected String scoreToSet;
#Override
public void onClick(View v) {
setValue(position);
}
});
return convertView;
}
Declare setValue() -
public void setValue(int position){
ViewHolder.text.setText(Integer.toString(modelList.get(position).getScore() + 1));
}

set onClickListener in getview() with ViewHolder class

I have a custom list adapter that extends BaseAdapter.
I create a holder class to tag my views in order to avoid inflating views that already exist.
static class ViewHolder{
TextView tvName;
TextView tvDescription;
Button btAdd;
}
and in my getView i have somthing like this:
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
ViewHolder holder = null;
if(vi == null){
vi = inflater.inflate(R.layout.list_row, null);
holder = new ViewHolder();
holder.tvName = (TextView)vi.findViewvById(R.id.name);
holder.tvDescription = (TextView)vi.findViewvById(R.id.desc);
holder.btAdd = (Button)vi.findViewvById(R.id.btnadd);
}else{
holder = (ViewHolder) vi.getTag();
}
holder.btnAdd.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
holder.btnAdd.startAnimation(scale);
holder.tvName.setVisibility(View.GONE);
}
});
return vi;
}
But eclipse get error from "holder.btnAdd.startAnimation(scale);" and says holder should be final......
How can I fix it?
You should get the view with the onClick method as follows:
holder.btnAdd.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
v.startAnimation(scale);
}
});
You pass the View v parameter in your onClick method. Then, your method is attached to the View which is in your case: holder.btnAdd, therefore v == holder.btnAdd
Update
It's a bit stupid what I did to resolve this. This is really easy, indeed you initialize viewHolder as null but you shouldn't. That's why you can't make your viewHolder as final:
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
final ViewHolder holder; // without initialized
if(vi == null){
vi = inflater.inflate(R.layout.list_row, null);
holder = new ViewHolder();
holder.tvName = (TextView)vi.findViewvById(R.id.name);
holder.tvDescription = (TextView)vi.findViewvById(R.id.desc);
holder.btAdd = (Button)vi.findViewvById(R.id.btnadd);
}else{
holder = (ViewHolder) vi.getTag();
}
holder.btnAdd.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
v.startAnimation(scale);
holder.tvName.setVisibility(View.GONE);
}
});
return vi;
}
That's it!
Based on this article https://scottweber.com/2013/04/30/adding-click-listeners-to-views-in-adapters/
You shouldn't make listener every time you call getView
Instead use just once
#Override public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder;
if (convertView == null) {
convertView =
LayoutInflater.from(getContext()).inflate(R.layout.row_simple, parent,
false);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.text);
holder.button = (Button) convertView.findViewById(R.id.button);
holder.button.setOnClickListener(mMyButtonClickListener);
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
holder.button.setTag(position);
return convertView; }
private View.OnClickListener mMyButtonClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = (Integer) v.getTag();
Toast.makeText(getContext(), "Row " + position + " was clicked!", Toast.LENGTH_SHORT).show();
} }

Android: OnClick ImageView not change correct Image

I am creating an app where there are images in a custom Listview. The database put a picture or another. Clicking the image has to change. But when I click the image is not changed at the correct ImageView. It changes other ImageView.
I need any help. thanks
public View getView(final int position, View convertView, ViewGroup parent) {
View v = convertView;
final MonumentosHolder holder = new MonumentosHolder();
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.listview_row, null);
TextView tv = (TextView) v.findViewById(R.id.textoListviewNombre);
ImageView img3 = (ImageView) v.findViewById(R.id.imagenVisto);
holder.texto = tv;
holder.imagenVisto = img3;
v.setTag(holder);
}
else {
holder = (MonumentosHolder) v.getTag();
}
holder.position = position;
final MonumentosObj p = monumentosLista.get(position);
holder.texto.setText(p.getNombre());
if (p.getVisto().equals("n")) {
holder.imagenVisto.setImageResource(R.drawable.vistorojo);
} else {
holder.imagenVisto.setImageResource(R.drawable.vistoverde);
}
holder.imagenVisto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MonumentosObj p1 = monumentosLista.get(holder.position);
if (p1.getVisto().equals("s")) {
holder.imagenVisto.setImageResource(R.drawable.vistorojo);
p1.setVisto("n");
} else {
holder.imagenVisto.setImageResource(R.drawable.vistoverde);
p1.setVisto("s");
}
MonumentosAdapter.updateMonumentos(p1);
MonumentosObj p = monumentosLista.get(holder.position);
}
});
imageLoader.displayImage(imageUrls[position], holder.imagen, options, animateFirstListener);
return v;
}
EDIT
Onclick not change the correct image. But when I scroll the listview to below and and return to top, the correct image has changed...
I think that bit of code maybe wrong :
holder.imagenVisto.setOnClickListener(new View.OnClickListener() {
private int pos = position;
#Override
public void onClick(View v) {
MonumentosObj p1 = monumentosLista.get(pos);
Try to store position inside holder object and when assigning it in onClick Listener instead
private int pos = position;
do
private int pos = holder.getPosition()
Remember that android ListViews are not loading all items at one time it just loads thats what is visible and few items beyond that,
Also remember that positions of your items in your Arrays doesn't change you may use it somehow :)
try to change
holder.imagenVisto.setOnClickListener(new View.OnClickListener()
by
holder.imagenVisto.setOnClickListener(new OnClickListener()
I think your click listener affect early items in your list!
do this:
put a long item in your viewHolder:
class MonumentosHolder {
.
.
.
long position;
}
and then in your getView, set the holder positon:
View v = convertView;
--EDITED--
final MonumentosHolder holder = new MonumentosHolder();
--END EDITED--
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.listview_row, null);
TextView tv = (TextView) v.findViewById(R.id.textoListviewNombre);
ImageView img3 = (ImageView) v.findViewById(R.id.imagenVisto);
holder.texto = tv;
holder.imagenVisto = img3;
v.setTag(holder);
}
else {
holder = (MonumentosHolder) v.getTag();
}
**holder.postion = position;**
and then click listener would be like this:
EDITED
holder.imagenVisto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MonumentosObj p1 = monumentosLista.get(**holder.position**);
if (p1.getVisto().equals("s")) {
holder.imagenVisto.setImageResource(R.drawable.vistorojo);
p1.setVisto("n");
} else {
holder.imagenVisto.setImageResource(R.drawable.vistoverde);
p1.setVisto("s");
}
MonumentosAdapter.updateMonumentos(p1);
MonumentosObj p = monumentosLista.get(holder.position);
}
});
EDIT 4
remove the final modifier from holder, define another MonumentosHolder named finalHolder like this:
public View getView(final int position, View convertView, ViewGroup parent) {
View v = convertView;
MonumentosHolder holder = new MonumentosHolder();
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.listview_row, null);
TextView tv = (TextView) v.findViewById(R.id.textoListviewNombre);
ImageView img3 = (ImageView) v.findViewById(R.id.imagenVisto);
holder.texto = tv;
holder.imagenVisto = img3;
v.setTag(holder);
}
else {
holder = (MonumentosHolder) v.getTag();
}
holder.position = position;
final MonumentosObj p = monumentosLista.get(position);
holder.texto.setText(p.getNombre());
if (p.getVisto().equals("n")) {
holder.imagenVisto.setImageResource(R.drawable.vistorojo);
} else {
holder.imagenVisto.setImageResource(R.drawable.vistoverde);
}
final MonumentosHolder finalHolder = holder;
holder.imagenVisto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MonumentosObj p1 = monumentosLista.get(finalHolder.position);
if (p1.getVisto().equals("s")) {
holder.imagenVisto.setImageResource(R.drawable.vistorojo);
p1.setVisto("n");
} else {
holder.imagenVisto.setImageResource(R.drawable.vistoverde);
p1.setVisto("s");
}
MonumentosAdapter.updateMonumentos(p1);
MonumentosObj p = monumentosLista.get(finalHolder.position);
}
});
imageLoader.displayImage(imageUrls[position], holder.imagen, options, animateFirstListener);
return v;
}

Android, List Adapter returns wrong position in getView

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;
}

Categories

Resources