Set onClickListener to getview () with ViewHolder class
I have a custom list adapter that extends BaseAdapter. I am creating a holder class to tag my views to avoid bloating the views that already exist.
static class ViewHolder{
TextView tvName;
TextView tvDescription;
Button btAdd;
}
and in my getView I have something 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 gets error from "holder.btnAdd.startAnimation (scale);" and says that the holder must be final ......
How can I fix this?
source to share
You should get view
using the method onClick
like this:
holder.btnAdd.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
v.startAnimation(scale);
}
});
You are passing a parameter View v
to your method onClick
. Then your method is bound to the view, which is in your case:, holder.btnAdd
sov == holder.btnAdd
Update
It's a bit silly what I did to fix this problem. It's really easy, really, you initialize viewHolder
like null
, but you shouldn't. This is why you cannot make yours viewHolder
like 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;
}
What is it!
source to share
Based on this article https://scottweber.com/2013/04/30/adding-click-listeners-to-views-in-adapters/ You shouldn't start the listener every time you call getView
Instead, use only 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();
} }
source to share