Pull to refresh android это

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() со цветами).

Обновляем список

По такому же принципу обновляем данные в списке.

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

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

Источник

Выбор Pull To Refresh инструмента

100; подгрузка элементов по требованию; набор списков располагается в самописном компоненте, аля ViewPager) это действительно оказалось проблематично. О всех моих изысканиях в данном направлении читайте под катом.

Pull To Refresh — фишка, насколько мне известно, перекочевавшая на Android из iPhone’а. Удобный способ обновления списка.
Рассмотрим его на примере нашего новостного приложения (в него-то собственно и возникла необходимость внедрить эту фичу): есть список новостей, который обновляется через новостной сервер. Обновление ручное, так что внизу торчит кнопочка «Обновить», которая занимает некоторое место на экране. А зачем тратить драгоценное экранное пространство на кнопочку, которая не так уж и часто используется, если можно вопользоваться приемом Pull To Refresh: находясь вверху списка потяните список вниз, а затем отпустите, чтобы список обновился. Новые новости (каламбурчик) подгрузятся и отобразятся. Выглядит это примерное так:

Идея довольно удачная, поэтому и используется во многих приложения, включая популярные Facebook и Twitter клиенты. Так вот и мы решили внедрить в свой новостной проект такую фишку.
Но зачем писать с нуля то, что уже есть в готовом виде? Быстрый поиск в Google, великий и могучий StackOverFlow — и вот найден самый популярный инструмент android-pulltorefresh от Йохана Нильсона. Взял последнюю версию с GitHub’а и заюзал у себя. Не тут-то было! Проект вроде бы уже почти год развивается, но… вот что Я вижу в случае малых списков:

Читайте также:  Долгое время работы android

И такой вопрос сразу возникает: WTF? Проект watch’ат 418 человек, аж 71 человек его форкнул, а тут такое каличное некорректное поведение. А все почему? Потому что вот этот вот «Tap to refresh. » — это header у ListView. И прячется он, в реализации от Йохана, банальным ListView.setSelection(1). А в случае коротких списков этот setSelection(1) вежливо посылает на фек не работает.
Но потом замечаю, что у проекта оказывается есть ещё два branch’а: enhancedpull (который уже был смержен с главным брэнчем) и, отоноче, scrollfix_for_short_list 🙂
Вытягиваю последнюю версию брэнча scrollfix_for_short_list, прикручиваю в проект: короткий список вроде выглядит нормально, только отчего ж у меня начал так тормозить UI? А дело вот в чем: список мой — не простой, а с подгрузкой по требованию (on-demand), т.е. саначала показываются первые 10 элементов, а если промотать до конца, то в список догружается следующая порция. А в чем же состоит fix для коротких списков по версии Йохана?
«А давайте добавим в footer ListView пустую вьюху ровно такой высоты, чтобы setSelection(1) снова смог нормально скрыть header», — сказал Йохан и приступил к вычилениям высоты footer’а. Чтобы вычислить его высоту надо знать суммарную высоту всех элементов в списке (кроме header’а конечно). Тогда мы отнимем эту высоту от высоты ListView и получим высоту для footer’а. А чтобы узнать высоту каждого элемента списка, откуда-то было взято «гениальное» решение перебрать с помощью адаптера все элементы (с помощью getView()) и каждому сделать measure(), т.е. по сути отрисовать их (даже если они невидимы). В результате мой список думал, что его все проматывают и проматывают — и все подгружал и подгружал новые порции до тех пор, пока элементы то и не закончатся. А элементов у меня обычно за 50 в списке, и списков несколько (пролистываются наподобие недавно появившегося ViewPager‘а). В общем вот такая реализация подсчета суммарной высоты элементов списка:

абсолютно не подходит для списков с подгрузкой on-demand. Да и вообще стоит избегать дергать getView() у адаптера вручную. Мало ли у кого там какая логика заложена.
В итоге пошел Я серфить интернет в поисках более адекватного инструмента. Вот, что нашел:

  • PullToRefresh от Guillermo
  • Android-Pull-To-Refresh от Tim Mahoney
  • Android-Pull-To-Refresh от Daniel Wang (форкнутая и пофикшенная версия timahoney)

