放流作業

ネットの海に放流するのでいつか戻ってきてほしい

下からひょこっと出てくるボタンを作る(Android/Kotlin)

やりたいこと

画面を開いたら下からひょこっとボタンが出てくる

ボタンを下にフリックすると引っ込む

できたもの

よい

前提として

これは

nageler.hatenablog.com

の応用例です。実装の際はこちらも一読すると良いと思います

作ってみる

環境はAndroidStudio+Kotlinです。

ボタンを用意する

画面外下から出したいのでConstraintLayoutを使って下に配置します。

Top_ToBottomOfで画面外配置できるのかなり便利

ボタンを出す

これが本題かな?(そうでもない)

アニメーションには前回も使ったSpringAnimationを使います。

developer.android.com

説明は前の分を見てください。

遅延を付けて出す

画面を出してから少し遅延を付けて出したいので、Kotlinの非同期処理としてCoroutineを利用します。

dependencies {
    //略

    //Physical Based Animation
    implementation 'androidx.dynamicanimation:dynamicanimation:1.0.0'

    //Coroutine
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3"
}

GlobalScopeでCoroutineを立て、1秒delayしてからアニメーションを実行するよう設定します。animation.start()はバックグラウンドスレッドで呼び出すと怒られるのでwithContextでスレッドを変えましょう。

出す長さの計算としてviewHeightとmarginを使っています。

val buttonMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16f+16f, resources.displayMetrics)

この一文ですが、SpringAnimationはPixel単位で動かすのでこう書くとDPから変換してくれるらしいです(やらないと端末ごとに移動距離が歪になる)。

引っ込める

利便性のため引っ込める関数も作っておきます。こちらは呼び出されたらすぐ実行するだけなのでCoroutineなしで書きます。

ぐにぐに動かす

前の記事のとおりです。今回は上方向に動いてほしくないので上に指が動いたときのみ制限をかけるようにします。

originAnimationは外部からアクセスしたいのでActivity内に宣言しました。

下へのフリックで引っ込むようにする

フリックの検知にはGestureDetector.SimpleOnGestureListenerを使います。

developer.android.com

class MainActivity : AppCompatActivity() {

    private lateinit var buttonGestureDetector: GestureDetector

    //略
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val buttonGestureListener = object: GestureDetector.SimpleOnGestureListener() {
            override fun onFling(
                e1: MotionEvent?,
                e2: MotionEvent?,
                velocityX: Float,
                velocityY: Float
            ): Boolean {
                println("速度: Y=$velocityY")
                return super.onFling(e1, e2, velocityX, velocityY)
            }
        }

        buttonGestureDetector = GestureDetector(this, buttonGestureListener)

        limitedButton.setOnTouchListener { _, e ->
            //略

            buttonGestureDetector.onTouchEvent(e)
        }

        //略
    }
}

ボタンのフリックした速度が出力されると思います。

適当な速度を超えたら引っ込むようにします。Viewが移動していてもよしなにアニメーションを作ってくれるのがSpringAnimationの素晴らしいところ。

パラメータがいくつかあるのでそれらを調整すれば、それなりの動きになると思います(最初の動画は動きすぎ...)。

最後に

Animationたのしい

出来上がったコードはGitHubにあげてあります(Branch切ってるだけなので見にくい)。

github.com