0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Android/Kotlin】円を拡大するアニメーションの実装方法

Last updated at Posted at 2019-12-03

基本画面

 2019-12-03 12.20.32.png
  • FrameLayoutをmatch/matchで設定しています。
  • 円のカスタムビューをvisible=GONEで設定しています。
  • 星のImageViewを2種類おいています。
  • 星をクリックすると、円が拡大描画されていきます。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <FrameLayout
        android:id="@+id/back_color"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center">

        <com.kiyota.scaleanimationapp.CircleCustomView
            android:id="@+id/main_circle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:visibility="gone"></com.kiyota.scaleanimationapp.CircleCustomView>

        <ImageView
            android:id="@+id/star_pink"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_gravity="center"
            android:src="@drawable/ic_star_pink"></ImageView>

        <ImageView
            android:id="@+id/star_blue"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_gravity="center"
            android:layout_marginTop="100dp"
            android:src="@drawable/ic_star"></ImageView>
    </FrameLayout>

</androidx.appcompat.widget.LinearLayoutCompat>
CircleCustomView.kt
class CircleCustomView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
    /**
     * サークルの色
     */
    private val paint = Paint()
    /**
     * サークルの座標位置
     */
    private val rect = RectF()
    /**
     * サークルの円周の長さ
     */
    private var angle = 360F
    /**
     * 中心座標(x)
     */
    private var x: Int = 0
    /**
     * 中心座標(y)
     */
    private var y: Int = 0
    /**
     * 初回フラグ
     */
    var isInit = true

    /**
     * コンパニオンオブジェクト
     */
    companion object {
        /**
         * サークルの開始位置
         */
        private const val angleTarget = 0F
    }

    /**
     * コンストラクタ
     */
    init {
        // サークルの幅
        this.paint.isAntiAlias = true
        this.paint.style = Paint.Style.FILL_AND_STROKE
        // サークルの色
        this.paint.color = (context.resources.getColor(R.color.star_color))
    }

    /**
     * ビュー描画メソッド
     *
     * @param canvas 描画領域
     */
    @SuppressLint("CanvasSize")
    public override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        // 初回は中心スタート
        if (isInit) {
            // サークル開始地点(中央揃え)
            this.x = canvas.width / 2
            this.y = canvas.height / 2
            isInit = false
        }
        // サークルの背景色(透明)
        canvas.drawColor(this.context.resources.getColor(R.color.color_back_circle))
        // サークルの半径()大きさ
        var radius = 40
        val left = this.x - radius
        val top = this.y - radius
        val right = this.x + radius
        val bottom = this.y + radius
        // サークルの領域設定
        this.rect.set(left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat())
        // サークルの描画
        canvas.drawArc(this.rect, angleTarget, this.angle, false, this.paint)
    }

    /**
     * 中心座標変更メソッド
     */
    fun changeCenter(x: Int, y: Int) {
        // サークルの中心座標
        this.x = x
        this.y = y
    }

    /**
     * サークル色変更メソッド
     *
     * @param index 押されたボタンの番号
     */
    fun changeColor(index: Int) {
        when (index) {
            0 -> {
                this.paint.color = context.resources.getColor(R.color.colorAccent)
            }
            1 -> {
                this.paint.color = context.resources.getColor(R.color.star_color)
            }
            else -> {
                this.paint.color = context.resources.getColor(R.color.colorPrimary)
            }
        }
    }
}

画面の中心で円を拡大する場合(ピンク)

  • 中心座標(540 , 792)
  • pivot(0.5f , 0.5f)
 2019-12-03 12.00.20.png
MainActivity.kt
package com.kiyota.scaleanimationapp

class MainActivity : AppCompatActivity(), Animation.AnimationListener {

    private var index = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // クリックされたらアニメーションをスタートする
        star_pink.setOnClickListener {
            index = 0
            // 端末(Nexus5x)の中心座標が(540,792)という意味です
            startScalingXml(540, 792, index)
        }
        star_blue.setOnClickListener {
            index = 1
            startScalingXml(540, 792, index)
        }
    }

    /**
     * サークル拡大アニメーションメソッド
     *
     * @param x x座標
     * @param y y座標
     * @param index クリックされたビューの順番
     */
    private fun startScalingXml(x: Int, y: Int, index: Int) {
        main_circle.changeCenter(x, y)
        main_circle.changeColor(index)
        var scaleAnimation = ScaleAnimation(
            1.0f, 30.0f, 1.0f, 30.0f,
            Animation.RELATIVE_TO_SELF,
            0.5f, Animation.RELATIVE_TO_SELF, 0.5f
        )
        scaleAnimation.duration = 20000
        scaleAnimation.repeatCount = 0
        scaleAnimation.fillAfter = true
        main_circle.visibility = VISIBLE
        scaleAnimation.setAnimationListener(this)
        main_circle.startAnimation(scaleAnimation)
    }

    override fun onAnimationRepeat(p0: Animation?) {
    }

    /**
     * アニメーション終了時処理メソッド
     *
     * @param p0 アニメーション
     */
    override fun onAnimationEnd(p0: Animation?) {
        setColorByIndex(index)
        main_circle.visibility = GONE
    }

    override fun onAnimationStart(p0: Animation?) {
    }

    /**
     * 背景色切り替えメソッド
     *
     * @param index クリックされたビューの順番
     */
    private fun setColorByIndex(index: Int) {
        when (index) {
            0 -> {
                back_color.setBackgroundColor(this.resources.getColor(R.color.colorAccent))
            }
            1 -> {
                back_color.setBackgroundColor(this.resources.getColor(R.color.star_color))
            }
            else -> {
                back_color.setBackgroundColor(this.resources.getColor(R.color.colorPrimary))
            }
        }
    }
}

画面の左側で円を拡大する場合(水色) :失敗

  • 中心座標(270 , 792)
  • pivot(0.5f , 0.5f)
 2019-12-03 12.04.11.png

画面の左側で円を拡大する場合(水色) :成功

  • 中心座標(270 , 792)
  • pivot(0.25f , 0.5f)
    ※x軸の値を半分にしてあげればOK
 2019-12-03 12.08.45.png
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?