5

我有一个习惯ListView,点击一个项目会触发一个新的Activity. 的每一行ListView都有一个CheckBox和一个TextView

这是getView我自定义的方法ListView

public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;
        if (v == null) {
            LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = vi.inflate(R.layout.puzzles_row, null);
        }
        ListedPuzzle lp = items.get(position);
        if (lp != null) {
            TextView title = (TextView) v.findViewById(R.id.listTitles);
            title.setText(lp.getTitle());
            CheckBox star = (CheckBox) v.findViewById(R.id.star_listed);
            star.setChecked(lp.isStarred());
            star.setTag(new Integer(position));

            star.setOnCheckedChangeListener(new OnCheckedChangeListener() {

                public void onCheckedChanged(CompoundButton buttonView,
                        boolean isChecked) {
                    Integer realPosition = (Integer) buttonView.getTag();
                    ListedPuzzle obj = items.get(realPosition);
                    starListedPuzzle(obj.getId(), isChecked);
                }
            });

        }
        return v;

    }

onCheckedChanged从另一个 Activty 返回时调用 ,而没有可能的用户交互来实际检查任何内容。

关键是它曾经工作得很好,并没有真正改变任何东西。我读过这是一个错误,但我真的不敢相信。

它总是在相同的两个项目上调用方法ListView。他们可以以checkedChange=true某种方式设置吗?

4

4 回答 4

10

我有一种感觉,它正在发生在onRestoreInstanceState方法中。View暂停和恢复时,Android 会自动处理恢复活动中大多数 s 的状态。恢复时,听起来像是在恢复CheckBox对象的已检查状态,即触发onCheckedChanged. 尝试在您的中执行此操作,Activity如果这可以解决您的问题,请告诉我:

private boolean mRestoringInstanceState;

@Override
protected void onRestoreInstanceState( Bundle savedInstanceState ) {

    mRestoringInstanceState = true;
    super.onRestoreInstanceState( savedInstanceState );
    mRestoringInstanceState = false;
}

然后onCheckChanged像这样改变你的方法:

public void onCheckedChanged(CompoundButton buttonView,
        boolean isChecked) {

    if(!mRestoringInstanceState) {
        Integer realPosition = (Integer) buttonView.getTag();
        ListedPuzzle obj = items.get(realPosition);
        starListedPuzzle(obj.getId(), isChecked);
    }
}

编辑:可能更好/更简单的解决方案是在方法中分配侦听器,onResume因为它在onRestoreInstanceState. 请注意,如果使用此解决方案,您将不会实现上述任何内容:

@Override
protected void onResume() {

    super.onResume();
    CheckBox star = (CheckBox) v.findViewById(R.id.star_listed);
    star.setOnCheckedChangeListener(new OnCheckedChangeListener() {

        public void onCheckedChanged(CompoundButton buttonView,
                boolean isChecked) {
            // onCheckedChanged implementation
        }
    });
}

Edit2:刚刚意识到你正在做这个Adapter。这可能与 无关onRestoreInstanceState,但我想我看到了问题。您在 s 中重用Views Adapter,这很好,但您在设置star侦听器之前设置为检查。问题是从上次通过该方法star时就已经有了一个侦听器。getView在你打电话之前star.setChecked(),打电话star.setOnCheckedChangedListener(null)看看这是否能解决你的问题。

于 2012-05-18T18:49:09.177 回答
9

可以在片段中的 onRestoreInstanceState 上调用它

你可以禁用它

android:saveEnabled="false"

在 Checkbox 的布局定义上

于 2015-06-10T18:44:26.990 回答
6

我使用自定义适配器也遇到了这个问题。

我发现检查按钮 isShown 是否解决了问题:

OnCheckedChangeListener ccl = new OnCheckedChangeListener()
{
    @Override
    public void onCheckedChanged(CompoundButton buttonView,
            boolean isChecked) {

        if(buttonView.isShown())
        {

        }
    }
};
于 2014-03-20T16:28:13.103 回答
1

在侦听器中检查您的堆栈跟踪

public void onCheckedChanged(CompoundButton buttonView, isChecked) {
    <breakpoint here>
}

如果您onRestoreInstanceState()在堆栈跟踪中看到,您可以在布局中使用它:

<CheckBox
...
android:saveEnabled="false" />

...如此处建议: Android CheckBox -- 屏幕旋转后恢复状态

或者

如果您看到这star.setChecked()是在堆栈跟踪中从您那里调用的那个,那么只需在之前getView()删除侦听器(然后您可以像这样做一样重置侦听器)。就像杰森罗宾逊建议的那样。star.setOnCheckedChangedListener(null)star.setChecked()

于 2015-03-13T18:41:05.230 回答