[Android / Kotlin] Animation Interpolator를 사용하여 로딩 화면 만들기

Subeen·2024년 2월 17일
0

Android

목록 보기
59/73

이번 팀과제인 MomenTravel은 Youtube Api를 사용하여 여행지와 관심사를 선택하면 해당 키워드로 필터링 된 동영상을 보여주는 앱이다. 키워드로 api를 호출하고 결과 리스트를 보여주는 과정에 로딩 화면이 있으면 좋겠다고 생각하여 세 개의 점이 번갈아가며 크기가 커지는 로딩 애니메이션을 만들었다.

결과 화면

fragment_loading.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:background="@color/white"
    android:gravity="center"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginBottom="16dp"
        android:layout_weight="1"
        android:gravity="center|bottom"
        android:orientation="horizontal"
        android:padding="10dp">

        <ImageView
            android:id="@+id/fitst_dot"
            android:layout_width="16dp"
            android:layout_height="16dp"
            android:layout_margin="4dp"
            android:background="@drawable/circle_shape" />

        <ImageView
            android:id="@+id/second_dot"
            android:layout_width="16dp"
            android:layout_height="16dp"
            android:layout_margin="4dp"
            android:background="@drawable/circle_shape" />

        <ImageView
            android:id="@+id/third_dot"
            android:layout_width="16dp"
            android:layout_height="16dp"
            android:layout_margin="4dp"
            android:background="@drawable/circle_shape" />


    </LinearLayout>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="center|top"
        android:text="회원님을 위한 동영상을 찾는 중..."
        android:textSize="14sp" />


</LinearLayout>

LoadingDialogFragment.kt

Interpolator는 시작시점과 종료시점까지의 변화 과정을 어떤식으로 표현 할 것 인가에 대한 것을 Animation으로 정의한 것이다.

class LoadingDialogFragment : DialogFragment() {

    private var _binding: FragmentLoadingBinding? = null
    private val binding get() = _binding!!

    private val dots by lazy {
        listOf(binding.fitstDot, binding.secondDot, binding.thirdDot)
    }
    private val handler = Handler(Looper.getMainLooper())

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = FragmentLoadingBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        setUpWindowAttributes()
        startLoadingAnimation()
    }

    // Dialog Window 속성을 구성
    private fun setUpWindowAttributes() {
        val params = dialog?.window?.attributes
        params?.width = ViewGroup.LayoutParams.MATCH_PARENT
        params?.height = ViewGroup.LayoutParams.MATCH_PARENT
        dialog?.window?.attributes = params
        dialog?.window?.setBackgroundDrawableResource(android.R.color.white)
    }

    // 점 이미지뷰의 반복 애니메이션을 시작
    private fun startLoadingAnimation() {
        var dotIndex = 0
        handler.post(object : Runnable {
            override fun run() {
                animateDot(dots[dotIndex])
                dotIndex = (dotIndex + 1) % dots.size
                handler.postDelayed(this, 500) // 500ms 간격으로 변경
            }
        })
    }

    // 점 이미지뷰의 크기 조정 애니메이션을 수행
    private fun animateDot(dot: ImageView) {
        val scaleX = ObjectAnimator.ofFloat(dot, "scaleX", 1.0f, 1.5f, 1.0f)
        val scaleY = ObjectAnimator.ofFloat(dot, "scaleY", 1.0f, 1.5f, 1.0f)

        /**
         * AccelerateDecelerateInterpolator : AccelerateInterpolator와 DecelerateInterpolator를 합친 효과를 나타낸다.
         * AccelerateInterpolator : 시작지점에서 가속하여 종료지점에 도달한다.
         * DecelerateInterpolator : 종료지점에 도달할 수록 속도가 느려진다.
         */
        scaleX.interpolator = AccelerateDecelerateInterpolator()
        scaleY.interpolator = AccelerateDecelerateInterpolator()

        scaleX.duration = 500 // 애니메이션 지속 시간 (ms)
        scaleY.duration = 500 // 애니메이션 지속 시간 (ms)

        scaleX.start()
        scaleY.start()
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

LoadingDialogFragment 사용하기

	// Api 호출이 시작되면 LoadingDialogFragment를 보여준다.  
    private fun showLoadingActivity() {
        loadingDialog = LoadingDialogFragment()
        loadingDialog?.show(parentFragmentManager, "LoadingDialog")
    }
    
    // 데이터 로딩이 완료 되면 LoadingDialogFragment를 dismiss 한다. 
    private fun closeLoadingActivity() {
        loadingDialog?.dismiss()
    }
profile
개발 공부 기록 🌱

0개의 댓글