当数据从网络加载时,您可能已经注意到 Facebook 移动应用程序中的微光效果。Shimmer 库由 Facebook 创建,用于在加载数据时显示动画,以使 UI 更有趣和美观,而不是使用传统的 ProgressBar。Facebook 后来发布了一个名为Shimmer 的开源库,我们可以使用它来实现 Shimmer Effect Placeholder。
Shimmer for Android 是作为布局实现的,这意味着您可以简单地将任何视图嵌套在 ShimmerFrameLayout 中。
以下是 Android 应用程序中的 Shimmer 效果示例:
在本文章中,我们将演示如何在您的 Android 应用程序中使用 Shimmer。我们将使用Fast-Android-Networking从 API 获取数据,然后在 RecyclerView 中显示数据。所以让我们开始吧!
在 Android App 中实现 Shimmer 的步骤
在这里,我们将设置 Android 项目。
创建项目
- 启动一个新的 Android Studio 项目
- 选择空活动和下一步
- 名称:Android-Shimmer-Example
- 包名:com.mindorks.example.shimmer
- 语言:Kotlin
- 结束
- 您的起始项目现已准备就绪
添加依赖项
在您的应用级别 build.gradle 中添加以下依赖项并同步。
implementation 'com.facebook.shimmer:shimmer:0.1.0@aar'
implementation "androidx.recyclerview:recyclerview:1.1.0"
implementation 'com.amitshekhar.android:android-networking:1.0.2'
implementation 'com.github.bumptech.glide:glide:4.11.0'
第一行是 Facebook 的微光依赖。我们添加了许多其他依赖项,这些依赖项用于Fast-Android-Networking、RecyclerView 和 Glide,它们将在我们的项目中使用。
现在,在布局文件夹中添加 item_layout.xml 并添加以下代码:
<?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:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="60dp">
<ImageView
android:id="@+id/imageViewAvatar"
android:layout_width="60dp"
android:layout_height="0dp"
android:padding="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/textViewUserName"
style="@style/TextAppearance.AppCompat.Large"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="4dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageViewAvatar"
app:layout_constraintTop_toTopOf="parent"
tools:text="MindOrks" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/textViewUserEmail"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/textViewUserName"
app:layout_constraintTop_toBottomOf="@+id/textViewUserName"
tools:text="MindOrks" />
</androidx.constraintlayout.widget.ConstraintLayout>
现在,在布局文件夹中添加 shimmer_placeholder_layout.xml 并添加以下代码:
<?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:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="60dp">
<ImageView
android:id="@+id/imageViewAvatar"
android:layout_width="60dp"
android:layout_height="0dp"
android:background="@color/colorGrey"
android:padding="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/textViewUserName"
style="@style/TextAppearance.AppCompat.Large"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="4dp"
android:background="@color/colorGrey"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageViewAvatar"
app:layout_constraintTop_toTopOf="parent"
tools:text="MindOrks" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/textViewUserEmail"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/colorGrey"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/textViewUserName"
app:layout_constraintTop_toBottomOf="@+id/textViewUserName"
tools:text="MindOrks" />
</androidx.constraintlayout.widget.ConstraintLayout>
在上面的 XML 中,需要注意的重要一点是背景颜色应该是灰色或任何非白色的颜色,因为如果背景是白色的,闪烁效果将不可见。
不要忘记在 colors.xml 中添加颜色,如下所示:
<color name="colorGrey">#dddddd</color>
现在,打开activity_main.xml文件并添加以下代码:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.facebook.shimmer.ShimmerFrameLayout
android:id="@+id/shimmerFrameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:orientation="vertical">
<!-- Adding 15 rows of placeholders -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="@layout/shimmer_placeholder_layout" />
<include layout="@layout/shimmer_placeholder_layout" />
<include layout="@layout/shimmer_placeholder_layout" />
<include layout="@layout/shimmer_placeholder_layout" />
<include layout="@layout/shimmer_placeholder_layout" />
<include layout="@layout/shimmer_placeholder_layout" />
<include layout="@layout/shimmer_placeholder_layout" />
<include layout="@layout/shimmer_placeholder_layout" />
<include layout="@layout/shimmer_placeholder_layout" />
<include layout="@layout/shimmer_placeholder_layout" />
<include layout="@layout/shimmer_placeholder_layout" />
<include layout="@layout/shimmer_placeholder_layout" />
<include layout="@layout/shimmer_placeholder_layout" />
<include layout="@layout/shimmer_placeholder_layout" />
<include layout="@layout/shimmer_placeholder_layout" />
</LinearLayout>
</com.facebook.shimmer.ShimmerFrameLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>
理解上面的代码:
- 我们添加了ShimmerFrameLayout。
- 接下来,在 ShimmerFrameLayout 中,我们需要在**LinearLayout中包含一些占位符布局(shimmer_placeholder_layout)。这些是类似于我们的 RecyclerView 布局的空白布局,在网络调用进行时将在其上执行闪烁效果。请注意,我们已多次添加这些占位符布局以将外观创建为列表。
- RecyclerView将显示在执行网络请求并从 API 接收内容后获取的数据列表。
现在,创建一个数据类 User,如下所示:
package com.mindorks.example.shimmer
import com.google.gson.annotations.SerializedName
data class User(
@SerializedName("id")
val id: Int = 0,
@SerializedName("name")
val name: String = "",
@SerializedName("email")
val email: String = "",
@SerializedName("avatar")
val avatar: String = ""
)
现在,创建一个 Kotlin 类 MainAdapter 并添加以下代码。
package com.mindorks.example.shimmer
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.item_layout.view.*
class MainAdapter(
private val users: ArrayList<User>
) : RecyclerView.Adapter<MainAdapter.DataViewHolder>() {
class DataViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(user: User) {
itemView.textViewUserName.text = user.name
itemView.textViewUserEmail.text = user.email
Glide.with(itemView.imageViewAvatar.context)
.load(user.avatar)
.into(itemView.imageViewAvatar)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
DataViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.item_layout, parent,
false
)
)
override fun getItemCount(): Int = users.size
override fun onBindViewHolder(holder: DataViewHolder, position: Int) =
holder.bind(users[position])
fun addData(list: List<User>) {
users.addAll(list)
}
}
现在打开 MainActivity 并添加以下代码:
package com.mindorks.example.shimmer
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.androidnetworking.AndroidNetworking
import com.androidnetworking.error.ANError
import com.androidnetworking.interfaces.ParsedRequestListener
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
private lateinit var adapter: MainAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupUI()
setupAPICall()
}
private fun setupUI() {
recyclerView.layoutManager = LinearLayoutManager(this)
adapter = MainAdapter(arrayListOf())
recyclerView.addItemDecoration(
DividerItemDecoration(
recyclerView.context,
(recyclerView.layoutManager as LinearLayoutManager).orientation
)
)
recyclerView.adapter = adapter
}
private fun setupAPICall() {
AndroidNetworking.initialize(applicationContext)
AndroidNetworking.get("https://5e510330f2c0d300147c034c.mockapi.io/users")
.build()
.getAsObjectList(User::class.java, object : ParsedRequestListener<List<User>> {
override fun onResponse(users: List<User>) {
shimmerFrameLayout.stopShimmerAnimation()
shimmerFrameLayout.visibility = View.GONE
recyclerView.visibility = View.VISIBLE
adapter.addData(users)
adapter.notifyDataSetChanged()
}
override fun onError(anError: ANError) {
shimmerFrameLayout.visibility = View.GONE
Toast.makeText(this@MainActivity, "Something Went Wrong", Toast.LENGTH_LONG).show()
}
})
}
override fun onResume() {
super.onResume()
shimmerFrameLayout.startShimmerAnimation()
}
override fun onPause() {
shimmerFrameLayout.stopShimmerAnimation()
super.onPause()
}
}
为了在我们的应用程序打开后立即开始闪烁效果,我们在 onResume() 活动生命周期方法中添加 shimmerFrameLayout .startShimmerAnimation() 并在 onPause() 活动生命周期方法中添加 shimmerFrameLayout .stopShimmerAnimation() 来停止它**。**
为了在网络请求执行并在 recyclerview 中设置数据后停止闪烁效果并使 recyclerview 可见,我们添加了:
shimmerFrameLayout.stopShimmerAnimation()
shimmerFrameLayout.visibility = View.GONE
recyclerView.visibility = View.VISIBLE
最后,在您的项目中添加 Internet 权限。在 AndroidManifest.xml 中添加以下内容:
<uses-permission android:name="android.permission.INTERNET" />
现在,运行应用程序,您将看到以下结果