Что такое эффект мерцания?
Это эффект для отображения состояния загрузки. Вместо того чтобы использовать прогресс, эффект Shimmer создает лучший дизайн для ux. Он имитирует макет страницы, показывая ее элементы в форме, похожей на реальный контент, по мере его загрузки и появления (т.е. когда позволяет сетевая задержка).
Как реализовать это на Android?
Существует библиотека для Android, Shimmer, которая предоставляет простой способ добавить эффект мерцания к любому представлению в вашем приложении для Android.
Итак, давайте начнем!
Сначала включите зависимость библиотеки:
dependencies {
// Shimmer
implementation 'com.facebook.shimmer:shimmer:0.5.0'
}
Теперь создайте макет list_placeholder_layout.xml
, который будет действовать как заполнитель во время загрузки содержимого.
В моем примере у меня есть imageView для отображения изображения животного и два textView для имени и типа. Таким образом, макет выглядит примерно так:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="10dp">
<androidx.cardview.widget.CardView
android:id="@+id/animal_image"
android:layout_width="120dp"
android:layout_height="150dp"
android:backgroundTint="@color/gray"
app:cardCornerRadius="20dp"
app:cardElevation="4dp"
app:cardUseCompatPadding="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.cardview.widget.CardView
android:id="@+id/animal_name"
android:layout_width="120dp"
android:layout_height="30dp"
android:layout_marginStart="20dp"
android:layout_marginTop="30dp"
android:backgroundTint="@color/gray"
app:cardCornerRadius="10dp"
app:cardElevation="4dp"
app:cardUseCompatPadding="true"
app:layout_constraintStart_toEndOf="@id/animal_image"
app:layout_constraintTop_toTopOf="parent" />
<androidx.cardview.widget.CardView
android:id="@+id/animal_type"
android:layout_width="120dp"
android:layout_height="30dp"
android:layout_marginStart="20dp"
android:layout_marginTop="20dp"
android:backgroundTint="@color/gray"
app:cardCornerRadius="10dp"
app:cardElevation="4dp"
app:cardUseCompatPadding="true"
app:layout_constraintStart_toEndOf="@id/animal_image"
app:layout_constraintTop_toBottomOf="@id/animal_name" />
</androidx.constraintlayout.widget.ConstraintLayout>
После создания макета нам нужно включить его в основной макет activity_main
, где расположен recyclerView.
Для этого мы включаем <com.facebook.shimmer.ShimmerFrameLayout>
.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.MainActivity">
<com.facebook.shimmer.ShimmerFrameLayout
android:id="@+id/shimmer_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:duration="800">
<!-- Adding 8 rows of placeholders -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="@layout/list_placeholder_layout" />
<include layout="@layout/list_placeholder_layout" />
<include layout="@layout/list_placeholder_layout" />
<include layout="@layout/list_placeholder_layout" />
<include layout="@layout/list_placeholder_layout" />
<include layout="@layout/list_placeholder_layout" />
<include layout="@layout/list_placeholder_layout" />
<include layout="@layout/list_placeholder_layout" />
</LinearLayout>
</com.facebook.shimmer.ShimmerFrameLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="5dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
На следующем этапе нам просто нужно указать Shimmer, когда начинать и останавливать анимацию.
- Мы должны запустить Shimmer, когда получим список элементов.
binding.shimmerView.startShimmer()
- Мы должны остановить мерцание, когда получим список элементов.
binding.shimmerView.stopShimmer()
.
Также мы должны скрыть видимость макета рамки Shimmer, когда получим список элементов.
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val viewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
//Start Shimmer
binding.shimmerView.startShimmer()
viewModel.getAnimals(10)
viewModel.animalList.observe(this) {
initRecyclerView(it)
}
}
private fun initRecyclerView(animalList: List<Animal>) {
binding.recyclerView.layoutManager = LinearLayoutManager(this)
val adapter = AnimalAdapter(animalList)
binding.recyclerView.adapter = adapter
//Stop Shimmer
binding.shimmerView.stopShimmer()
//Hide Shimmer view
binding.shimmerView.isVisible = false
}
}
И это все!
Если вы хотите посмотреть весь проект, то вот ссылка: ShimmerEffectAndroid
Не забудьте поставить лайк и поделиться! Спасибо! 🙂
Полезные ссылки:
- https://facebook.github.io/shimmer-android/