Guillermo, в лучших традиция ООП, реализовал Pull To Refresh посредством паттерна State. В результате получилось 13 классов, и возможность делать не только pull-down-to-refresh, но и pull-up-to-refresh. Уж не знаю ввиду чего, но реализация получилась не очень скоростной: ну не успевал край списка за резвым пальцем. Да и срабатывание требовало довольно резкого движения вниз, чтобы вызвать появление header’а. И анимации что-то не наблюдается… Поехали дальше.
Tim Mahoney никого не стал обманывать а сразу в README написал: «Current Status: Buggy.» Нет уж, для сурьезного проекта не подойдет. Но посмотрел на граф версий — какой-то добрый Daniel Wang форкнул проект и пофиксил баги. Берем, прикручиваем. Удобство использования оставляет желать лучшего. Если в предыдущих реализациях, достаточно было по приходу события onRefresh обновить список и потом вызвать onRefreshComplete():

Читайте также:  Контакте мобильная версия для андроид

то здесь надо вручную создавать header, и по приходу событий менять текст в нем, ну и список конечно обновлять:

Не знаю, может это и более гибко, но… неудобно. К тому же оказалось, что данная реализация не очень корректно работает в Pager’е: стало возможно пролистывать список по вертикали и Pager по горизонтали одновременно.
В итоге со слезами на глазах Я стал ставить на костыли версию Йохана из брэнча scrollfix_for_short_list, чтобы она не заставляла списки подгружаться до бесконечности. Кое-как было сделано, но работало, мягко говоря, нестабильно. На горизонте замаячила перспектива писать компонент самому, и Я решил ещё раз пересерфить интренет. И, о чудо!, Я наткнулся на ещё одну реализацию — от Криса Бэйнса. Проект базировался на версии Йохана, но был с тех пор существенно улучшен (как пишет автор). Испытание подтвердило: данная реализация дествительно лишена всех багов, присущих версии Йохана, и выглядит более приятно (за счет дополнительной анимации).

Так вот, к чему Я тут так распространился? А все затем чтобы выдать мораль:

Если вы хотите использовать в своем проекте механизм Pull To Refresh — используйте реализацию от Криса Бэйнса. На мой взгляд, на данный момент это самая качественная реализация приема Pull To Refresh.

Источник

Работающий Pull to refresh

Это рассказ о том, как получилась работающая реализация Pull to refresh под Android. Совсем не будет примеров кода. Немного картинок и в конце статьи ссылка на архив проекта.

Недавно встала необходимость встроить в текущее приложение Pull to refresh. Это сейчас модно, пользователи привыкли, и для твиттер-клиентов уже стало стандартом. Поиск готовых решений в сети вывел на единственный вариант — open-source проект Johan Nilsson android-pulltorefresh на Github.

В ListView вставляется Header, который прячется при необходимости. Решение работающее, но очень криво. Часто подвисает в каком-либо состоянии. Если в списке мало элементов и они не занимают все пространство, отведенное для ListView, то Header не скрывается, а надпись изменяется на Tap to refresh. Логичное ограничение данной реализации. Еще одна особенность была обнаружена при добавлении этого проекта в рабочее приложение. Так как Pull to refresh — это Header, то часто выполняется метод setSelection(1), чтобы спрятать Header. А так как мы используем сохранение и восстановление позиции, то конечно постоянный вызов setSelection нам все портит.

Поначалу решили доработать эту реализацию, исправить самые неприятные моменты. Даже встроили в один проект. Но сделать так, как хочется, не получилось, сказались ограничения от использования Header’а.

