这是我的数组适配器。它为列表中的每个开关按钮分配一个侦听器,该侦听器依赖于数据库给出的id(使用devices.id
传递)。但由于某种原因,交换机监听器表现得很奇怪。
出于调试目的,无论状态如何,我只是在更改侦听器上使用相同的内容。因此,无论我将其打开还是关闭,它都会运行相同的功能。
我的问题有时候我打开第一个开关,第7个开关打开,当我打开第2个开关时n,第8个开关打开。我正在做错事,但我真的没弄明白。第6,第7和第8个开关无法正常工作。
你可以在液晶显示屏上看到,当我按顺序打开开关时,它必须给我输出“12345678”。但事实并非如此。相反,它给出“12345112”。
编辑:Emil Adz给出的答案有效。给我输出“12345678”。但我有一个问题。如果我打开开关1,向下滚动直到看不见并向上滚动,开关重置为OFF。为什么会这样?
public class DevListAdapter extends ArrayAdapter<Devices>{
Context context;
int layoutResourceId;
Devices data[] = null;
private TextView txt = null;
public DevListAdapter(Context context, int layoutResourceId, Devices[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.d("WCAM","GetView");
View row = convertView;
DeviceHolder holder = null;
Devices devices = data[position];
String id = devices.id;
Log.d("WCAM","Inflator");
if(row == null)
{
Log.d("WCAM","True");
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new DeviceHolder();
holder.devTxt = (TextView)row.findViewById(R.id.devdesc);
holder.nameTxt = (TextView)row.findViewById(R.id.devname);
holder.toggleSwitch = (Switch)row.findViewById(R.id.toggleswitch);
holder.txt = (TextView) row.findViewById(R.id.debug);
final int i;
if(id.matches("1")) {
i = 0x31;
}
else if(id.matches("2")) {
i = 0x32;
}
else if(id.matches("3")) {
i = 0x33;
}
else if(id.matches("4")) {
i = 0x34;
}
else if(id.matches("5")) {
i = 0x35;
}
else if(id.matches("6")) {
i = 0x36;
}
else if(id.matches("7")) {
i = 0x37;
}
else {
i = 0x38;
}
holder.toggleSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Control._service.write(i);
}
});
row.setTag(holder);
}
else
{
Log.d("WCAM","False");
holder = (DeviceHolder)row.getTag();
}
holder.devTxt.setText(devices.dev);
holder.nameTxt.setText(devices.name);
holder.txt.setText(id);
return row;
}
static class DeviceHolder
{
TextView devTxt;
TextView txt;
TextView nameTxt;
Switch toggleSwitch;
}
}
devices是Devices.java的对象
public class Devices {
public String dev;
public String name;
public String id;
public Devices(){
super();
}
public Devices(String _id, String dev, String name) {
super();
this.dev = dev;
this.name = name;
this.id = _id;
}
}
答案 0 :(得分:1)
试试这样:
public class DevListAdapter extends ArrayAdapter<Devices>{
Context context;
int layoutResourceId;
Devices data[] = null;
private TextView txt = null;
public DevListAdapter(Context context, int layoutResourceId, Devices[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.d("WCAM","GetView");
DeviceHolder holder = null;
Devices devices = data[position];
String id = devices.id;
Log.d("WCAM","Inflator");
Log.d("WCAM","True");
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new DeviceHolder();
holder.devTxt = (TextView)row.findViewById(R.id.devdesc);
holder.nameTxt = (TextView)row.findViewById(R.id.devname);
holder.toggleSwitch = (Switch)row.findViewById(R.id.toggleswitch);
holder.txt = (TextView) row.findViewById(R.id.debug);
final int i;
if(id.matches("1")) {
i = 0x31;
}
else if(id.matches("2")) {
i = 0x32;
}
else if(id.matches("3")) {
i = 0x33;
}
else if(id.matches("4")) {
i = 0x34;
}
else if(id.matches("5")) {
i = 0x35;
}
else if(id.matches("6")) {
i = 0x36;
}
else if(id.matches("7")) {
i = 0x37;
}
else {
i = 0x38;
}
holder.toggleSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Control._service.write(i);
}
});
holder.devTxt.setText(devices.dev);
holder.nameTxt.setText(devices.name);
holder.txt.setText(id);
return row;
}
基本上由于某些原因我多次遇到这个问题。当您使用convertView
时,所有列表都会变得疯狂。请注意它可以获得性能,但我没有找到适合此问题的解决方案。当列表不那么大时,它不会发生太大变化。
<强>更新强> 首先看一下本指南:
与复选框状态一样,您将看到:
//setting data into the the ViewHolder.
holder.title.setText(RowData.getName());
holder.checked.setChecked(RowData.isChecked());
//return the row view.
return convertView;
所以在你的情况下,在这段代码之后:
holder.devTxt.setText(devices.dev);
holder.nameTxt.setText(devices.name);
holder.txt.setText(id);
你应该添加如下内容:
holder.toggleSwitch.setChecked(devices.isChecked());
并且在onCheckedChanged
中,状态会发生变化。
答案 1 :(得分:1)
我的切换视图遇到了同样的问题。经过大量的搜索和阅读,我发现这个问题是Android推出的一种优化视图的结果。它尝试重用视图对象。这确实有效,但如果你不注意,或者只是不知道行为(像我一样),就会发生一些非常奇怪的结果。
无论如何,我找到了这个简单的解决方案:
将我的观点存储在ViewHolder中并编写onCheckedChanged事件,就像你一样。诀窍是,在设置之前,如果检查了交换机并定义了CheckedChange监听器,我只需用null重置回调,这可以确保不触发另一个交换机的事件。
以下是摘录:
...
viewHolder.switchView.setOnCheckedChangeListener(null);
viewHolder.switchView.setChecked(myObject.getStatus() > 0);
...
viewHolder.switchView.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
...
}
});
myObject是存储Cursor数据的最终对象。
无论是否检查开关,都必须调用setChecked方法。
希望它有所帮助!
答案 2 :(得分:0)
您的ListView当前正在将行的状态与行的位置相关联,而不是与行的实际内容相关联。当用户滚动ListView,并且它的内容被回收时,它会根据位置输入切换值。
要解决此问题,您需要以与实际行关联的方式保存交换机的状态。 Android: Problem With ListViews and CheckBoxes处理完全相同的问题,但使用复选框。它对于解决这些问题非常有用