我的应用活动显示通过自定义实现填充的列表视图 一个BaseAdapter。项目由progressBar和CheckBox组成。
progressBars值由后台线程通过使用调用BaseAdapter.notifyDataSetChanged()的Handler更新。 在这个应用程序中,用户应该能够检查复选框。
问题是似乎notifyDataSetChanged()隐藏或忽略用户对CheckBox的点击。 会发生的是onClickListener.onClick()被称为用户点击的1/5倍。
一开始,我认为BaseAdapter.getView()设置的值会覆盖用户点击CheckBox所设置的任何值。所以我在getView()中尝试过类似的东西:
if (checkBox.isChecked != data.isChecked(){
checkBox.setOnCheckedChangeListener(null);
checkBox.setChecked(data.isChecked());
checkBox.setOnCheckedChangeListener(cbClickListener);
}
没有任何变化,在onClickListener.onClick()中添加日志已经清楚地表明每次都不会调用onClick。 我该怎么办?
这是非常经典的适配器代码:
class InputsConfAdapter extends BaseAdapter {
private static LayoutInflater inflater = null;
private final Model model;
private final inputsConfAdapterInterface handler;
private int[] positions;
//---------------------------------------------------------------------------------------------------
class CbClickListener implements CheckBox.OnCheckedChangeListener{
int inputId;
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
handler.setFailSafe((byte) inputId, isChecked);
}
}
//---------------------------------------------------------------------------------------------------
public InputsConfAdapter(LayoutInflater inflater, Model model, inputsConfAdapterInterface handler) {
super();
InputsConfAdapter.inflater = inflater;
this.handler = handler;
this.model = model;
}
@Override
public int getCount() {
return model.inputs.length;
}
@Override
public Object getItem(int i) {
return i;
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
if (view == null) {
view = inflater.inflate(R.layout.theIem, null);
ViewHolder viewHolder = new ViewHolder();
viewHolder.pbPosition = (ProgressBar) view.findViewById(R.id.pbPosition);
viewHolder.checkBox = (CheckBox) view.findViewById(R.id.cb);
final CbClickListener cbClickListener = new CbClickListener();
viewHolder.checkBox.setOnCheckedChangeListener(cbClickListener);
viewHolder.cbClickListener = new CbClickListener();
view.setTag(viewHolder);
}
final ViewHolder viewHolder = (ViewHolder) view.getTag();
final CheckBox checkBox = viewHolder.checkBox;
final ProgressBar pbPosition = viewHolder.pbPosition;
final CbClickListener cbClickListener = viewHolder.cbClickListener;
final Input data = model.inputs[i];
//--- progressBar
if (positions != null)
pbPosition.setProgress(positions[i]);
//--- checkBox
cbClickListener.inputId = i;
checkBox.setOnCheckedChangeListener(null);
checkBox.setChecked(data.isChecked());
checkBox.setOnCheckedChangeListener(cbClickListener);
return view;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public int getViewTypeCount() {
return 1;
}
public void serPositions(int[] positions) {
this.positions = positions;
}
private class ViewHolder {
public CheckBox checkBox;
public ProgressBar pbPosition;
CbClickListener cbClickListener;
public ViewHolder() {
}
}
public interface inputsConfAdapterInterface {
void setFailSafe(byte inputId, boolean value);
}
}
@Khaled的更新:在接收listView的片段中。 有一个“同步器”:
private final Synchronizer synchronizer = new Synchronizer(new Handler(), new DefaultListener() {
@Override
public void ValuesReceived(ValueStruct values) {
if (getActivity() != null) {
adapter.serPositions(values.values);
adapter.notifyDataSetChanged();
}
}
});
updater线程调用synchronizer.valuesReceived(),它发布了一个runnable 在gui线程中实现的Handler:
public interface ISink {
void ValueReceived(
ValueStruct inputValue
);
}
public class defaultListener implements ISink {
}
public class Synchronizer implements ISink {
private ISink sink;
private Handler handler;
public Synchronizer(Handler handler, ISink sink) {
this.handler = handler;
this.sink = sink;
}
private class ValueRunnable implements Runnable {
ValueStruct s;
ValueRunnable(ValueStruct s) {
this.s = new ValueStruct(s);
}
@Override
public void run() {
sink.ValuesReceived(s);
}
}
@Override
public void ValuesReceived(ValueStruct s) {
handler.post(new ValueRunnable(s));
}
}
答案 0 :(得分:0)
您可能正在点击列表项而不是复选框。要解决此问题 使复选框在xml中无法点击并处理检查点击整个项目。
答案 1 :(得分:0)
我认为您应该考虑使用OnCheckedChangeListener
代替OnClickListener
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
handler.setFailSafe((byte) inputId, isChecked);
}
});
答案 2 :(得分:0)
这是我为解决这个问题所做的工作。它不是很令人满意,但它确实有效。 我们的想法是使用notifyDataSetChanged()来手动更新每个进度条。
在adapater中,我添加了一个ArrayList来存储progressbars。 在此结束时:
public View getView(int i, View view, ViewGroup viewGroup) {
if (view == null) {
我添加了
bars.add(viewHolder.pbPosition);
为了使每个progressBar在
结尾处知道与之相关的项目 @Override
public View getView(int i, View view, ViewGroup viewGroup) {
我添加了
pbPosition.setTag(i);
我删除了对adapter.notifyDataSetChanged();
的调用我将setPositions(...)更改为
public void serPositions(int[] positions) {
for (ProgressBar bar :
bars) {
int index = (int) bar.getTag();
bar.setProgress(positions[index]);
}
}