アニメーションについてのセッション
アニメーションはより説得力のあるアプリケーションを作る助けになるし、よりアプリを楽しくする
# ここには書かないけど、全体的にコントみたいなやりとりが多いので見ると面白いかも?
ユーザーとアプケーションをより結びつけ、アプリの体験を記憶してもらう
クオリティの高い時間をユーザーにすごしてもらう
画面上で起こるアニメーションによって、ユーザーは遷移や変更が実際に起こっていることを認識できる
知るべきことを伝える、状態遷移を伝える、どこから来てどのようにこれを取得したのか
Elements of Good Animations
いいアニメーションの4つの原則
- Short
- Smooth
- Natural
- Purposeful
- 必要以上にうるさくしない
- ユーザーが求めていないときのアニメーションはとてもつらい。ユーザーにとってつらいし、開発者にとってもつらい。開発時に何回も何回も見ないといけないから
- ViewPropertyAnimator はデフォルトでアニメーションの時間を 300ms にしている
300ms はモバイルデバイスの多くのアニメーション時間に適してる
十分短いが短すぎるわけではない
ただし、これが答えというわけではない。すべてのアニメーションを 300ms にしろ、というわけではない
シチュエーション、ビューの大きさ、アニメーションの複雑度、移動する距離などに依存する
- ウィンドウのアニメーションがいい例。これはスケールとアルファのアニメーションを組み合わせて、フルスケールのアニメーションをさせなくても 0 からサイズが変わったように感じられる
- 小さいボタンを大きいボタンを同じ時間、同じ距離を移動させた場合、ユーザーには異なるように感じられる。
「つまり、なんでガリレオは石と羽で実験したのかっていうと、アニメーションの時間をテストしてたのさw」(ジョークね)
Smooth
いろんな効果を組み合わせてかっこ良くしてもガタガタしてたらユーザーは嫌になる
最初から最後までスムーズな体験
1. アニメーション中にレイアウトを走らせないこと
2. レイアウトなどの重い処理はアニメーションを開始する前に行っておくこと
複数のアニメーションをつなげるときに、加速カーブを使うなど、滑らかにつながるように気をつける
Natural
ナチュラルだと感じられる様にする
単にアニメーションしていることを気づかせるだけでなく、なぜそれが必要なのか伝える
かっこいいからという理由だけでアニメーションするのはよくない
Purposeful
アニメーションに目的をもたせる
「僕の好きな例は、、、Linux のだったかな?」「Linux Desktop だね。あるウィンドウマネジャーがあって、ウィンドウを閉じるときに炎に包まれて消えて煙が出るんだ。かっこいいよ。。。でもそうしちゃだめだよw」「一番最初はすごく楽しんだけど、、、」「やってもいい状況が1つだけあるよ。カンファレンスのステージに上がってそれを見せて、観客にやるなって言うんだ」
UI でなにが起こりつつあるのか見せる
重要なアクションを示す
アニメーションの理由はかっこいいからじゃない
List Animation
リストのアイテムを右にスワイプして消すことができ、消した後その部分が閉じるアニメーションのサンプル
ArrayAdapter を継承した StableArrayAdapter クラス
- stable ID を getItemId() で返す
- getView() で一行の View に setOnTouchListener() をセットする
- アイテムがスワイプアウトされたときの背景(ドロップシャドウあり)を描画する
- 上と下用の2つのドロップシャドウを作って(9-patch を使ってもOK)、背景を表示すると言われたときに setWillNotDraw(false) をセットして描画する
- onSizeChanged() でサイズが変更されたらドロップシャドウのサイズをアップデートする
- onDraw() を Override して、canvas を translate してドロップシャドウを描画する
- アニメーションのロジックのすべてがある
- StableArrayAdapter を生成して ListView にセット
- View.OnTouchListener でアクションをトラックしてスワイプに応じて透明度を変更
- 指が離れたときに位置と速度に応じて、戻るのかスワイプアウトするのか決めアニメーションを開始する
- アニメーションは ViewPropertyAnimator で alpha(), translationX(), withEndAction() を使う
- リストのアイテムが消えるとその分リストがつまるので、つまる前の位置を保持しておき、つまる前からつまった後の位置までアニメーションさせたい
- リストのアイテムが消えるとレイアウトが走り、他の子ビューの位置を変更する
- まずレイアウトが起こる前に情報を集める
- JellyBean で追加された setHasTransientState(true) を他の子ビューにセットする
- ListView に false をセットするまでビューのコンテンツを台無しにしないために重要
- それから ViewTreeObserver.OnPreDrawListener をセットする
- レイアウトパスの結果を描画する前に OnPreDrawListener の onPreDraw() が呼ばれる
- ここで OnPreDrawListener を remove
- レイアウトが起こった後の情報を集め、レイアウト前の位置からレイアウト後の位置までアニメーションさせる
- 終わったら setHasTransientState(false) をセットする
コードはあとで公開される
Activity Animations
window animation をカスタマイズする方法を提供しているが、とても制限がある
JellyBean 4.1 からサムネイルの状態からスケールアップして起動できるようになったが、カスタマイズできない
そこで、、、アプリ内のサムネイルをタップして写真を大きく表示するサブアクティビティを表示するサンプル
- サムネイルの状態では白黒
- サムネイルの位置からスケールアップして画像が画面全体に表示される
- スケールアップに合わせて白黒じゃなくなり、背景も暗くなる
- 画像のスケールアップが終わったら、詳細が画像のしたからアニメーションで出てくる
- サブアクティビティは透明の Activity
- トリックはすべてこの透明な Activity で行う
サムネイルを表示している Activity では
- Grid を表示して、ColorMatrix filter を使って白黒にしているだけ
- サムネイルがクリックされたら、getLocationOnScreen() でサムネイルの画面上の位置を取得、orientation を取得
- これらの情報を Intent を介してサブアクティビティに伝える
- startActivity() を呼んだあとに overridePendingTransition(0, 0); を呼んでデフォルトのアニメーションが走らないようにする
サブアクティビティでは
- savedInstanceState が null かどうかチェックして、画面回転時にアニメーションが走らない様にする
- ViewTreeObserver.OnPreDrawListener をセットする
- onPreDraw() が呼ばれたら、OnPreDrawListener を削除し、getLocationOnScreen() で画像の位置を取得
- もとのサムネイルとのスケールを計算し、Intent で渡された位置からレイアウトされた位置までアニメーションする
- 合わせて背景の透明度、画像の saturation(ColorMatrixColorFilter を利用したカスタマイズ property)なども一緒にアニメーションする
- finish() 時に overridePendingTransition(0, 0); を呼ぶ
- バックボタンが押されたときに、サムネイルに戻るアニメーションを実行してから finish() を呼ぶようにする
ShadowLayout
- BlurMaskFilter を使って深さを表現したレイアウト
コードはあとで公開される
Cartoon Animation Techniques
- ディズニーのアニメーションについて
- 彼らはアニメーションの12の原則を作った
- これらは観客の理解を助けることにフォーカスしていた
- 原則の1つに Squash and Stretch というのがある
- ボタンが跳ねるときのアニメーションを例に説明
- 2つのアニメーションをつなげるときにナチュラルになるようにしようということ
ボタンが画面の端に達したら横に広がるアニメーションを走らせて、それが終わったら跳ね返るアニメーションを走らせる
Anticipation
走り出す前に、走りそうなモーションを入れたりすること
のけぞってから動きだし、止まったところで揺れるボタンのアニメーションサンプル
Follow Through and Overlapping Action
自然界では壁にぶつかったとして、すぐに止まれるわけではない Non-linear motion を利用する サンプルアプリのデモ Path アプリの画像ストレッチ
ViewTreeObserver
便利なクラスなので見ておくこと
システム内部でもよく使っている
Layers
アニメーションさせたい複雑なビューや複雑なビュー階層がある場合、アニメーション中に hardware layer をセットすることを考える
実際に変化するものには使わないこと、フレーム毎にレイヤーを再生成しないといけなくなるから
More info
- Parleys.com : Animation Rules (Devoxx 2009)
- Youtube.com : DevBytes (androiddevelopers channel)
- Book : The Illusion of Life (Thomas and Johnston)
- Chet's Tips & Tricks (graphics-geek.blogspot.com)
- Romain's Tips & Tricks (www.curious-creature.org)
0 件のコメント:
コメントを投稿