В этом уроке мы рассмотрим компонент SwipeRefreshLayout
и реализуем его в простом Android приложении. Изучим преимущества и узнаем где его лучше использовать. Компонент SwipeRefreshLayout
работатет по принципу «проведите пальцем вниз, чтобы выполнить какую-то функцию (обновить компонент Android или визуально отобразить запрос на сервер). Компонент SwipeRefreshLayout
является частью Android Material Design и используется во многих приложениях, например, в Twitter, Gmail, Facebook.
Обзор контейнера SwipeRefreshLayout в Android
Контейнер SwipeRefreshLayout
представляет собой ViewGroup, который может работать только с одним дочерним элементом. Этим элементом может быть, например, ScrollView, ListView или RecyclerView. Контейнер SwipeRefreshLayout
нужен для того, чтобы пользователи могли обновлять экран вручную. Раньше отдельного компонента, который бы отвечал за это не было, поэтому приходилось создавать свои велосипеды с обнаружением вертикальных свайпов (движение пальца по экрану). Пример этого можно посмотреть при обновлении ленты в приложении Twitter.
Пример использования SwipeRefreshLayout в Android
Первым делом давайте добавим необходимые зависимости в наш проект. Зайдите в файлик
build.gradle (Module: app)
и добавьте в секции dependencies следующую строку:
1 compile 'com.android.support:recyclerview-v7:24.0.0'
Обратите внимание, что у меня установлены buildTools версии 24, поэтому я могу подключать версию 24.0.0 библиотеки RecyclerView. Используйте ту версию библиотеки, которая подходит Вам.
Теперь займемся макетом activity_main.xml, в котором опишем виджет SwipeRefreshLayout
из библиотеки v4 и вставим в него единственный дочерний элемент — RecyclerView из библиотеки дизайна:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/srl_container" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/rv_list" android:layout_width="match_parent" android:layout_height="wrap_content" /> </android.support.v4.widget.SwipeRefreshLayout> </RelativeLayout> |
Также создадим файл компоновки, который отвечает за представление одного элемента в списке RecyclerView. Содержимое файла item_row.xml представлено ниже:
1 2 3 4 5 6 |
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/tv_row" android:layout_width="match_parent" android:layout_height="30dp" android:gravity="center" /> |
Для обработки данных и передачи их для отрисовки в RecyclerView нам понадобится класс адаптер с реализацией паттерна ViewHolder:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
package javadevblog.com.swiperefreshlayoutapp; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import android.widget.Toast; import java.util.List; public class Adapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private Context mContext; private List<String> mDataList; public Adapter(Context context, List<String> dataList) { mContext = context; mDataList = dataList; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(mContext); View view = inflater.inflate(R.layout.item_row, parent, false); return new VHolder(view); } @Override public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) { String itemAtPosition = mDataList.get(position); VHolder vHolder = (VHolder) viewHolder; vHolder.mTextViewResult.setText(itemAtPosition); } @Override public int getItemCount() { return mDataList.size(); } /** * Добавляем в существующий список какую-то строку * @param randomElement - строка, которую нужно добавить в адаптер */ public void addRandomElement(String randomElement) { mDataList.add(randomElement); notifyDataSetChanged(); } public class VHolder extends RecyclerView.ViewHolder implements View.OnClickListener { public TextView mTextViewResult; public VHolder(View view) { super(view); mTextViewResult = (TextView) view.findViewById(R.id.tv_row); view.setOnClickListener(this); } @Override public void onClick(View view) { Toast.makeText(mContext, "Был нажат элемент " + getAdapterPosition(), Toast.LENGTH_SHORT).show(); } } } |
Комментарий к коду. В нашем классе-адаптере четко распределены роли:
В конструкторе передаем контекст и данные для обработки, в методе onCreateViewHolder()
происходит создание объекта View
из файла компоновки, а в методе onBindViewHolder()
по позиции отрисовывается контент. Все это работает с использованием паттерна ViewHolder
.
Теперь в классе MainActivity.java мы инициализируем виджеты и для SwipeRefreshLayout
переопределяем метод onRefresh
интерфейса OnRefreshListener
с функцией добавления элемента в список:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
package javadevblog.com.swiperefreshlayoutapp; import android.os.Bundle; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import java.util.ArrayList; import java.util.List; import java.util.Random; public class MainActivity extends AppCompatActivity { private Adapter mAdapter; private RecyclerView mRecyclerView; private SwipeRefreshLayout mSwipeRefreshLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // инициализируем контейнер SwipeRefreshLayout mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.srl_container); // инициализируем список mRecyclerView = (RecyclerView) findViewById(R.id.rv_list); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); // инициализируем адаптер с данными mAdapter = new Adapter(MainActivity.this, getFakeData()); mRecyclerView.setAdapter(mAdapter); // указываем слушатель свайпов пользователя mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { // добавляем в список рандомную строку String randomElement = new Random().nextInt(100) + " - это новый элемент"; // метод срабатывает по свайпу mAdapter.addRandomElement(randomElement); // указываем, что мы уже сделали все, что нужно было // убираем стандартную анимацию mSwipeRefreshLayout.setRefreshing(false); } }); } /** * Метод создает список со строками типа "N-й элемент списка" * * @return */ private List<String> getFakeData() { List<String> listOfStrings = new ArrayList<>(); for (int i = 0; i < 10; i++) { listOfStrings.add(i + " элемент списка"); } return listOfStrings; } } |
Теперь запустим проект на устройстве или эмуляторе и посмотрим что получилось в результате:
Здесь пользователь делает вертикальный свайп вниз (тянет список вниз экрана) и поверх элементов списка появляется круглый виджет со стрелкой — это уже зона ответственности SwipeRefreshLayout.
На этой картинке видно, что к начальному списку из 10 элементов добавились 3 сгенерированных элемента. Это значит, что пользователь три раза сделал вертикальный свайп.
В этой статье мы реализовали простое приложение, которое умеет добавлять какие-то элементы в список по запросу пользователя, а именно — по свайпу внутри компонента SwipeRefreshLayout
.
Рабочий проект со всеми кодами можно скачать здесь.
Следите за обновлениями раздела Разработка под Android и подписывайтесь на новые статьи сайта Javadevblog.com!
Спасибо большое