본문 바로가기
Android

Progress Indicator

by 들풀민들레 2022. 8. 1.

 

수업시간에 나온 질문에 도움을 주기 위해 작성된 글입니다.

 

Progress Indicator

 

화면을 구성하면서 Progress Indicator 를 출력해야 하는 경우는 많은 것 같습니다. 대부분 서버에서 데이터를 출력해야 하는 경우, 서버에서 데이터가 전달되기 전까지 progress Indicator 를 출력하고 데이터가 전달된 후에 실제 데이터를 화면에 출력시키는 식으로 구성을 많이 합니다.

 

Progress Indicator Android Platform API 에서 제공되는 View 되 있고 외부 라이브러리도 꾀 있는 것 같습니다. 이곳에서는 Android 기본 Progress Indicator Glide, Shimmer 등을 이용 방법에 대해 살펴 보겠습니다.

 

 

Android Platform 에서 제공하는 Progress Indicator bar 형태인 LinearProgressIndicator 와 원 형태인CircularProgressIndicator 가 있습니다.

 

<com.google.android.material.progressindicator.CircularProgressIndicator
    android:id="@+id/circularProgress"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:indeterminate="true"/>

<com.google.android.material.progressindicator.LinearProgressIndicator
    android:id="@+id/linearProgress"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="50dp"
    android:layout_marginRight="50dp"
    app:trackCornerRadius="10dp"
    android:max="100"/>

 

CoroutineScope(Dispatchers.Main).launch {
    for(i in 0..100 step 10) {
        Log.d("kkang", "$i")
        binding.linearProgress.progress = i
        delay(1000)
    }
}

 

Shimmer

Shimmer effect for Android

 

http://facebook.github.io/shimmer-android/

 

https://codinginfinite.com/facebook-shimmer-effect-android-example/

 

아래와 같이 View 가 출력되어야 하는 경우, 이를 지원하는 외부 라이브러리가 몇 개 보이는데 facebook 에서 제공되는 라이브러리가 가장 많이 사용되는 것으로 보입니다.

 

 

설정

 

implementation 'com.facebook.shimmer:shimmer:0.5.0'

 

layout xml 구성

 

SimmerFrameLayout 을 이용하는데 SimmerFrameLayout Child 뷰들을 위의 그림처럼 출력시키는 뷰입니다.

 

다양하게 사용될 수 있을 것 같은데 SimmerFrameLayout 에 의해 화면에 Progress 가 먼저 보이다가 원래 출력되어야 하는 뷰가 보이는 형태로 제공하고자 한다면 아래처럼 Layout 을 구성해 볼 수 있을 것 같습니다.

 

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:shimmer="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.facebook.shimmer.ShimmerFrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/parentShimmerLayout"
        shimmer:duration="700">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <include layout="@layout/shimmer_view"/>

            <include layout="@layout/shimmer_view"/>

            <include layout="@layout/shimmer_view"/>

        </LinearLayout>

    </com.facebook.shimmer.ShimmerFrameLayout>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/shader_recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>

</RelativeLayout>

위의 예를 보면 루트 레이아웃에 SimmerFrameLayout RecyclerView 가 추가되있습니다. SimmerFrameLayout 에 의한 Progress 가 먼저 보이다가 어느 순간 SimmerFrameLayout  visibility 값을 GONE 으로 처리해서 RecyclerView 만 보이게 하고자 하는 의도입니다.

 

SimmerFrameLayout 하위의 뷰들은 progress 진행 시 보여야 하는 화면의 뷰입니다. 아래처럼 화면이 출력되게 됩니다.

 

서버에서 데이터가 전달된 순간 등, 더 이상 SimmerFrameLayout 에 의해 화면이 출력될 필요가 없는 경우 아래처럼 SimmerFrameLayout 의 애니메이션 기능을 stop 시키고 visibility 값 조정으로  화면에서 안보이게 처리합니다.

 

binding.parentShimmerLayout.visibility = View.GONE
binding.parentShimmerLayout.stopShimmer()

 

Glide, placeholder

 

이미지 다운로드하는 경우 실제 이미지가 다운로드 되기 전에 보여줄 placeholder 이미지 지정은 쉽게 placeholder() 함수에 Drawable 이미지를 지정해 주면 됩니다.

 

Glide.with(this)
            .load(url)
            .placeholder(R.drawable.placeholder)
            .fitCenter()
            .into(binding.progressImageView);

 

위처럼 지정하면 placeholder 에 지정한 이미지가 먼저 보이다가 load 에 명시한 이미지 다운로드가 완료되면 다운로드 된 이미지가 보이게 됩니다. 그런데 일반적으로 placeholder gif animation 에 의한 로딩 이미지를 출력하고자 할 것이고 이 경우 아래처럼 thumbnail 을 통해 이미지를 지정해 주면 됩니다.

 

Glide.with(this)
            .load(url)
            .thumbnail(Glide.with(this).load(R.drawable.progress))
		.fitCenter()
            .into(binding.progressImageView);