2

使用此可扩展列表复选框示例代码作为基线,我正在尝试保存和维护复选框状态。OnCheckedChangeListener但是,当我将它们滚动到视线之外,最小化它们的组,甚至最小化/最大化附近的组时,随机复选框会被选中和取消选中(触发我的新值)!

public Object getChild(int groupPosition, int childPosition) {
    return colors.get( groupPosition ).get( childPosition );
}

public long getChildId(int groupPosition, int childPosition) {
    return (long)( groupPosition*1024+childPosition );  // Max 1024 children per group
}

public View getChildView(final int groupPosition, final int childPosition, 
        boolean isLastChild, View convertView, ViewGroup parent) {

    View v = null;
    if( convertView != null ) {
        v = convertView;
    } else {
        v = inflater.inflate(R.layout.child_row, parent, false); 
    }

    Color c = (Color)getChild( groupPosition, childPosition );

    TextView color = (TextView)v.findViewById( R.id.childname );
    if( color != null ) {
        color.setText( c.getColor() );
    }

    TextView rgb = (TextView)v.findViewById( R.id.rgb );
    if( rgb != null ) {
        rgb.setText( c.getRgb() );
    }

    CheckBox cb = (CheckBox)v.findViewById( R.id.check1 );
    cb.setChecked( c.getState() );
    cb.setOnCheckedChangeListener(new OnCheckedChangeListener()
    {
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
        {
            colors.get(groupPosition).get(childPosition).setState(isChecked);
            context.setColorBool(groupPosition, childPosition, isChecked);
            Log.d("ElistCBox2", "listitem position: " +groupPosition+"/"+childPosition+" "+isChecked);
        }
    });

    return v;
}

我不知道哪段代码可能对此负责,因此欢迎就此处包含的内容提出任何建议。我的代码仅在尝试保存值时与原始代码不同。

4

2 回答 2

0

这是一个非常古老的问题,但我遇到了同样的问题,所以这是我对任何人的回答:

最简单的方法是使用 CheckBox.onClickListener 而不是 onCheckedChangeListener。

就重新安排逻辑而言,这只是有点烦人,但会确保当随机取消选中框(例如通过扩展相邻组)时,不会触发事件。

老实说,我认为这应该被视为一个错误,即使我确信可以从 Android 源代码中解释该行为。

于 2013-08-14T12:22:19.287 回答
0

我的猜测是,当您的适配器正在创建视图时,会在初始化复选框视图时调用检查侦听器。android 中的很多小部件都是这样工作的……在初始化视图时调用侦听器。

我不知道为什么事情会这样,但它可能是允许客户端代码以一致的方式初始化自己。例如,复选框是否被用户选中或者是否初始化为选中,运行相同的代码。

为了解决这个问题,您可以尝试在您的侦听器类 impl 中设置一个标志,以允许您忽略第一次点击,例如,

cb.setOnCheckedChangeListener(new OnCheckedChangeListener()
    {
        private void first = true;

        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
        {
            if (first) {
              first = false;
              return;
            }

            colors.get(groupPosition).get(childPosition).setState(isChecked);
            context.setColorBool(groupPosition, childPosition, isChecked);
            Log.d("ElistCBox2", "listitem position: " +groupPosition+"/"+childPosition+" "+isChecked);
        }
    });

另外,请确保您在适配器convertView中的实现中正确重用。getView()例如,

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View view = convertView;
    if (view == null) {
        view = inflater.inflate(R.layout.applications_item, null);
    }
于 2012-06-27T19:41:21.833 回答