【问题标题】:Can onCheckedChanged method be called with no interaction?可以在没有交互的情况下调用 onCheckedChanged 方法吗?
【发布时间】:2012-05-18 18:41:24
【问题描述】:

我有一个自定义ListView,点击一个项目会触发一个新的ActivityListView 的每一行都有一个CheckBox 和一个TextView

这是我自定义的ListView 中的getView 方法:

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 回来时被调用,没有可能的用户交互来实际检查任何内容。

关键是过去工作正常,并没有真正改变任何东西。我已经read 说这是一个错误,但我不敢相信。

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

【问题讨论】:

    标签: android oncheckedchanged


    【解决方案1】:

    我感觉它发生在 onRestoreInstanceState 方法中。当您的活动暂停和恢复时,Android 会自动处理恢复活动中大多数 Views 的状态。恢复时,听起来它正在恢复 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 无关,但我想我看到了问题所在。您在Adapter 中重用Views,这很好,但是您在设置侦听器之前将star 设置为检查。问题是star 已经有一个从上次通过getView 方法传入的侦听器。在致电star.setChecked() 之前,请先致电star.setOnCheckedChangedListener(null) 看看是否能解决您的问题。

    【讨论】:

    • 你完全正确!不过现在,当然,单击我的 CheckBox 并没有做任何事情。
    • 如果您在 super.onRestoreInstanceState 执行完毕后将 mRestoringInstanceState 设置回 false,则应该这样做。
    • 此外,您还可以将star.setOnCheckedChangeListener... 行移至onResume 方法,因为它在onRestoreInstanceState 之后调用。在这种情况下,您不需要实现 onRestoreInstanceState。我将编辑我的答案以显示此选项。
    • 好吧,如果我设置if(mRestoringInstanceState),它就像我说的那样工作,但如果我设置if(!mRestoringInstanceState),它就不起作用
    • @eskalera 之所以这样工作,是因为您在getView 中重用视图,star 已经有一个监听器从上次通过getView 传递到它。 .因此,当您检查star 时,它会触发分配给它的最后一个侦听器。您可以在检查之前取消初始化。
    【解决方案2】:

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

    您可以使用

    禁用它
    android:saveEnabled="false"
    

    关于 Checkbox 的布局定义

    【讨论】:

    • 这是解决真正烦人问题的最佳解决方案。如果 onCheckedChanged() 被意外调用,试试这个。
    【解决方案3】:

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

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

    OnCheckedChangeListener ccl = new OnCheckedChangeListener()
    {
        @Override
        public void onCheckedChanged(CompoundButton buttonView,
                boolean isChecked) {
    
            if(buttonView.isShown())
            {
    
            }
        }
    };
    

    【讨论】:

    • 我认为这是一个很好的解决方案,因为系统在恢复状态时调用 OnCheckedChangedListener 显然不是 99% 的开发人员想要的。值得一提的是,ViewCompat.isLaidOut(buttonView) 也可用于此目的,并且与可见性无关。
    【解决方案4】:

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

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

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

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

    ... 此处建议: Android CheckBox -- Restoring State After Screen Rotation

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

    【讨论】:

    • 拯救了我的一天 :) 虽然我没有在适配器中使用它。
    猜你喜欢
    • 1970-01-01
    • 2021-04-23
    • 2015-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-26
    • 2012-09-27
    • 1970-01-01
    相关资源
    最近更新 更多