Android 中使用 Shimmer 实现内容占位符动画
介绍
什么是 Android 中使用 Shimmer 实现的内容占位符动画?
在 Android 应用中,有很多不同的方法可以显示加载指示器,例如进度条、水平加载条等等。类似地,Shimmer View 也是一种加载指示器,我们可以用它来显示应用中的加载屏幕。
Shimmer View 的实现
我们将创建一个简单的应用程序,从 API 加载一些数据,并使用 Shimmer 添加加载指示器作为内容占位符动画。我们将遵循分步指南在 Android 应用中实现 Shimmer View。
步骤 1:在 Android Studio 中创建一个新项目
按照下图所示导航到 Android Studio。在下图中,点击“新建项目”以创建一个新的 Android Studio 项目。
点击“新建项目”后,您将看到以下屏幕。
在这个屏幕中,我们只需选择“Empty Activity”并点击“Next”。点击“Next”后,您将看到以下屏幕。
在这个屏幕中,我们只需指定项目名称。然后包名将自动生成。
注意 - 确保选择 Kotlin 作为语言。
指定所有详细信息后,点击“Finish”以创建一个新的 Android Studio 项目。
项目创建完成后,我们将看到打开的两个文件:activity_main.xml 和 MainActivity.kt 文件。
步骤 2:添加依赖项以使用 Shimmer View 和 Volley
导航到 app>Gradle Scripts>build.gradle 文件>dependencies 部分,并向其中添加以下依赖项。代码中添加了注释,以便更详细地了解。
// volley is used for json parsing. implementation 'com.android.volley:volley:1.2.0' // shimmer is use to displaying loading indicatr implementation 'com.facebook.shimmer:shimmer:0.5.0'
添加依赖项后,只需同步项目即可安装它。
步骤 3:使用 activity_main.xml。
导航到 activity_main.xml。如果此文件不可见,则打开此文件。在左侧窗格中导航到 app>res>layout>activity_main.xml 以打开此文件。打开此文件后,向其中添加以下代码。代码中添加了注释,以便更详细地了解。
语法
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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=".MainActivity"> <!-- creating a relative layout on below line--> <RelativeLayout android:id="@+id/idRLView" android:layout_width="match_parent" android:layout_height="wrap_content" android:visibility="gone"> <!-- creating an image view for image on below line--> <ImageView android:id="@+id/idIVImage" android:layout_width="200dp" android:layout_height="100dp" android:layout_centerHorizontal="true" android:layout_marginTop="150dp" android:src="@drawable/gptimg" /> <!-- creating text view for name on below line--> <TextView android:id="@+id/idTVTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/idIVImage" android:layout_centerHorizontal="true" android:layout_margin="10dp" android:gravity="center" android:padding="4dp" android:text="Title" android:textAlignment="center" android:textColor="@color/black" android:textSize="20sp" android:textStyle="bold" /> <!-- creating a text view for description on below line--> <TextView android:id="@+id/idTVDescription" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/idTVTitle" android:layout_centerHorizontal="true" android:layout_margin="10dp" android:gravity="center" android:padding="4dp" android:text="Description" android:textAlignment="center" android:textColor="@color/black" android:textSize="15sp" android:textStyle="bold" /> <!-- creating an address for text view on below line--> <TextView android:id="@+id/idTVAddress" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/idTVDescription" android:layout_centerHorizontal="true" android:layout_marginStart="10dp" android:layout_marginEnd="10dp" android:gravity="center" android:padding="4dp" android:text="Address" android:textAlignment="center" android:textColor="@color/black" android:textSize="15sp" android:textStyle="normal" /> </RelativeLayout> <!-- creating a shimmer frame layout on below line--> <com.facebook.shimmer.ShimmerFrameLayout android:id="@+id/shimmerLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:animateLayoutChanges="true" android:animationCache="true" app:shimmer_repeat_mode="restart" app:shimmer_shape="radial"> <!--creating a relative layout on below line--> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <!--creating an image view on below line--> <ImageView android:id="@+id/idIVSImg" android:layout_width="200dp" android:layout_height="100dp" android:layout_centerHorizontal="true" android:layout_marginTop="150dp" android:background="#B3B3B3" /> <!-- creating an empty text view on below line--> <TextView android:id="@+id/idTVSTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/idIVSImg" android:layout_centerHorizontal="true" android:layout_marginStart="10dp" android:layout_marginTop="10dp" android:layout_marginEnd="10dp" android:layout_marginBottom="10dp" android:background="#B3B3B3" android:gravity="center" android:padding="4dp" android:textAlignment="center" android:textSize="20sp" android:textStyle="bold" /> <!-- creating an empty text view on below line--> <TextView android:id="@+id/idTVSDescription" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/idTVSTitle" android:layout_centerHorizontal="true" android:layout_margin="10dp" android:background="#B3B3B3" android:gravity="center" android:padding="4dp" android:textAlignment="center" android:textSize="15sp" android:textStyle="bold" /> <!-- creating an empty text view for address on below line--> <TextView android:id="@+id/idTVSAddress" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/idTVSDescription" android:layout_centerHorizontal="true" android:layout_marginStart="10dp" android:layout_marginEnd="10dp" android:background="#B3B3B3" android:gravity="center" android:padding="4dp" android:textAlignment="center" android:textColor="@color/black" android:textSize="15sp" android:textStyle="bold" /> </RelativeLayout> </com.facebook.shimmer.ShimmerFrameLayout> </RelativeLayout>
说明 - 在上面的代码中,我们创建了一个 RelativeLayout 作为我们的根布局,在这个 RelativeLayout 内部,我们创建了一个 RelativeLayout 和一个 Shimmer Frame Layout。子 RelativeLayout 包含我们必须显示给用户的实际 UI,其中包含 TextView 和 ImageView。此外,还有一个 Shimmer Frame Layout,我们在其中创建了一个 ImageView 和 TextView。
最初,我们将 RelativeLayout 的可见性设置为 gone,Shimmer Frame Layout 的可见性设置为 visible。一旦我们从 API 接收到响应,我们将把 RelativeLayout 的可见性更改为 visible,并将 Shimmer Layout 的可见性更改为 Gone。
步骤 3:使用 MainActivity.kt
导航到 MainActivity.kt。如果此文件不可见,则打开此文件。在左侧窗格中导航到 app>java>您的应用程序包名>MainActivity.kt 以打开此文件。打开此文件后,向其中添加以下代码。代码中添加了注释,以便更详细地了解。
package com.example.gptapp import android.os.Bundle import android.util.Log import android.view.ContextMenu import android.view.MenuItem import android.view.View import android.widget.ImageView import android.widget.RelativeLayout import android.widget.TextView import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.android.volley.Request import com.android.volley.RequestQueue import com.android.volley.toolbox.JsonObjectRequest import com.android.volley.toolbox.Volley import com.facebook.shimmer.ShimmerFrameLayout import com.squareup.picasso.Picasso import kotlin.math.log class MainActivity : AppCompatActivity() { // creating variables on below line. lateinit var originRL: RelativeLayout lateinit var shimmerView: ShimmerFrameLayout lateinit var logoIV: ImageView lateinit var nameTV: TextView lateinit var addressTV: TextView lateinit var descTV: TextView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // initializing all variables with their ids on below line. originRL = findViewById(R.id.idRLView) shimmerView = findViewById(R.id.shimmerLayout) logoIV = findViewById(R.id.idIVImage) nameTV = findViewById(R.id.idTVTitle) addressTV = findViewById(R.id.idTVAddress) descTV = findViewById(R.id.idTVDescription) // calling method to read data from API. readData() } private fun readData() { // creating a variable for request queue on below line. val queue: RequestQueue = Volley.newRequestQueue(applicationContext) // creating a variable for aoi url on below line. val apiUrl = "https://www.jsonkeeper.com/b/AR3Q" // making a json object request and passing method as get to get the response from API. val request = JsonObjectRequest(Request.Method.GET, apiUrl, null, { response -> // on below line extracting data from our json object. val title = response.getString("name") val imgUrl = response.getString("imgUrl") val description = response.getString("description") val address = response.getString("address") // on below line changing visibility for oue shimmer view and original relative layout. shimmerView.visibility = View.GONE originRL.visibility = View.VISIBLE // setting data to our text views and image view on below line. . nameTV.text = title Picasso.get().load(imgUrl).into(logoIV) descTV.text = description addressTV.text = address }, { error -> // displaying a toast message if we fail to get response from API. Toast.makeText(this@MainActivity, "Fail to get response", Toast.LENGTH_SHORT) .show() }) // at last we are adding // our request to our queue. queue.add(request) } }
说明 - 在我们的 MainActivity.kt 文件中,我们首先为所有视图(例如 RelativeLayout、TextView 和 ImageView)创建变量。然后,在我们的 onCreate 方法中,我们使用它们的 ID 初始化这些视图。
初始化这些视图后,我们创建了一个名为 readData() 的单独方法,在这个方法中,我们将进行 API 调用以从我们的 API 读取数据。在 readData() 方法中,我们创建了一个 requestQueue 变量,用于进行 API 调用请求。之后,我们创建了一个变量来存储我们的 API url。然后,我们进行一个 Json 对象请求来进行 API 调用。在这个 json 对象请求方法中,有两个方法,一个是 response,用于从 API 获取响应,另一个是 Error,如果 API 无法返回任何响应,则会提供错误。在 response 方法中获取响应后,我们将从响应中提取数据,并将该数据设置为我们的 TextView 和 ImageView。之后,我们将 Shimmer 视图的可见性更改为 gone,并将 RelativeLayout 的可见性更改为 visible,以便向用户显示实际的 UI。在 error 方法中,我们显示一个吐司消息以向用户显示错误。最后,我们将请求添加到队列中以进行 API 调用。
添加上述代码后,我们只需点击顶部栏中的绿色图标即可在移动设备上运行我们的应用程序。
注意 - 确保您已连接到您的真实设备或模拟器。
结论
在本教程中,我们学习了什么是 Android 中的吐司消息,以及如何使用它在 Android 应用程序中向用户显示简短消息。我们学习了如何创建一个新的 Android Studio 项目,然后处理 UI 并为我们的按钮添加功能,以便在用户点击按钮时显示吐司消息。