Little Strange Software

スマホアプリの開発を行う LittleStrangeSoftware のブログです。

Androidでアニメーションさせるのはとっても簡単!!なのにハマった話

 どうも!LSSです!

 

 今回は、xmlにアニメーションの動作を記載して、kotlinからそれを呼び出して特定のパーツをアニメさせる方法について書きます!
 

 先日、予想外のつまづき(動画について)にて、

 >ハマった、とは言っていますが、Androidアプリ開発においてアニメーションさせる事自体はとっても簡単です!

とか書いてましたが、色々やってみてると、変なところでハマったりしました^^;。

 

 

 

完成したアニメーションと、xml

 作りたかったのはこういうモノ。

 透明→実体化しつつ、大きくなりながら、回転しながら、画面上部から降りてくる、という感じ。

実際の動作 xmlファイルの内容
f:id:little_strange:20191022151439g:plain
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
android:duration="8000"
android:shareInterpolator="true"
android:interpolator="@android:anim/linear_interpolator"
>
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"
/>
<scale
android:fromXScale="0.0"
android:fromYScale="0.0"
android:toXScale="1.0"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
/>
<rotate
android:fromDegrees="0"
android:toDegrees="1800"
android:pivotX="50%"
android:pivotY="50%"
/>
<translate
android:fromXDelta="0%p"
android:fromYDelta="-50%p"
android:toXDelta="0%p"
android:toYDelta="0%p"
/>

</set>

 

  

失敗したアニメーションと、xml

 なぜか期待した通りに動かなかった例がこちら。

 透明→実体化大きくなりながら、は期待通り。
 回転は軸がおかしい(画面中央になってる?)、画面上部から降りてくるがほぼ無効化されてる、といった具合^^;。
…こっちはこっちで味があるんですけどねw

実際の動作 xmlファイルの内容

f:id:little_strange:20191022154129g:plain

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
android:duration="8000"
android:shareInterpolator="true"
android:interpolator="@android:anim/linear_interpolator"
>
<translate
android:fromXDelta="0%p"
android:fromYDelta="-50%p"
android:toXDelta="0%p"
android:toYDelta="0%p"
/>
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"
/>
<scale
android:fromXScale="0.0"
android:fromYScale="0.0"
android:toXScale="1.0"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
/>
<rotate
android:fromDegrees="0"
android:toDegrees="1800"
android:pivotX="50%"
android:pivotY="50%"
/>

</set>

 

 

 

成功版と失敗版でのxmlの違うところ

 というのが、実は、

<translate
    android:fromXDelta="0%p"
    android:fromYDelta="-50%p"
    android:toXDelta="0%p"
    android:toYDelta="0%p"
    />

を入れる場所が違うだけだったりします。

 

 タグの構造だけでいうと、

<set>
    <alpha/>
    <scale/>
    <rotate/>
    <translate/>
</set>

で、<set>~</set>で囲んだなかのアニメーション、
alpha(透明度の変化)、scale(拡大縮小)、rotate(回転)、translate(移動)の4つを同時に実行する、って事なので、何故これで動作が変わるのか、納得は行かない部分はあるのですが^^;

 

 

問題となる個所はこちら!pivotXとpivotYの謎について!

回転の軸がずれているのがまず問題。

だったのですが、その軸について指定しているのは

android:pivotX="50%"
android:pivotY="50%"

この2行。

 scalerotateにそれぞれ指定しています。

 これはアニメーションさせる対象(今回でいうとロゴ画像)の中心を軸に、という指定だったんですが、それがどうやら 画面の中心が軸になってしまっている様子。

で、これについて色々調べてみたのですが、プログラム側からアニメーションを指定する際には、

アニメーションさせる対象上の位置を指定する場合=Animation.RELATIVE_TO_SELF

親要素上の位置を指定する場合=Animation.RELATIVE_TO_PARENT

という指定になる、という情報はすぐに見つかったのですが、xml上でそれを指定する場合、どう書けばよいのやらがさっぱりでした^^;;;

 

 しつこく検索していて見つけた情報はこちら!

http://ja.voidcc.com/question/p-brlkfplo-bd.html 

 

 こちらによると"50%p"のように%pで指定した場合には、親要素内の位置指定、"50%"のように%で指定した場合には、対象の要素内の位置指定となる、ようです。

 

 

あれ?それにしても…

 rotateのところには

android:pivotX="50%"
android:pivotY="50%"

で指定しているんだから、pつけてない、この記述で画面中央が軸になるのはおかしいよね??と、また悩みました…。

pつけてるのと言えば、translateで 

