连续按钮的自定义arrayadapter和onclicklistener
Posted
技术标签:
【中文标题】连续按钮的自定义arrayadapter和onclicklistener【英文标题】:Custom arrayadapter and onclicklistener for a button in a row 【发布时间】:2014-02-05 08:53:19 【问题描述】:我有一个自定义的arrayadapter,我想在它的每一行中为一个按钮添加一个 onclicklistener,当我单击按钮时,我希望更改图像资源,除了单击按钮时,一切正常图像会发生变化,但另一行中另一个按钮的图像也会发生变化。谢谢你的帮助 ! 这是我的代码:
public class Coursadapter extends ArrayAdapter<String>
Context context;
int layoutResourceId;
ArrayList<String> data = null;
WeatherHolder holder;
public Coursadapter(Context context, int layoutResourceId, ArrayList<String> data)
// super(context, layoutResourceId, data, coeff);
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
public View getView(int position, View convertView, ViewGroup parent)
View row = convertView;
if(row == null)
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new WeatherHolder();
holder.name = (TextView)row.findViewById(R.id.item_cours_name);
holder.b=(ImageButton) row.findViewById(R.id.button);
holder.b.setTag(holder);
row.setTag(holder);
else
holder = (WeatherHolder)row.getTag();
holder.b.setOnClickListener(new OnClickListener()
@Override
public void onClick(View v)
// TODO Auto-generated method stub
WeatherHolder w = (WeatherHolder) v.getTag();
w.b.setImageResource(R.drawable.butgreen);
);
String name1 = data.get(position);
holder.name.setText(name1);
return row;
static class WeatherHolder
TextView name;
ImageButton b;
【问题讨论】:
尝试将holder.b.setTag(holder);
移动到 else 部分下方。您的问题是因为 lsitview 回收视图。
你得到解决方案了吗。谢谢
【参考方案1】:
检查代码完成了一些更改
包 com.example.dontpanic;
public class Coursadapter extends ArrayAdapter<String>
Context context;
int layoutResourceId;
ArrayList<String> data = null;
WeatherHolder holder;
public Coursadapter(Context context, int layoutResourceId,
ArrayList<String> data)
// super(context, layoutResourceId, data, coeff);
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
public View getView(int position, View convertView, ViewGroup parent)
View row = convertView;
if (row == null)
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new WeatherHolder();
holder.name = (TextView) row.findViewById(R.id.item_cours_name);
holder.b = (ImageButton) row.findViewById(R.id.button);
holder.b.setOnClickListener(new OnClickListener()
@Override
public void onClick(View v)
// TODO Auto-generated method stub
WeatherHolder w = (WeatherHolder) v.getTag();
w.b.setImageResource(R.drawable.butgreen);
);
row.setTag(holder);
else
holder = (WeatherHolder) row.getTag();
holder.b.setTag(holder);
String name1 = data.get(position);
holder.name.setText(name1);
return row;
static class WeatherHolder
TextView name;
ImageButton b;
将您的点击监听器放在 if 条件中,并在 if else 条件之外设置标签
【讨论】:
很抱歉,我按照你告诉我的方式更新了我的 getview,但我仍然遇到完全相同的问题! 尝试调试你的点击事件并检查你得到了什么。这可能是不同的事情 调试时一切正常,单击按钮时只有一个单击事件,但不知何故另一个按钮也发生了变化 尝试通过更改 row = inflater.inflate(layoutResourceId, parent, false); to row = inflater.inflate(layoutResourceId, null);让我知道 对不起@dinesh sharma,我复制粘贴了你的代码,改变了膨胀表达式,还是同样的问题【参考方案2】:public View getView(int position, View convertView, ViewGroup parent)
if(convertView == null)
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
convertView = inflater.inflate(layoutResourceId, parent, false);
TextView name = (TextView)convertView.findViewById(R.id.item_cours_name);
ImageButton b=(ImageButton) convertView.findViewById(R.id.button);
b.setOnClickListener(new OnClickListener()
@Override
public void onClick(View v)
b.setImageResource(R.drawable.butgreen);
);
String name1 = data.get(position);
name.setText(name1);
return convertView;
【讨论】:
那没用,我照你说的做了,但我仍然有同样的问题 只需将 getView 方法替换为我编辑的内容即可。试一次 我复制/粘贴了您的getview,但它不起作用,同样的问题,当我单击一个按钮时,另一行中的另一个按钮也发生了变化【参考方案3】:您的问题和两个答案都有一个常见的误解。
首先,请确保您了解 ListView 的回收工作原理。比如this post就稍微解释一下这个问题。
关于这个具体案例,我们先来了解一下问题所在。当你点击一个按钮时,图像会改变,一切看起来都很好。但是,如果您滚动,您将在另一个位置获得相同的视图(带有更改图像的按钮)。因为回收。
要解决此问题,您必须维护按钮的图像选择。这不会神奇地发生。您必须添加一些逻辑来告诉此方法应在特定位置显示哪个图像资源。
例如,在您的 getView() 方法中,添加以下(伪)代码:
public View getView(int position, View convertView, ViewGroup parent)
View row = convertView;
if(row == null)
// omitted..
else
holder = (WeatherHolder)row.getTag();
// BUTTON's IMAGE MAINTAINING
if(condition)
w.b.setImageResource(R.drawable.butgreen);
else
w.b.setImageResource(some-other-image-resource);
// omitted..
return row;
【讨论】:
【参考方案4】:发生这种情况的原因是适配器在滚动时回收视图。
例如,假设您总共有 15 行,并且一次有 5 行适合屏幕。 if(row == null)
部分仅对前 5 行执行。当您向下滚动到第 6 行时,它使用第 1 行的视图。这就是为什么你应该在 if-else 子句之后设置 View 的内容。所以现在,当第 6 行进入屏幕时,行不是null
。它拥有第一行的视图。当它执行holder.name.setText(name1);
时,它将第 1 行的名称替换为第 6 行的名称。同样,第 7 行使用第 2 行的视图,依此类推。
现在,假设您单击第一行的按钮。第一行的视图发生变化,w.b.setImageResource(R.drawable.butgreen);
设置第一行按钮的图像资源。当您滚动到第 6 行时,它使用第 1 行的视图。但是您仅将 holder.name
设置为第 6 行的名称。第一行按钮的图像资源将保留在那里,从而导致您的问题。
解决方案:创建另一个ArrayList<String>
并将按钮的状态存储在其中。因此,在您的情况下,我假设按钮的颜色为“红色”或“绿色”。您可以在每个位置存储“红色”或“绿色”,表示每个按钮当前的颜色(您可以将此 ArrayList 初始化为红色)。然后,当每行加载时,您可以设置图像资源以及该行的名称。看看下面的代码。我已将 cmets 添加到我添加的行中。
public class Coursadapter extends ArrayAdapter<String>
Context context;
int layoutResourceId;
ArrayList<String> data = null;
WeatherHolder holder;
ArrayList<String> colors; // Stores the color of each button
public Coursadapter(Context context, int layoutResourceId, ArrayList<String> data)
// super(context, layoutResourceId, data, coeff);
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
this.colors = new ArrayList<>(Collections.nCopies(data.size(), "red")); // initialize all the buttons to red color
public View getView(final int position, View convertView, ViewGroup parent)
View row = convertView;
if(row == null)
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new WeatherHolder();
holder.name = (TextView)row.findViewById(R.id.item_cours_name);
holder.b=(ImageButton) row.findViewById(R.id.button);
holder.b.setTag(holder);
row.setTag(holder);
else
holder = (WeatherHolder)row.getTag();
if(colors.get(position).equals("red"))
holder.b.setImageResource(R.drawable.butred); // set the colors of the button to red or whatever you need
else
holder.b.setImageResource(R.drawable.butgreen); // set the colors of the button to green
holder.b.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
// TODO Auto-generated method stub
WeatherHolder w = (WeatherHolder) v.getTag();
//w.b.setImageResource(R.drawable.butgreen);
colors.set(position, "green"); // update the ArrayList colors
);
String name1 = data.get(position);
holder.name.setText(name1);
return row;
static class WeatherHolder
TextView name;
ImageButton b;
【讨论】:
以上是关于连续按钮的自定义arrayadapter和onclicklistener的主要内容,如果未能解决你的问题,请参考以下文章
ListView 中自定义 ArrayAdapter 的自定义过滤
android中自定义ArrayAdapter中的自定义getFilter