我的Activity中有一个ListView,每行使用我的自定义布局和TextView以及两个按钮。当我单击这两个按钮中的任何一个时,我想要执行某个操作。在我的ArrayAdapter中,在getView方法中,我将onClickListeners设置为这两个按钮。
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
v = li.inflate(R.layout.process_row, null);
}
final Button processCheck = (Button) v.findViewById(R.id.processCheck);
processCheck.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (process.isChecked() == false) {
process.setChecked(true);
processCheck.setBackgroundColor(Color.BLUE);
}
else {
process.setChecked(false);
processCheck.setBackgroundColor(Color.RED);
}
}
});
return v;
}
ArrayList保存mz自定义类进程的对象,代码中的进程是此类的一个实例。所以现在当我在其中一个ListView行中单击此按钮时,我希望更改给定Process实例中的boolean变量并更改按钮的颜色。这种情况发生了,但不仅仅是这一行,还有3-4行。所以点击后,我有5个更改按钮而不是一个。你知道我在这里做错了什么吗?请注意,我不太了解ListActivity编码,大多数代码实际上是从示例文件中复制和编辑的。谢谢!
编辑:
问题可能只出在某个地方。当我单击按钮时,更多的颜色会改变颜色,但只有我点击的进程才会更改其布尔值。
答案 0 :(得分:0)
问题在这里
View v = convertView;
if (v == null) {
v = li.inflate(R.layout.process_row, null);
}
这是因为View v仅为可见项创建,然后重复使用。所以只需删除ifv == null)所以你的代码将是
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
v = li.inflate(R.layout.process_row, null);
final Button processCheck = (Button) v.findViewById(R.id.processCheck);
processCheck.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (process.isChecked() == false) {
process.setChecked(true);
processCheck.setBackgroundColor(Color.BLUE);
}
else {
process.setChecked(false);
processCheck.setBackgroundColor(Color.RED);
}
}
});
return v;
}
答案 1 :(得分:0)
每次呈现列表时都会调用getView。所以你应该添加你的gerview条件来设置颜色:public View getView(int position,View convertView,ViewGroup parent){
View v = convertView;
v = li.inflate(R.layout.process_row, null);
//在下面添加这些行
if(process.isChecked()== false){
processCheck.setBackgroundColor(Color.BLUE);
}
else {
processCheck.setBackgroundColor(Color.RED);
}
final Button processCheck = (Button) v.findViewById(R.id.processCheck);
processCheck.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (process.isChecked() == false) {
process.setChecked(true);
processCheck.setBackgroundColor(Color.BLUE);
}
else {
process.setChecked(false);
processCheck.setBackgroundColor(Color.RED);
}
}
});
return v;
}
答案 2 :(得分:0)
编辑:在帖子末尾找到“开箱即用”的示例!
因为您看到多行受到影响,我想它有一些事情要做,系统如何回收资源,可能对Button
的引用不明确。
我不确定我在哪里学习这个练习(Android教程或我们以前通过这些教程学习android的开发人员)。但建议使用嵌套类ViewHolder
private static class ViewHolder {
public Button processCheck;
}
将它放在适配器或您声明getView()
的任何类中,并将其修改为:
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
$ViewHolder viewHolder; //wait for the magic!
if (v == null) {
v = li.inflate(R.layout.process_row, null);
$viewHolder = new ViewHolder();
$viewHolder.processCheck = (Button) v.findViewById(R.id.processCheck);
$v.setTag(viewHolder);
//ok we somewhat stuffed an object with the Button into our View... so what?
}
$viewHolder = (ViewHolder) v.getTag();
//see explanation below
$viewHolder.processCheck.setOnClickListener(new View.OnClickListener() {
//set the onClickListener for this and only this button.
@Override
public void onClick(View v) {
if (process.isChecked() == false) {
process.setChecked(true);
processCheck.setBackgroundColor(Color.BLUE);
}
else {
process.setChecked(false);
processCheck.setBackgroundColor(Color.RED);
}
}
});
return v;
}
(我用$标记了更改。我认为如果我使用eclipse,他们应该很容易发现。否则查找+替换^^)
因此getTag()将返回与被调用视图关联的Object。对象是如此令人难以置信的通用,您可以将其称为您创建的ViewHolder对象。因此,您可以引用该按钮并将其存储在对象中
现在,无论何时获得ListView,您都可以检索对象并设置OnclickListener
新鲜和新的。这样你就只能调用一个监听器。
请注意,您无需再次致电v.setTag();
以“保存”您的更改。
如果你做了一些疯狂的事情,比如在同一个列表中为不同的布局加注出于什么原因。您可能想要为它们分配不同的ViewHandlers
,如:
if (v == null) {
if( someCriteria) {
v = li.inflate(R.layout.process_row, null);
viewHolder = new ViewHolder();
}
v = li.inflate(R.layout.process_another_row, null);
viewHolder = new AnotherViewHolder();
}
然后,对一个ViewHolder或其他ViewHolder进行未经检查的getView()
调用可能会在运行时抛出错误!
答案 3 :(得分:0)
这就是我解决它的方法:
在我的适配器中,我创建了类:
private static class ViewHolder {
public Button processCheck;
public Process process;
public TextView name;
}
比我为我的按钮创建了一个自定义监听器:
private class CustomListener implements View.OnClickListener {
public ViewHolder viewHolder;
public CustomListener(ViewHolder holder) {
this.viewHolder = holder;
}
@Override
public void onClick( View v ) {
if (viewHolder.process.isChecked()) {
viewHolder.name.setText("not checked");
viewHolder.process.setChecked(false);
}
else {
viewHolder.name.setText("checked");
viewHolder.process.setChecked(true);
}
}
}
我的getView功能:
public View getView( int position, View convertView, ViewGroup parent ) {
ViewHolder viewHolder;
if ( convertView == null ) {
convertView = mInflater.inflate( R.layout.process_row, null );
viewHolder = new ViewHolder();
viewHolder.processCheck = (Button) convertView.findViewById(R.id.processCheck);
viewHolder.name = (TextView) convertView.findViewById(R.id.processName);
convertView.setTag( viewHolder );
}
viewHolder = (ViewHolder) convertView.getTag();
viewHolder.process = list.get(position);
if (viewHolder.process.isChecked()) {
viewHolder.name.setText("checked");
}
else {
viewHolder.name.setText("not checked");
}
CustomListener listener = new CustomListener( viewHolder );
viewHolder.processCheck.setOnClickListener(listener);
return convertView;
}