Выбор ListView остается постоянным после выхода из режима выбора - PullRequest
41 голосов
/ 18 марта 2012

У меня есть подкласс ListView, который разрешает выбор, когда активна контекстная панель действий (CAB). CAB устанавливается как обратный вызов для события onItemLongClick:

public boolean onCreateActionMode(ActionMode mode, Menu menu) {
    // Inflate a menu resource providing context menu items
    MenuInflater inflater = mode.getMenuInflater();
    inflater.inflate(context_menu, menu);
    getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
    return true;
}

Это нормально, и ListView работает должным образом, при этом выбранный элемент остается выделенным при прикосновении.

Когда я закрываю CAB, я хочу, чтобы ListView вернулся в нормальное состояние (т. Е. Сенсорный режим) . Проблема в том, что последний выбранный элемент остается подсвеченным бесконечно, независимо от того, какими методами я пытаюсь его очистить:

public void onDestroyActionMode(ActionMode mode) {
    //Unselect any rows
    ListView lv = getListView();
    lv.clearChoices(); // Has no effect
    lv.setChoiceMode(ListView.CHOICE_MODE_NONE); // Has no effect on the highlighted item 
    lv.setFocusable(false); // Has no effect
    lv.setSelection(0); // Has no effect
    mActionMode = null;
}

Есть предложения?

Ответы [ 11 ]

34 голосов
/ 31 января 2013

Основная причина проблемы заключается в том, что после переключения режима выбора ListView на CHOICE_MODE_NONE платформа оптимизирует операцию clear , поскольку она больше не поддерживает «выбор».Я немного улучшил вышеупомянутые обходные пути, очистив состояние выбора вручную, а затем установив режим с задержкой, чтобы у платформы была очередь очищать состояние, прежде чем переключать режим в 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);
    }
});
20 голосов
/ 11 мая 2012

Я столкнулся с той же проблемой, и так как запрос макета не решает проблему для меня, я реализовал небольшой хак, который работает для меня. Может быть, это та же проблема, потому что я переключаюсь между CHOICE_MODE_SINGLE и CHOICE_MODE_NONE.

Когда режим действия заканчивается, я вызываю этот фрагмент кода. clearChoices гарантирует, что все элементы больше не проверяются (внутренне). Итерация по представлениям гарантирует, что все видимые в настоящее время представления сбрасываются и больше не проверяются.

mListView.clearChoices();

for (int i = 0; i < mListView.getChildCount(); i++) {
    ((Checkable) mListView.getChildAt(i)).setChecked(false);
}

mListView.setChoiceMode(ListView.CHOICE_MODE_NONE);
18 голосов
/ 21 декабря 2012

Глядя на исходный код ListView, единственный способ обойти это - установить для ListView значение CHOICE_MODE_NONE, а затем переназначить ListAdapter (который очищает внутренний список выбора независимо от режима выбора)

т.е. в ListFragment / ListActivity

getListView().setChoiceMode(ListView.CHOICE_MODE_NONE);
getListView().setAdapter(getListAdapter())
4 голосов
/ 15 июля 2013

У меня была эта проблема в API Level 17, и я решил ее, выполнив:

listView.clearChoices();
listView.invalidateViews();
2 голосов
/ 04 апреля 2014

Мне кажется, что принятый ответ не работает для невидимых предметов, и нет необходимости звонить

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

, просто позвоните

lv.requestLayout();

, чтобы полностью решить мойЯ звоню

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

в onDestroyActionMode()

и звоню

lv.setItemChecked(position, false)

в onItemClick(), когда он не находится в ActionMode

Однако, Я не подтвердил, вызовет ли setItemChecked() некоторые проблемы с производительностью

1 голос
/ 02 марта 2016

Это было зарегистрировано как ошибка AOSP , но помечено как устаревшее по любой причине.

Обычно вы ожидаете, что это будет работать:

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

К сожалениюЭто не.Отмена установки режима выбора на нет на следующем этапе макета будет работать:

getListView().clearChoices();
getListView().post(new Runnable() {
    @Override
    public void run() {
        getListView().setChoiceMode(ListView.CHOICE_MODE_NONE);
    }
});
0 голосов
/ 24 мая 2014

Не уверен, что уже слишком поздно, просто хотел поделиться. Я создал намерение на той же странице, чтобы после захвата данных, по которым щелкнули, она воссоздала новую страницу без сохранения щелчка.

0 голосов
/ 03 января 2014

Я обнаружил, что здесь работают только два метода (API 19):

  • Сброс адаптера списка, что нежелательно, поскольку он возвращается к началу списка;
  • Установка режима выбора на CHOICE_MODE_NONE в new Runnable

Если режим выбора изменяется без использования listView.post(new Runnable()), он не работает.Может кто-нибудь объяснить мне, почему это?

Извинения за отсутствие комментариев;У меня нет репутации.

Спасибо.

0 голосов
/ 22 ноября 2013

Я знаю, что на этот ответ уже получен ответ, но приведенные выше ответы по-прежнему вызывали проблемы с кэшированными / переработанными представлениями, которые поддерживает ListView, которые не обновляли свое состояние при прокрутке обратно в представление.Итак, вышеприведенное решение слегка меняется на:

    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);

Это лучше, чем использование getChildAt (i), потому что этот метод jusg дает вам текущие видимые представления и не учитывает внутренние кэшированные представления, которые не являютсявиден.

0 голосов
/ 19 июня 2013

Это не ошибка. Такое поведение требуется для поддержки нескольких HID для Android. Таким образом, чтобы показать состояние выбора, вам нужно только установить режим выбора для списка и фона для поддержки выбранного состояния для «макета элемента списка», например:

android:background="?android:attr/activatedBackgroundIndicator"

FYI: http://android -developers.blogspot.mx / 2008/12 / touch-mode.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...