Освой Android играючи
/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000
Пример на Kotlin
Устаревший пример для Java
В марте 2014 года был представлен новый компонент android.support.v4.widget.SwipeRefreshLayout, который входил в состав библиотеки Support Library v4. Сейчас это отдельная библиотека в составе AndroidX.
Компонент позволяет отказаться от сторонних библиотек и собственных велосипедов для реализации шаблона "Pull to Refresh", когда пользователь сдвигает экран, чтобы обновить данные. Подобное поведение можно увидеть в клиентах для Твиттера, чтобы получить новую порцию твитов, не дожидаясь, когда список сообщений обновится самостоятельно.
В марте 2020 года обзавелась стабильной версией.
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
Подготовим макет.
<?xml version="1.0" encoding="utf-8"?>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView"
android:text="Hello Kitty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center"/>
</ScrollView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
В методах setColorSchemeColors() или setColorSchemeResources() следует указать используемые цвета.
Компонент достаточно интересный с занимательной анимацией. Вначале анимация представляла собой цветные полоски под заголовком программы. Позже анимацию заменили в стиле Material Design, теперь это маленький кружочек, внутри которого крутятся цветные линии (или чёрная линия, если не использовать метод setColorSchemeResources() со цветами).
package ru.alexanderklimov.swipe
import android.os.Bundle
import android.os.Handler
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import java.util.*
class MainActivity : AppCompatActivity() {
private lateinit var random: Random
private lateinit var handler: Handler
private lateinit var runnable: Runnable
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
random = Random()
handler = Handler()
swipeRefreshLayout.setOnRefreshListener {
// Initialize a new Runnable
runnable = Runnable {
// Update the text view text with a random number
textView.text = "Котика пора кормить. Его не кормили уже ${1 + random.nextInt(10)} минут"
// Hide swipe to refresh icon animation
swipeRefreshLayout.isRefreshing = false
}
// Execute the task after specified time
handler.postDelayed(
runnable, 3000.toLong()
)
}
swipeRefreshLayout.setColorSchemeResources(
android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light
)
}
}
Запустите пример и потяните экран сверх вниз, чтобы увидеть эффект обновления данных.
Обернём компоненты родительским элементом SwipeRefreshLayout. На панели инструментов данного компонента нет, поэтому придётся писать код вручную.
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/swipe_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textViewCat"
android:text="Hello Kitty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center"/>
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
Код:
package ru.alexanderklimov.swipe;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import java.util.Random;
public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {
private SwipeRefreshLayout mSwipeRefreshLayout;
private TextView mCatTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCatTextView = findViewById(R.id.textViewCat);
mSwipeRefreshLayout = findViewById(R.id.swipe_container);
mSwipeRefreshLayout.setOnRefreshListener(this);
mSwipeRefreshLayout.setColorSchemeResources(android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light);
// Альтернативный способ
// mSwipeRefreshLayout.setColorSchemeColors(
// Color.RED, Color.GREEN, Color.BLUE, Color.CYAN);
}
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// Отменяем анимацию обновления
mSwipeRefreshLayout.setRefreshing(false);
Random random = new Random();
mCatTextView.setText("Котика пора кормить. Его не кормили уже "
+ (1 + random.nextInt(10)) + " мин.");
}
}, 4000);
}
}
В примере реализуется интерфейс OnRefreshListener с методом onRefresh(), в котором следует обновить поступающие данные. В нашем случае просто генерируются случайные числа.
При первом появлении библиотеки использовался метод setColorScheme(), который объявлен устаревшим. Вместо него появились два новых метода setColorSchemeColors() и setColorSchemeResources(). Принцип остался тот же, вам нужно указать четыре цвета по константам Color.XXX или из ресурсов. Вы можете не использовать вызов метода с цветными линиями, тогда будет выводиться только чёрная линия по умолчанию.
Компонент достаточно интересный с занимательной анимацией. Вначале анимация представляла собой цветные полоски под заголовком программы, как представлено на видео.
Позже анимацию заменили в стиле Material Design, теперь это маленький кружочек, внутри которого крутятся цветные линии (или чёрная линия, если не использовать метод setColorSchemeResources() со цветами).
По такому же принципу обновляем данные в списке.
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.widget.SwipeRefreshLayout>
При каждой попытке обновить список будет добавляться текущая дата и время.
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private SwipeRefreshLayout mSwipeRefreshLayout;
private ListView mListView;
private List<String> mList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSwipeRefreshLayout = findViewById(R.id.swipeRefreshLayout);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
String currentDateTime = DateFormat.getDateTimeInstance().format(new Date());
mList.add(currentDateTime);
mListView.invalidateViews();
mSwipeRefreshLayout.setRefreshing(false);
}
});
mListView = findViewById(R.id.listView);
mList = new ArrayList<>();
ListAdapter mAdapter = new ArrayAdapter<>(
this, android.R.layout.simple_list_item_1, mList);
mListView.setAdapter(mAdapter);
}
}
Не забывайте, что обновление может занимать длительное время и использовать сеть для получения данных. Поэтому следует позаботиться о выполнении в другом потоке.
vaigunth/card-printer: Pull down to refresh - card printer
Cleveroad/FireworkyPullToRefresh: Let's try to refresh your data with our library! - интересный эффект обновления.