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 併為我們的按鈕新增功能,以便在使用者點選按鈕時顯示吐司訊息。

更新於:2023年3月14日

630 次檢視

啟動您的 職業生涯

完成課程獲得認證

開始學習
廣告
© . All rights reserved.