Android에서 Text를 Animation처럼 표시

이 기사는 Goodpatch Advent Calendar 2018 11일째 기사입니다.

올해 되돌아



테두리가 비어 있었기 때문에 올해를 되돌아 보면 안드로이드 개발로 애니메이션을 만드는 경우가 많았기 때문에
오늘은 그쪽을 소개하겠습니다.

개요



텍스트 숫자가 빠르게 업데이트되는 애니메이션입니다.


대상자


  • 숫자가 표시된 텍스트 View를 지정한 시간에 표시시키고 싶은 분
  • 디자이너로부터 「수치를 듀룰루린이라고 표시」라고 말해진 분

  • 코드


        /**
         * start: アニメーション開始時の数値
         * end: アニメーション終了時の数値
         * duration: アニメーション表示期間
         * period: 更新時間
         */
        private fun textAnimation(start: Int, end: Int, duration: Int, period: Long) {
            val blockValue = ((end - start) * period / duration).toInt()
            val timer = Timer()
            val handler = Handler(Looper.getMainLooper())
            val animationText: TextView = this.findViewById(R.id.animationText)
            timer.schedule(object : TimerTask() {
                var value = 0
                override fun run() = if (value < end) {
                    handler.post {
                        animationText.text = "$value %"
                    }
                    value += blockValue
                } else {
                    value = end
                    timer.cancel()
                }
            }, 0, period)
        }
    

    요약


    1. 表示終了までにカウントアップする数値を計算する
    2. Timerを使って更新タイミングを指定(短ければ短いほど細かく動く)
    3. 数値が超えたタイミングで更新処理を止める
    

    이 애니메이션이 처리되는 타이밍은 화면이 생성되는 타이밍이나 데이터가 갱신되어 화면을 다시 그려지는 타이밍만을 추천합니다.
    화면이 열린 타이밍마다 애니메이션을 실행하면 기분 좋게 느낍니다.

    추가



    2020년 어드벤트 캘린더를 준비하고 있는 동안 과거 기사를 되돌아보면
    별로 갈 수 없다고 생각했으므로 수정하겠습니다.

    과거 카운트 업을 할 때 자신이 카운트 업하는 코드를 작성했습니다.
    실은 그런 일을 할 필요는 없고 ValueAnimation 를 사용해 표현하는 것이 가능하기 때문에
    업데이트하겠습니다.

    이번 코드는 다음과 같습니다. Animation 의 값을 View 에 반영해 갈 뿐이므로
    빨리 사용하고 싶을 때 사용할 수 있다고 생각합니다.
    // kotlin
    import android.animation.ValueAnimator
    import android.os.Bundle
    import androidx.appcompat.app.AppCompatActivity
    import androidx.databinding.DataBindingUtil
    import jp.co.goodpatch.databinding.ActivityMainBinding
    
    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            val binding =
                DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
    
            val animation = ValueAnimator.ofInt(0, 100)
            animation.duration = 2000
            animation.addUpdateListener {
                binding.textView.text = "${it.animatedValue}"
            }
    
            binding.button.setOnClickListener {
                animation.start()
            }
        }
    }
    

    레이아웃은 다음과 같습니다.
    <?xml version="1.0" encoding="utf-8"?>
    <layout 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">
    
        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context=".MainActivity">
    
            <androidx.appcompat.widget.AppCompatTextView
                android:id="@+id/text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="end"
                android:text="0"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toStartOf="@id/percent_text_view"
                app:layout_constraintTop_toTopOf="parent" />
    
    
            <androidx.appcompat.widget.AppCompatTextView
                android:id="@+id/percent_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="%"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintTop_toTopOf="parent" />
    
            <Button
                android:id="@+id/button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="START"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/text_view" />
    
        </androidx.constraintlayout.widget.ConstraintLayout>
    </layout>
    

    실행결과는 이런 느낌이

    좋은 웹페이지 즐겨찾기