android:fromXDelta="0%p"
android:fromYDelta="-50%p"
android:toXDelta="0%p"
android:toYDelta="0%p"

で使っている程度で、こちらは「半画面分、上から降りてくる」という指定なのでpつきでいいはずだし…と思いながら、

translateタグを最初に書いていたものを最後に移動したら、なぜか正常動作するようになった!!

という、よくわからない解決になってしまいました^^;

(先にpつき指定していたら、それ以上のpなし%指定もpつきの効果になってしまう、という事なんでしょうか???)

 

 とりあえず、これで期待通りの動きをしてくれるようになったので、解決!って事にしておきますw

 

 

xmlでのアニメーションのやり方~

ここからやっと作り方解説になりますw

f:id:little_strange:20191022182419p:plain

 AndroidStudioの画面左から、「app」内の「res」を右クリックして、「New」「Directory」を選択します!

f:id:little_strange:20191022182726p:plain

ダイアログが出てくるので「anim」と入力します。

ここはanimじゃないとダメです!

任意の名前ではありません。

 

 

f:id:little_strange:20191022182959p:plain

res」の中に「anim」が作られます。

 

 

f:id:little_strange:20191022183216p:plain

 その、作ったばかりの「anim」を右クリック、「New」「Animatiron resource file」を選択します!

 

 

f:id:little_strange:20191022183448p:plain

 また、ダイアログが出てきます。

 File nameのところに適当に名前をつけます。
(今度は任意の名前。今回は「anime0」とつけてみました。)

で、OKボタンを押します。

 

 

f:id:little_strange:20191022183934p:plain

 anime0.xmlファイルが作られ、編集ウィンドウに出てきます!

  最初からsetタグが書かれた状態で生成されます。

 ここに、どんな動きを持たせたいかを書いていく事になります。

 

試しに簡単にxmlを書いてみます

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="5000"
android:fillAfter="true"
>
<translate
android:fromXDelta="0"
android:fromYDelta="-500"
android:toXDelta="0"
android:toYDelta="0"
/>
</set>

試しに、translateだけのアニメーションを定義してみました。

setタグの右端の>の手前で改行し、「a」キーを押すと補完候補が出てきます。
記載内容を見ると、タグのオプションは全て「android:~」で始まっているので、細かい綴りを覚えなくても「a」キーでだいたいなんとかなりますw

 

項目のざっくりとした説明

android:duration="5000"

こちらはアニメが始まってから終わるまでの時間をミリ秒で指定します。

5000で「5秒」って事になります。

今回はsetタグに書いていますが、translateタグ内に書いてもOKです。
(これがまた何故か、「a」キーでの補完候補に出てくるのはsetタグの場合だけみたいです)

 

 android:fillAfter="true"
 アニメ終了時に、画面のアニメさせた対象物を「アニメ終了時そのままの状態で画面に残す」場合に"true"で指定しておきます。

 

android:fromXDelta="0"
android:fromYDelta="-500"

translateタグのオプションで、それぞれ「アニメ開始時の位置」を縦横それぞれ指定しています。
縦はY、横はXです。
上記の書き方だと「横はそのまま、縦は500ピクセル上の位置から」という指定になります。

 

android:toXDelta="0"
android:toYDelta="0" 

translateタグのオプションで、それぞれ「アニメ終了時の位置」を縦横それぞれ指定しています。
縦はY、横はXです。
上記の書き方だと「縦も横も元(画面のxmlデザイン上で対象物が置かれた位置)のまま」という指定になります。

 

 このアニメを実行すると、指定した対象物が
「本来の場所から500ピクセル上の位置に出現し、そこから5秒かけて本来の位置に移動する」
という動きになります。

 

 

kotlinで対象物に指定のアニメをさせてみる


class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val anm0 = AnimationUtils.loadAnimation(this, R.anim.anime0)
bt0.startAnimation(anm0)
}
}

kotlinで、対象物にアニメさせる記述は、赤字で書いた2行になります。

 この場合、bt0 という対象物にanm0という名前で定義した「anime0に書いた動作」をさせる、という指定です。

 実際に、適当に作ったボタンに「bt0」とidをつけて動かしてみました!

f:id:little_strange:20191022191754g:plain

 ↑こんな感じの動作になります!!

 

  以上、Androidでのアニメーションについて、でした!

 他にもxmlを使わずにプログラム内だけで指定する方法とか、何通りかのやり方があるようです。
が、規定の動作をさせたいのであれば、今回のようなxmlに内容を記載するのが 、結局お手軽なんじゃないかな?と思います^^

 

 ではまた!次回もよろしくお願いします!!