Реализация множественного выбора для массовых действий пользователя

Эта запись в блоге является продолжением серии, посвященной моей работе по разработке приложения AfterShoot.

Если вы не читали предыдущие, вы можете найти некоторые из них здесь:







Когда вы имеете дело с изображениями в приложении, скорее всего, вы захотите дать пользователям возможность выполнять определенные действия с несколькими изображениями одновременно. Например, в приложении «Галерея» пользователи обычно могут выбрать несколько изображений и удалить их все сразу вместо того, чтобы выполнять операцию удаления для каждого изображения по одному.

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

После этого приложение должно работать следующим образом:

Добавление опции множественного выбора в RecyclerView

Сообщение в блоге предполагает, что у вас есть приложение, которое показывает список данных с помощью RecyclerView. Если вы не знаете, как это настроить, обратитесь к следующей статье:



Шаг 1. Подготовка адаптера

Прежде чем мы продолжим и реализуем множественный выбор в нашем приложении, важно добавить две важные переменные в наш адаптер RecyclerView.

Boolean в строке номер 5 отслеживает, находится ли пользователь в режиме множественного выбора или нет, а ArrayList в строке номер 7 отслеживает все выбранные элементы.

Шаг 2: изменение onBindViewHolder

Затем мы должны обновить наш onBindViewHolder метод, чтобы добавить правильные обработчики щелчков (долгое нажатие и касание).

Это очень много, поэтому давайте посмотрим, что здесь происходит.

Во-первых, для каждого элемента в нашем RecyclerView мы проверяем, есть ли этот элемент в списке, содержащем все выбранные элементы (далее именуемого selectedItems). Если этот элемент находится в этом списке, мы добавляем к нему альфа-слой, который дает нашему пользователю визуальную обратную связь о том, что элемент выбран. В противном случае мы удаляем альфа-слой с элемента, который сообщает пользователю, что элемент не выбран.

Затем мы добавляем onLongClickListener к элементу, который при вызове проверяет, находится ли пользователь в режиме множественного выбора. В противном случае он устанавливает логическое значение multiSelect в значение true и добавляет элемент в список selectedItems.

Однако, если пользователь уже находится в режиме множественного выбора, он ничего не делает.

Наконец, мы добавили наш onClickListener к элементу, который вызывается, когда пользователь щелкает или касается элемента. Если пользователь находится в режиме множественного выбора, щелчок по элементу добавляет его в список selectedItems; в противном случае отображается изображение, по которому щелкнули.

У нас также есть вспомогательный метод под названием selectItem(), который принимает изображение и решает, добавлять ли его или удалять из списка selectedItems, в зависимости от значения логического multiSelect.

Изменение панели инструментов с помощью контекстных меню

На этом этапе, если вы попытаетесь запустить приложение, вы сможете удерживать нажатой и выбирать элементы в своем RecyclerView. Но пока нет интуитивного способа взаимодействия с этими элементами. Здесь мы воспользуемся контекстным ActionBar, чтобы предоставить нашим пользователям варианты, когда они начинают процесс множественного выбора.

Если вам интересно, что такое контекстный ActionBar, вот как он выглядит:

Теперь, когда вы знаете, как это выглядит, давайте посмотрим, как реализовать это в текущем приложении.

Шаг 1. Создание файла меню в приложении

Начнем с создания файла меню в приложении. Вы можете сделать это, щелкнув правой кнопкой мыши папку res в вашем приложении и выбрав следующие параметры:

В результате будет создан новый menu.xml файл, который ведет себя как обычный файл меню. А пока добавьте к нему следующее:

Шаг 2. Реализуйте ActionMode.Callback in your Adapter

Теперь давайте предложим нашему адаптеру реализовать ActionMode.Callback интерфейс, который определяет жизненный цикл меню контекстной панели действий.

При этом вам также придется переопределить следующие методы:

Наша следующая задача - по очереди заполнить эти методы их реализациями. Начнем с метода onCreateActionMode.

Этот метод содержит код для наполнения и отображения нашего меню, поэтому код выглядит так:

Затем давайте добавим реализацию для методов onAcionItem и onDestroyActionMode.

Эти два метода определяют, что происходит при щелчке по конкретному пункту меню и что происходит, когда пользователь выходит из режима множественного выбора и меню должно быть скрыто соответственно.

Вот как выглядит код этих двух методов:

Поскольку мы не обновляем меню динамически, вы можете оставить метод onPrepareActionMode как есть и просто вернуть true.

Шаг 2: Регистрация меню в нашей деятельности

После того, как у нас есть обратные вызовы, следующим шагом будет отображение или скрытие меню в зависимости от действия пользователя.

Поскольку меню являются частью Activity приложения, мы не можем отображать или скрывать их в Adapter. Следовательно, нам нужно найти способ зарегистрировать меню в Activity, которое содержит Adapter. Хотя есть много способов сделать это, пока давайте просто передадим экземпляр нашему Activity конструктору адаптера.

Примечание. Обратите внимание, что есть более эффективные способы сделать это (например, создать интерфейс и позволить вашей деятельности реализовать его) вместо прямой передачи объекта Activity. Мы выбрали этот метод, чтобы общий код оставался простым.

Когда у нас есть объект Activity, мы можем вызвать для него метод startSupportActionMode() с экземпляром объекта ActionMode.Callback. Как только мы вызовем этот метод, он отобразит меню на панели инструментов, поэтому нам нужно убедиться, что мы вызываем его только тогда, когда пользователь запустил процесс множественного выбора.

Мы можем гарантировать это, вызвав метод внутри нашего onLongClickHandler метода. Вот как выглядит код:

Примечание. Вы можете столкнуться с ошибкой при использовании этого метода, когда после выбора нескольких изображений нажимается кнопка «Назад» - контекстное меню исчезает, но элементы все еще выбираются. Это можно сделать, переопределив метод onBackPressed в действии и очищая список multiSelect при каждом нажатии кнопки «Назад».

Вот и все!

Если вы хотите увидеть всю реализацию, перейдите в репозиторий GitHub для приложения AfterShoot и найдите файл ResutImageAdapter.kt.



Спасибо за внимание! Если вам понравилась эта история, пожалуйста, нажмите 👏 кнопку и поделитесь ею, чтобы помочь другим найти ее! Не стесняйтесь оставлять комментарии 💬 ниже.

Есть отзывы? Подключим в Twitter.

Примечание редактора. Heartbeat - это онлайн-публикация и сообщество, созданное авторами и посвященное предоставлению первоклассных образовательных ресурсов для специалистов по науке о данных, машинному обучению и глубокому обучению. Мы стремимся поддерживать и вдохновлять разработчиков и инженеров из всех слоев общества.

Независимая редакция, Heartbeat спонсируется и публикуется Comet, платформой MLOps, которая позволяет специалистам по обработке данных и группам машинного обучения отслеживать, сравнивать, объяснять и оптимизировать свои эксперименты. Мы платим участникам и не продаем рекламу.

Если вы хотите внести свой вклад, отправляйтесь на наш призыв к участникам. Вы также можете подписаться на наши еженедельные информационные бюллетени (Deep Learning Weekly и Comet Newsletter), присоединиться к нам в » «Slack и подписаться на Comet в Twitter и LinkedIn для получения ресурсов, событий и гораздо больше, что поможет вам быстрее и лучше строить лучшие модели машинного обучения.