Umi Uyuraのブログ

プログラミング関連の作業ログ

Titanium Androidのアニメーションについて(3.1.3以前)

この記事はTitanium™ Advent Calendar 2013の第3日目として書いています。

Advent Calendar初参加なので、皆様お手柔らかにお願いします。

お・こ・と・わ・り

この記事の内容は、Titanium SDK 3.1.3ベースのものです。

もうすぐ3.2.0がリリースされる模様ですが、そこではAndroidのアニメーションが大きく改善されているようですので、本記事の内容は当てはまらない可能性があります。いえ、きっと本記事のような問題は起こらないと思います。信じています。

というわけで、これから3.2.0ベースで開発される方は、昔は大変だったんだな−という感じで呼んで頂ければ幸いです。

経緯

個人的に作ろうとしていたアプリにて、Viewをいくつか単純なアニメーションさせたいと思いました。

アプリはiPhone/Android両方で出したかったのでTitaniumを使うことにしたのですが、以前から特にAndroidにおいて、アニメーションはとても弱いという噂を耳にしていました。

私が実現したかったのは、色々な情報を表示するための角が丸くなったViewを用意し、状況に応じて大きさを変えたり、位置を移動したりさせるという、わりと単純なものです。

さすがにこのくらいの単純なアニメーションなら大丈夫だろうと試したところ、噂通りAndroidで予想以上に不可解な動きになったため、サンプルを作ってどんなものになるか検証した記録になります。

サンプル

今回の検証で試行錯誤したサンプルはGitHubに上げていますので、ご興味ある方はお手元にて動かしてみてください。

そして、改善方法がわかりましたら、ぜひ教えてください!

umi-uyura/TiAnimateStudy

ま、3.2.0で全て解決しているはずだけどね!(希望)

使い方

アプリを起動すると、こんな感じの画面になります。

f:id:umi-uyura:20131203165715p:plain

TiAnimateStudy (iPhone)

f:id:umi-uyura:20131203165725p:plain

TiAnimateStudy (Android)

各メニューを辿ると、四角いViewが1つ置いてある画面になりまして、そのViewをタップすると、各メニューに合わせたアニメーションが始まるというものです。

実験項目

サンプルアプリの構成にもなっていますが、以下の様な順番で試していきました。

  1. Viewの単純な移動
  2. Border付きViewの単純な移動
  3. Viewの単純な変形
  4. Border付きViewの単純な移動
  5. Viewの移動&変形

iPhoneについてはシミュレータで、Androidについては主にGALAXY S3にて確認しています。

1. Viewの単純な移動

まずは、ひとつのViewを単純に上から下や左から右、連続や同時(つまり斜め)に動かしてみました。

Movement - Top to Bottom, Left to Right

これはさすがにAndroidでも期待どおりに動いてくれました。

2. Border付きViewの単純な移動

次でいきなり躓きます。

角丸のViewを実現するために、Titanium.UI.ViewのborderWidth、borderRadiusを使うことにしました。

そして1.のコードをベースにViewにborderをつけたところ、さっそくAndroidで予想外の動きをしました。

Movement with Border - Top to Bottom

なんと、Borderを残してView部分だけ移動しています!

そしてその後、アプリが落ちます(笑)

どうやらAndroidではTitanium側でViewの周りにBorderを自前で描画しているようですが、アニメーション時には内部のView部分だけが移動してしまい、Borderが置き去りにされているのですね。

さて、これが動かないということは、冒頭に書いた私が実現したいものが実装できないということになってしまいます。

そこでBorderが置き去りにされるのであれば、Border毎移動するようにすれば良いのではと、Borderを持つViewの下に、それを内包するViewを付けてみました。

Movement with Border - Top to Bottom (for Android)

一応、動きました。

サンプルではわかりやすいように色を付けていますが、透明なViewにすれば、移動だけであればこれで誤魔化せそうな気がしました。

3. Viewの単純な変形

さてさて、移動の挙動がわかったところで、次は変形を試しました。

Viewの幅や高さを縮めるものです。

Transformation - Shrink width

これも、Borderがないためか、Androidでも意図どおりに動いてくれました。

4. Border付きViewの単純な移動

で、魔のBorder付き版です。

Transformation with Border - Shrink width

予想通り、Borderを残して縮みました。そして落ちます(笑)

そこで2.と同様、Borderを持つViewの下に、それを内包するViewを置くという方式を試してみました。

Transformation with Border - Shrink width (for Android)

すると今度は、確かに一番下のViewは縮むのですが、上に乗っている肝心のBorderを持つViewの幅は変わりません。

拡縮を行いたい場合、この方法では実現できないようです。

4. Border付きViewの単純な移動(その2)

そこで今度は2DMatrixを試すことにしました。

Transformation with Border - Shrink width by 2DMatrix (for Android)

今度は動きました!

ちなみに、拡大縮小処理を2DMatrixに変えたので、ひょっとしたらラッパーViewは不要ではないかと思いましたが、

Transformation with Border - Shrink width by 2DMatrix

アプリは落ちなかったものの、あ、やっぱり、という結果でした。

5. Viewの移動&変形

さてさて、ここまでの結果で、ひとまず現状(3.1.3GA時点)のAndroidにて、冒頭に述べたようなアニメーションを実現するのであれば、ラッパーViewを置いて、そこに対してアニメーション処理を行う、というのが良さそうだとわかりました。

そこまでわかれば、もうBorder付きView(with ラッパーView)を移動しながら変形とかもできるでしょ!

Movement & Transformation - Top to Bottom & Shrink width, Left to Right & Shrink height with Border (for Android)

・・・甘かった。

最初の上から下へ移動し、その後に幅を縮めるところまでは意図したとおりです。
が、そのまま連続して左から右へ移動し、さらに高さを縮めるという動きの途中、移動が終わったタイミングで一瞬、Viewの大きさが元の大きさに戻ってしまいます。

他にもいくつか移動や縮小のタイミングを変えてみていますが、移動の前後などで一瞬サイズ変更の効果が解除されて?しまい、元の大きさに戻ってしまう動きになってしまいました。

Movement & Transformation - Shrink width & Top to Bottom, Shrink height & Left to Right with Border (for Android)

まとめ

この時に私が試せたのはここまででしたが、これだけでもAndroidでのアニメーションの難しさが伝わるのではないかな、と思います。

この後の方針としては、

  • Androidは9-patchで角丸Viewを作る→色を変えるなどのバリエーションを作りにくいのが難点
  • GitHubなどにある、アニメーションを扱うモジュールを試す

などを考えていましたが、残念ながらそこまで手が回りませんでした。

そんな感じだったので、3.2.0でのアニメーションの改善には非常に期待しています。

3.2.0リリース後で枠が余っていたら、本サンプルを3.2.0で動かしてみたレポートを書いてみようかな・・・

というわけで、明日はユーザー会の偉大なる会長@yagi_さんです。
よろしくお願いします!

ありがとうございました。