Android:AbsListView.setItemChecked()导致ActionMode销毁和重新创建?

时间:2015-02-27 02:23:51

标签: android actionmode

如果您直接致电AbsListView.setItemChecked(),效果会很好,ActionMode会激活并创建。

mGridView.setItemChecked(pPosition, true);

但是,当您先致电View.startActionMode(),然后致电AbsListView.setItemChecked()时,ActionMode创建的startActionMode()将会销毁,并通过setItemChecked()重新创建新的View.startActionMode()

我的问题是:首先致电{{1}}时如何避免此问题?

期待您的回复!谢谢!

1 个答案:

答案 0 :(得分:1)

为什么要重新创建一个新的?查看AbsListView.setItemChecked(int position, boolean value)方法的源代码,您可以看到以下代码:

    // Start selection mode if needed. We don't need to if we're unchecking something.
    if (value && mChoiceMode == CHOICE_MODE_MULTIPLE_MODAL && mChoiceActionMode == null) {
        if (mMultiChoiceModeCallback == null ||
                !mMultiChoiceModeCallback.hasWrappedCallback()) {
            throw new IllegalStateException("AbsListView: attempted to start selection mode " +
                    "for CHOICE_MODE_MULTIPLE_MODAL but no choice mode callback was " +
                    "supplied. Call setMultiChoiceModeListener to set a callback.");
        }
        mChoiceActionMode = startActionMode(mMultiChoiceModeCallback);
    }

这意味着如果mChoiceActionMode == null,则会调用startActionMode(mMultiChoiceModeCallback),因此会重新创建一个新的ActionMode。

如何解决? 这是一种简单的方法:使用reflect将startActionMode()创建的ActionMode分配给mChoiceActionMode中的私有字段AbsListView

private void startActionMode() {
    // Get the field "mMultiChoiceModeCallback" instance by reflect
    AbsListView.MultiChoiceModeListener wrapperIns = null;
    try {
        Field wrapper = null;
        wrapper = AbsListView.class.getDeclaredField("mMultiChoiceModeCallback");
        wrapper.setAccessible(true);
        wrapperIns = (AbsListView.MultiChoiceModeListener) wrapper.get(mMessageGridView);
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    }
    // Start the ActionMode, but not select any item. 
    ActionMode actionMode = mMessageGridView.startActionMode(wrapperIns);
    // Assign actionMode to field "mChoiceActionMode" by reflect 
    try {
        Field mChoiceActionMode = null;
        mChoiceActionMode = AbsListView.class.getDeclaredField("mChoiceActionMode");
        mChoiceActionMode.setAccessible(true);
        mChoiceActionMode.set(mMessageGridView, actionMode);
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    }
}

为什么我们在这里使用包装器?因为AbsListView.setMultiChoiceModeListener(MultiChoiceModeListener listener)将包装我们的mMultiChoiceModeListener,所以我们不能直接使用。