正式名がよく分からない
Material Designなどではあまり見かけませんが、必要性が出てきたので作ってみました。
何に使うのか
業務にて動きのある/指で動かせるボタンを作る機会があったのですが、動かせる範囲を制限したくこのような動きを考えました。これについては他の記事で話しましょう。
作ってみる
環境はAndroidStudio+Kotlinです。
SpringAnimation
今回、指を離した後に戻る部分のアニメーションにはSpringAnimationを使っています。これはAndroidで使えるAnimationのうちの一つ、「Physical based Animation」の一種で、簡単にバネの動きをViewに対して実装できます。
app/build.gradleに以下を追加しましょう。
dependencies { //略 implementation 'androidx.dynamicanimation:dynamicanimation:1.0.0' }
指に追随させる
指の動きに合わせてViewを動かすには、ViewのonTouchListenerを利用します。
limitedButton.yに座標(pixel)を書き込むことでボタンを移動できるのですが、ここではtouchGapYとstartRawYを使って制御しています。
ボタンのY座標には"親の"Viewの左上からの座標を指定しなければならないのに対しe.rawYで取得できるのは"画面の"左上からの座標です。この分のズレを吸収するためにViewが押された瞬間に2つの差分を取ってtouchGapYに保持します。そして動いたときにはtouchGapYを引いてあげればちょうど良くなるということです。
MotionEvent.ACTION_DOWN -> { touchGapY = e.rawY - limitedButton.y startRawY = e.rawY } MotionEvent.ACTION_MOVE -> { limitedButton.y = e.rawY - touchGapY }
動きの限界を設定する
本題です。限界を設定するにしても動きがスムーズでなければ不自然になってしまいます。そこで私はarctanを使って滑らかさを作りました。なにかの値に収束する関数であればなんでもいいと思います。
2/πに収束するのだと不便なので正規化してこのような関数を用意しましょう。
適当に動かした分(startY-rawY)に応じた量(α)でボタンが動くようにします。
これでlimitを超えない範囲でいい感じに動いてくれるようになります。実際に動かしながらvariationの値などを変えるとよいです。
離したら戻るようにする
ここまでだとただ単に動きの悪いDraggableButtonです。先のSpringAnimationを付けてみましょう。
次の関数を用意します。
まずSpringAnimationの引数で対象と終点を設定します。終点の種類には以下のようなものがあります。
DynamicAnimation. | 説明 |
---|---|
ALPHA | 透明度を設定 |
TRANSLATION_(X|Y|Z) | 現在座標からの移動距離(px)を指定 |
(X|Y|Z) | 画面の左上からの絶対位置を指定 |
SCALE_(X|Y) | 拡大縮小を設定 |
次にAnimationの物理的な特性である剛性(spring.sfiffness)と減衰率(spring.dampingRatio)を指定します。
- 剛性を上げる -> 勢いが強くなる
- 減衰率を下げる -> 終点に達するまでの揺れが多くなる
公式が詳しいので目を通すのがよいです。
指を離したときに関数を呼ぶようにすれば完成です!
MotionEvent.ACTION_UP -> { goBack2MyRoots(startRawY - touchGapY) }
ついでにX座標にも動かせるようにしたのが以下のコードです。冒頭のGIFもこれですね。
参考
出来上がったコードはGitHubにあげています。