Возникла идея, как сделать по-другому и появилось свободное время. Раз проблема в Header’е, значит, его нужно убрать и поместить сам Pull to refresh View и ListView в один LinearLayout и двигать его. В идеале хотелось получить такой же Pull to refresh как в официальном Twitter-клиенте. Но там используется другая связка. Pull to refresh там плавный и хорошо везде работающий. Вообще много времени провели, наблюдая за работой официального Twitter-клиента.

Вариантов что и как двигать много. Можно двигать и Pull to refresh View, и ListView, и LinearLayout. Можно двигать, изменяя Padding, Margin или ScrollTo. После большого количества экспериментов на эмуляторе и на реальных устройствах, была найдена наиболее оптимальная связка. Первоначальный сдвиг делается изменением Padding на высоту Pull to refresh View, таким образом, мы его прячем с экрана. А дальше двигаем весь Layout изменением ScrollTo.

Получилось красиво и максимально плавно. Но возникла проблема, на тот момент кажущаяся непреодолимой. Почему-то при сдвиге Layout все начинало прыгать. Приходили координаты то ниже, то выше, и никак не получалось исправить. Чуть даже не вернулись к первоначальному плану — доработать Pull to refresh от Johan Nilsson.

Читайте также:  Список новых андроид смартфонов

Но потом как по волшебству на глаза попал другой проект. Альтернативный Pull To Refresh от guillep на том же Github. Он еще ужаснее работает, чем у Johan Nilsson, но используется совсем другой механизм, похожий на нашу идею. И самое главное там обходится проблема с прыгающим Layout’ом. Берется три последних координаты и вычисляется средняя. Таким образом, обеспечивается плавность.

Мы взяли понемногу из каждого проекта, все объединили, и получился хорошо работающий Pull to refresh, но оставалось незаконченным состояние загрузки. После отпускания Release to refresh превращается в Loading и в таком состоянии оно должно скролиться вместе со списком, поэтому оно должно быть частью ListView. Отдельный Pull to refresh View должен исчезнуть, а в ListView должно добавиться Pull to refresh View в состоянии Loading.

Так как наше View должно постоянно то появляться, то исчезать в ListView, использовать его как Header нельзя. Но и изменять текущие адаптеры тоже не хочется. Необходимо, чтобы при добавлении Pull to refresh в рабочий проект, было как можно меньше изменений. Решили использовать специальный Adapter внутри Pull to refresh как Декоратор. И этот адаптер контролирует наличие специального View в состоянии Loading.

Было много проблем, особенно при добавлении в рабочий проект, но все они успешно решились. В конце концов, получился класс, которым можно заменять обычный ListView и в котором реализован хорошо работающий Pull to refresh. Он прекрасно работает на всех API, начиная с версии 1.5.

Только на некоторых устройствах Samsung с переделанным ListView наблюдаются иногда проблемы. Но уже есть идеи как и что можно переделать.

Источник

Pull to Refresh with RecyclerView in Android with Example

The SwipeRefreshLayout widget is used for implementing a swipe-to-refresh user interface design pattern. Where the user uses the vertical swipe gesture to refresh the content of the views. The vertical swipe is detected by the SwipeRefreshLayout widget and it displays a distinct progress bar and triggers the callback methods in the app. In order to use this behavior, we need to use the SwipeRefreshLayout widget as the parent of a ListView or GridView. These Material Design UI Patterns are seen in applications like Gmail, Youtube, Facebook, Instagram, etc. It allows the user to refresh the application manually. SwipeRefreshLayout class contains a listener called OnRefreshListener. The classes which want to use this listener should implement SwipeRefreshLayout.OnRefreshListener interface. On vertical swipe-down gesture, this listener is triggered and onRefresh() method is called and can be overridden according to the needs.

Example

In this example, we would store data into the ArrayList which is used for populating the RecyclerView. Whenever onRefresh() method is called the ArrayList data gets rearranged. A sample GIF is given below to get an idea about what we are going to do in this article. Note that we are going to implement this project using the Java language.

Step by Step Implementation

Step 1: Create a New Project

To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Java as the programming language.

Step 2: Adding dependencies

Источник

Оцените статью