ListView selection remains persistent after exiting choice mode

后端 未结 11 814
青春惊慌失措
青春惊慌失措 2020-11-29 01:45

I have a ListView subclass that I allow selections on when the context action bar (CAB) is active. The CAB is set as a callback to the onItemLongClick event:

相关标签:
11条回答
  • 2020-11-29 02:12

    The main reason for the problem is that once the ListView selection mode is switched to CHOICE_MODE_NONE, the framework optimizes out the clear operation as it is no longer supporting 'selections'. I have improved the above workarounds a bit by clearing the selection state manually and then setting the mode in a delayed manner so the framework will have its turn to clear the state before turning the mode to CHOICE_MODE_NONE.

    final ListView lv = getListView();
    lv.clearChoices();
    for (int i = 0; i < lv.getCount(); i++)
        lv.setItemChecked(i, false);
    lv.post(new Runnable() {
        @Override
        public void run() {
            lv.setChoiceMode(ListView.CHOICE_MODE_NONE);
        }
    });
    
    0 讨论(0)
  • 2020-11-29 02:15

    For me, it seems the accepted answer is not working for invisible items, and it's no need to call

    for (int i = 0; i < lv.getCount(); i++)
            lv.setItemChecked(i, false);
    

    instead, just call

    lv.requestLayout();
    

    To completely solve my issue, I call

    lv.clearChoices();
    lv.requestLayout();
    

    in onDestroyActionMode()

    and call

    lv.setItemChecked(position, false)
    

    in onItemClick() when it's not in ActionMode

    However, I did not confirm whether call setItemChecked() will result some performance issues

    0 讨论(0)
  • 2020-11-29 02:15

    This has been logged as an AOSP bug, but marked as obsolete for whatever reason.

    Normally you would expect this to work:

    getListView().clearChoices();
    getListView().setChoiceMode(ListView.CHOICE_MODE_NONE);
    

    Unfortunately it does not. Deferring setting choice mode to none in the next layout pass would work:

    getListView().clearChoices();
    getListView().post(new Runnable() {
        @Override
        public void run() {
            getListView().setChoiceMode(ListView.CHOICE_MODE_NONE);
        }
    });
    
    0 讨论(0)
  • 2020-11-29 02:18

    I faced the same issue and since requesting layout doesn't solve the problem for me either I implemented a little hack which works for me. Maybe this is the same issue because I'm switching between CHOICE_MODE_SINGLE and CHOICE_MODE_NONE.

    When the action mode ends I'm calling this code snippet. clearChoices makes sure that all items are not checked anymore (internally). The iteration over the views makes sure that all currently visible views are reset and not checked anymore.

    mListView.clearChoices();
    
    for (int i = 0; i < mListView.getChildCount(); i++) {
        ((Checkable) mListView.getChildAt(i)).setChecked(false);
    }
    
    mListView.setChoiceMode(ListView.CHOICE_MODE_NONE);
    
    0 讨论(0)
  • 2020-11-29 02:18

    I know this has been answered, but above answers still gave me problems with the cached/recycled views that ListView maintains, that didn't update it's state when scrolled back into view. So, the above solution changes slightly to:

        lv.clearChoices();  
    
        ArrayList<View> list = new ArrayList<View>();
        lv.reclaimViews(list);
        for (View view : list) {
            ((Checkable) view).setChecked(false);
        }
    
        lv.setChoiceMode(lv.CHOICE_MODE_NONE);
    

    This is better than using getChildAt(i) because that method jusg gives you the currently visble views and does not account for the internal cached views, that are not visible.

    0 讨论(0)
提交回复
热议问题