Когда пользователь листает ленту или список сообщений, ему удобно обновить содержимое, просто потянув экран вниз. Этот жест называется pull-to-refresh, и в Android для него существует готовый компонент — SwipeRefreshLayout. В этом занятии для Android Studio мы на языке Kotlin разберём, как обернуть список в такой контейнер и настроить обновление данных. Материал построен так, чтобы даже новичок смог добавить знакомый жест в своё приложение за несколько минут.
Знакомство со SwipeRefreshLayout
SwipeRefreshLayout — это контейнер из библиотеки AndroidX, который добавляет своему единственному дочернему элементу возможность реагировать на жест смахивания вниз. При свайпе появляется анимированный индикатор, а когда данные обновлены, он исчезает. Компонент работает с любым прокручиваемым содержимым: RecyclerView, ListView, ScrollView и их наследниками.
Главное, что нужно запомнить: setOnRefreshListener задаёт действие при жесте, а isRefreshing = false прячет индикатор, когда работа завершена. Этих двух методов достаточно для большинства сценариев.
Подключаем библиотеку
SwipeRefreshLayout требует отдельной зависимости, хотя и входит в семейство AndroidX. Откройте build.gradle.kts уровня модуля app и добавьте строку:
dependencies {
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
}
После синхронизации Gradle компонент станет доступен в палитре разметки.
Размещение в XML
В файле activity_main.xml замените корневой элемент на SwipeRefreshLayout, а внутри оставьте RecyclerView. Важно, чтобы список был единственным прямым потомком контейнера.
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/swipeRefresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
Программная настройка в Activity
В MainActivity.kt получим ссылки на SwipeRefreshLayout и RecyclerView, настроим адаптер (возьмём простой список строк), а затем установим слушатель на жест. При свайпе вниз будем имитировать загрузку нового элемента: добавим строку в начало списка и через задержку скроем индикатор.
class MainActivity : AppCompatActivity() {
private val items = mutableListOf("Первый", "Второй", "Третий")
private lateinit var adapter: ArrayAdapter<String>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val swipeRefresh = findViewById<SwipeRefreshLayout>(R.id.swipeRefresh)
val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
recyclerView.layoutManager = LinearLayoutManager(this)
adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, items)
recyclerView.adapter = adapter
swipeRefresh.setOnRefreshListener {
// имитация обновления данных
Handler(Looper.getMainLooper()).postDelayed({
items.add(0, "Новый элемент ${items.size + 1}")
adapter.notifyItemInserted(0)
swipeRefresh.isRefreshing = false
}, 2000) // задержка 2 секунды
}
}
}
Handler с задержкой здесь просто для демонстрации. В реальном проекте на этом месте будет запрос к серверу или базе данных, после которого вы вызовете isRefreshing = false.
Современный вариант с корутиной и ViewBinding
Использование корутин и ViewBinding делает код чище. Принцип тот же, но вместо Handler мы применяем lifecycleScope.launch и delay.
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
// ... настройка RecyclerView ...
binding.swipeRefresh.setOnRefreshListener {
lifecycleScope.launch {
delay(1500) // имитация загрузки
items.add(0, "Свежая запись")
adapter.notifyItemInserted(0)
binding.swipeRefresh.isRefreshing = false
}
}
}
Цветовое оформление индикатора
Чтобы вращающийся круг вписывался в дизайн, измените его цвета через setColorSchemeResources. Вызовите этот метод сразу после получения ссылки на SwipeRefreshLayout.
swipeRefresh.setColorSchemeResources(
android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light
)
Несколько замечаний для начинающих
- Всегда отключайте индикатор после обновления. Если забыть установить
isRefreshing = false, кружок будет вращаться бесконечно, и пользователь решит, что приложение зависло. - Не используйте SwipeRefreshLayout для начальной загрузки. Для отображения прогресса при первом входе на экран лучше подойдёт ProgressBar или Shimmer-анимация.
- Проверяйте, не идёт ли уже обновление. Повторный свайп во время выполнения фоновой задачи может вызвать дублирование запросов.
Коротко о главном
Сегодняшний урок в Android Studio на языке Kotlin показал, как оживить список с помощью SwipeRefreshLayout. Вы обернули RecyclerView в контейнер, настроили обработку жеста и научились скрывать индикатор после завершения работы. Теперь в вашем приложении появился стандартный pull-to-refresh, к которому привыкли пользователи. Попробуйте реализовать настоящее обновление данных с сервера — так вы закрепите навык и сделаете интерфейс ещё удобнее.