- SwipeRefreshLayout
- Пример на Kotlin
- Устаревший пример для Java
- Обновляем список
- Новый SwipeRefreshLayout из библиотеки Android support — «потяните чтобы обновить»
- Drag и Swipe в RecyclerView. Часть 2: контроллеры перетаскивания, сетки и пользовательские анимации
- Контроллеры перетаскивания
- Выделение элемента списка
- Сетки
- Пользовательские анимации смахивания
- Заключение
- Исходный код
- Drag и Swipe в RecyclerView. Часть 1: ItemTouchHelper
- ItemTouchHelper
- Настройка
- Использование ItemTouchHelper и ItemTouchHelper.Callback
- Заключение
- Исходный код
SwipeRefreshLayout
В марте 2014 года был представлен новый компонент android.support.v4.widget.SwipeRefreshLayout, который входил в состав библиотеки Support Library v4. Сейчас это отдельная библиотека в составе AndroidX.
Компонент позволяет отказаться от сторонних библиотек и собственных велосипедов для реализации шаблона «Pull to Refresh», когда пользователь сдвигает экран, чтобы обновить данные. Подобное поведение можно увидеть в клиентах для Твиттера, чтобы получить новую порцию твитов, не дожидаясь, когда список сообщений обновится самостоятельно.
Пример на Kotlin
В марте 2020 года обзавелась стабильной версией.
В методах setColorSchemeColors() или setColorSchemeResources() следует указать используемые цвета.
Компонент достаточно интересный с занимательной анимацией. Вначале анимация представляла собой цветные полоски под заголовком программы. Позже анимацию заменили в стиле Material Design, теперь это маленький кружочек, внутри которого крутятся цветные линии (или чёрная линия, если не использовать метод setColorSchemeResources() со цветами).
Запустите пример и потяните экран сверх вниз, чтобы увидеть эффект обновления данных.
Устаревший пример для Java
Обернём компоненты родительским элементом SwipeRefreshLayout. На панели инструментов данного компонента нет, поэтому придётся писать код вручную.
В примере реализуется интерфейс OnRefreshListener с методом onRefresh(), в котором следует обновить поступающие данные. В нашем случае просто генерируются случайные числа.
При первом появлении библиотеки использовался метод setColorScheme(), который объявлен устаревшим. Вместо него появились два новых метода setColorSchemeColors() и setColorSchemeResources(). Принцип остался тот же, вам нужно указать четыре цвета по константам Color.XXX или из ресурсов. Вы можете не использовать вызов метода с цветными линиями, тогда будет выводиться только чёрная линия по умолчанию.
Компонент достаточно интересный с занимательной анимацией. Вначале анимация представляла собой цветные полоски под заголовком программы, как представлено на видео.
Позже анимацию заменили в стиле Material Design, теперь это маленький кружочек, внутри которого крутятся цветные линии (или чёрная линия, если не использовать метод setColorSchemeResources() со цветами).
Обновляем список
По такому же принципу обновляем данные в списке.
При каждой попытке обновить список будет добавляться текущая дата и время.
Не забывайте, что обновление может занимать длительное время и использовать сеть для получения данных. Поэтому следует позаботиться о выполнении в другом потоке.
Источник
Новый SwipeRefreshLayout из библиотеки Android support — «потяните чтобы обновить»
Тихо и незаметно вместе с обновлением библиотеки Android support до версии 19.1 в нее прокрался новый компонент, который часто бывает нужным и полезным в быту. Сей совсем крохотный росчерк я посвящаю ему, SwipeRefreshLayout.
Он добавляет функционал, который один мой коллега называет «резинка от трусов», а остальные знают этот UI-паттерн под названием «потяни, чтобы обновить». Он бывает нужен, когда есть какой-то контент, который пользователь хочет часто обновлять, и может это сделать, просто потянув контент жестом вниз, а потом отпустив.
Очень похоже, что компонент был создан для GoogleNow, а потом перекочевал в support lib (очень похожа анимация).
Алгоритм простой.
- Компонент «оборачивается» вокруг View или Layout, для которого нужно сделать обновление и может содержать только одного потомка (похоже на ScrollView).
- Устанавливается OnRefreshListener с одним единственным методом onRefresh(). Как на него реагировать — решаем сами.
- Когда нужно показать, что идет обновление (и запустить анимацию), вызываем метод setRefreshing(boolean) и передаем ему true. Наиболее логичным кажется вызов метода внутри onRefresh().
- Когда обновление закончено, вызываем метод setRefreshing(boolean) и передаем ему false.
Давайте попробуем набросать пример использования.
Наш XML (если нужно, можно и динамически создать компонент и добавить в него потомка, компонент наследуется от ViewGroup).
Теперь наша Activity, а именно метод onCreate:
В данном случае я сделал нашу Activity реализующей интерфейс OnRefreshListener
Обратите внимание на метод setColorScheme, он как раз и раскрашивает в разные цвета прогресс во время обновления. В видео ниже видно, о чем я говорю. Первый цвет из 4-х — цвет прогресса во время оттягивания контента вниз перед обновлением. Остальные — сменяющиеся цвета прогресса.
А теперь сам onRefresh();
UPD:
Для желающих добавил саму APK
Ссылка на APK в виде кода, чтобы было жить легче:
Источник
Drag и Swipe в RecyclerView. Часть 2: контроллеры перетаскивания, сетки и пользовательские анимации
В первой части мы рассмотрели ItemTouchHelper и реализацию ItemTouchHelper.Callback, которая добавляет базовые функции drag & drop и swipe-to-dismiss в RecyclerView . В этой статье мы продолжим то, что было сделано в предыдущей, добавив поддержку расположения элементов в виде сетки, контроллеры перетаскивания, выделение элемента списка и пользовательские анимации смахивания (англ. swipe).
Контроллеры перетаскивания
При создании списка, поддерживающего drag & drop, обычно реализуют возможность перетаскивания элементов по касанию. Это способствует понятности и удобству использования списка в «режиме редактирования», а также рекомендуется material-гайдлайнами. Добавить контроллеры перетаскивания в наш пример сказочно легко.
Сперва обновим layout элемента (item_main.xml).
Изображение, используемое для контроллера перетаскивания, можно найти в Material Design иконках и добавить в проект с помощью удобного плагина генератора иконок в Android Studio.
Как кратко упоминалось в прошлой статье, вы можете использовать ItemTouchHelper.startDrag(ViewHolder) , чтобы программно запустить перетаскивание. Итак, всё, что нам нужно сделать, это обновить ViewHolder , добавив контроллер перетаскивания, и настроить простой обработчик касаний, который будет вызывать startDrag() .
Нам понадобится интерфейс для передачи события по цепочке:
Затем определите ImageView для контроллера перетаскивания в ItemViewHolder :
и обновите RecyclerListAdapter :
RecyclerListAdapter теперь должен выглядеть примерно так.
Всё, что осталось сделать, это добавить OnStartDragListener во фрагмент:
RecyclerListFragment теперь должен выглядеть следующим образом. Теперь, когда вы запустите приложение, то сможете начать перетаскивание, коснувшись контроллера.
Выделение элемента списка
Сейчас в нашем примере нет никакой визуальной индикации элемента, который перетаскивается. Очевидно, так быть не должно, но это легко исправить. С помощью ItemTouchHelper можно использовать стандартные эффекты подсветки элемента. На Lollipop и более поздних версиях Android, подсветка «расплывается» по элементу в процессе взаимодействия с ним; на более ранних версиях элемент просто меняет свой цвет на затемнённый.
Чтобы реализовать это в нашем примере, просто добавьте фон (свойство background ) в корневой FrameLayout элемента item_main.xml или установите его в конструкторе RecyclerListAdapter.ItemViewHolder. Это будет выглядеть примерно так:
Выглядит круто, но, возможно, вы захотите контролировать ещё больше. Один из способов сделать это — позволить ViewHolder обрабатывать изменения состояния элемента. Для этого ItemTouchHelper.Callback предоставляет ещё два метода:
- onSelectedChanged(ViewHolder, int) вызывается каждый раз, когда состояние элемента меняется на drag (ACTION_STATE_DRAG) или swipe (ACTION_STATE_SWIPE). Это идеальное место, чтобы изменить состояние view -компонента на активное.
- clearView(RecyclerView, ViewHolder) вызывается при окончании перетаскивания view -компонента, а также при завершении смахивания (ACTION_STATE_IDLE). Здесь обычно восстанавливается изначальное состояние вашего view -компонента.
А теперь давайте просто соберём всё это вместе.
Сперва создайте интерфейс, который будут реализовывать ViewHolders :
Затем в SimpleItemTouchHelperCallback реализуйте соотвутствующие методы:
Теперь осталось только, чтобы RecyclerListAdapter.ItemViewHolder реализовал ItemTouchHelperViewHolder :
В этом примере мы просто добавляем серый фон во время активности элемента, а затем его удаляем. Если ваш ItemTouchHelper и адаптер тесно связаны, вы можете легко отказаться от этой настройки и переключать состояние view -компонента прямо в ItemTouchHelper.Callback .
Сетки
Если теперь вы попытаетесь использовать GridLayoutManager , вы увидите, что он работает неправильно. Причина и решение проблемы просты: мы должны сообщить нашему ItemTouchHelper , что мы хотим поддерживать перетаскивание элементов влево и вправо. Ранее в SimpleItemTouchHelperCallback мы уже указывали:
Единственное изменение, необходимое для поддержки сеток, заключается в добавлении соответствующих флагов:
Тем не менее, swipe-to-dismiss не очень естественное поведение для элементов в виде сетки, поэтому swipeFlags разумнее всего обнулить:
Чтобы увидеть рабочий пример GridLayoutManager , смотрите RecyclerGridFragment. Вот как это выглядит при запуске:
Пользовательские анимации смахивания
ItemTouchHelper.Callback предоставляет действительно удобный способ для полного контроля анимации во время перетаскивания или смахивания. Поскольку ItemTouchHelper — это RecyclerView.ItemDecoration, мы можем вмешаться в процесс отрисовки view -компонента похожим образом. В следующей части мы разберём этот вопрос подробнее, а пока посмотрим на простой пример переопределения анимации смахивания по умолчанию, чтобы показать линейное исчезновение.
Параметры dX и dY — это текущий сдвиг относительно выделенного view -компонента, где:
- -1.0f — это полное смахивание справа налево (от ItemTouchHelper.END к ItemTouchHelper.START )
- 1.0f — это полное смахивание слева направо (от ItemTouchHelper.START к ItemTouchHelper.END )
Важно вызывать super для любого actionState , который вы не обрабатываете, для того, чтобы запускалась анимация по умолчанию.
В следующей части мы рассмотрим пример, в котором будем контролировать отрисовку элемента в момент перетаскивания.
Заключение
На самом деле, настройка ItemTouchHelper — это довольно весело. Чтобы не увеличивать объём этой статьи, я разделил её на несколько.
Исходный код
Весь код этой серии статей смотрите на GitHub-репозитории Android-ItemTouchHelper-Demo. Эта статья охватывает коммиты от ef8f149 до d164fba.
Источник
Drag и Swipe в RecyclerView. Часть 1: ItemTouchHelper
Существует множество обучающих материалов, библиотек и примеров реализации drag & drop и swipe-to-dismiss в Android c использованием RecyclerView. В большинстве из них по-прежнему используются устаревший View.OnDragListener и подход SwipeToDismiss, разработанный Романом Нуриком. Хотя уже доступны новые и более эффективные методы. Совсем немногие используют новейшие API, зачастую полагаясь на GestureDetectors и onInterceptTouchEvent или же на другие более сложные имплементации. На самом деле существует очень простой способ добавить эти функции в RecyclerView . Для этого требуется всего лишь один класс, который к тому же является частью Android Support Library.
ItemTouchHelper
ItemTouchHelper — это мощная утилита, которая позаботится обо всём, что необходимо сделать, чтобы добавить функции drag & drop и swipe-to-dismiss в RecyclerView . Эта утилита является подклассом RecyclerView.ItemDecoration, благодаря чему её легко добавить практически к любому существующему LayoutManager и адаптеру. Она также работает с анимацией элементов и предоставляет возможность перетаскивать элементы одного типа на другое место в списке и многое другое. В этой статье я продемонстрирую простую реализацию ItemTouchHelper . Позже, в рамках этой серии статей, мы расширим рамки и рассмотрим остальные возможности.
Примечание. Хотите сразу увидеть результат? Загляните на Github: Android-ItemTouchHelper-Demo. Первый коммит относится к этой статье. Демо .apk -файл можно скачать здесь.
Настройка
Сперва нам нужно настроить RecyclerView . Если вы ещё этого не сделали, добавьте зависимость RecyclerView в свой файл build.gradle .
ItemTouchHelper будет работать практически с любыми RecyclerView.Adapter и LayoutManager , но эта статья базируется на примерах, использующих эти файлы.
Использование ItemTouchHelper и ItemTouchHelper.Callback
Чтобы использовать ItemTouchHelper , вам необходимо создать ItemTouchHelper.Callback. Это интерфейс, который позволяет отслеживать действия перемещения (англ. move) и смахивания (англ. swipe). Кроме того, здесь вы можете контролировать состояние выделенного view -компонента и переопределять анимацию по умолчанию. Существует вспомогательный класс, который вы можете использовать, если хотите использовать базовую имплементацию, — SimpleCallback. Но для того, чтобы понять, как это работает на практике, сделаем всё самостоятельно.
Основные функции интерфейса, которые мы должны переопределить, чтобы включить базовый функционал drag & drop и swipe-to-dismiss:
Мы также будем использовать несколько вспомогательных методов:
Рассмотрим их поочередно.
ItemTouchHelper позволяет легко определить направление события. Вам нужно переопределить метод getMovementFlags() , чтобы указать, какие направления для перетаскивания будут поддерживаться. Для создания возвращаемых флагов используйте вспомогательный метод ItemTouchHelper.makeMovementFlags(int, int) . В этом примере мы разрешаем перетаскивание и смахивание в обоих направлениях.
ItemTouchHelper можно использовать только для перетаскивания без функционала смахивания (или наоборот), поэтому вы должны точно указать, какие функции должны поддерживаться. Метод isLongPressDragEnabled() должен возвращать значение true , чтобы поддерживалось перетаскивание после длительного нажатия на элемент RecyclerView . В качестве альтернативы можно вызвать метод ItemTouchHelper.startDrag(RecyclerView.ViewHolder) , чтобы начать перетаскивание вручную. Рассмотрим этот вариант позже.
Чтобы разрешить смахивание после касания где угодно в рамках view -компонента, просто верните значение true из метода isItemViewSwipeEnabled() . В качестве альтернативы можно вызвать метод ItemTouchHelper.startSwipe(RecyclerView.ViewHolder) , чтобы начать смахивание вручную.
Следующие два метода, onMove() и onSwiped() , необходимы для того, чтобы уведомить об обновлении данных. Итак, сначала мы создадим интерфейс, который позволит передать эти события по цепочке вызовов.
Самый простой способ сделать это — сделать так, чтобы RecyclerListAdapter имплементировал слушателя.
Очень важно вызвать методы notifyItemRemoved() и notifyItemMoved() , чтобы адаптер увидел изменения. Также нужно отметить, что мы меняем позицию элемента каждый раз, когда view -компонент смещается на новый индекс, а не в самом конце перемещения (событие «drop»).
Теперь мы можем вернуться к созданию SimpleItemTouchHelperCallback , поскольку нам всё ещё необходимо переопределить методы onMove() и onSwiped() . Сначала добавьте конструктор и поле для адаптера:
Затем переопределите оставшиеся события и сообщите об этом адаптеру:
В результате класс Callback должен выглядеть примерно так:
Когда Callback готов, мы можем создать ItemTouchHelper и вызвать метод attachToRecyclerView(RecyclerView) (например, в MainFragment.java):
После запуска должно получиться приблизительно следующее:
Заключение
Это максимально упрощённая реализация ItemTouchHelper . Тем не менее, вы можете заметить, что вам не обязательно использовать стороннюю библиотеку для реализации стандартных действий drag & drop и swipe-to-dismiss в RecyclerView . В следующей части мы уделим больше внимания внешнему виду элементов в момент перетаскивания или смахивания.
Исходный код
Я создал проект на GitHub для демонстрации того, о чём рассказывается в этой серии статей: Android-ItemTouchHelper-Demo. Первый коммит в основном относится к этой части и немного ко второй.
Источник