Flipboardのページめくりってイイですよね!ってことで試してみました。
一応それっぽく動いたのでご紹介します。
今回一例としてご紹介するのはandroid.graphics.Cameraを使った実装になります。
Cameraを使うとビューのCanvasを3次元的に操作することができます。
やり方
今回は、こんな感じで考えてみました。
1.めくり開始時に表面のViewからBitmapを取得
2.めくり中は、取得したBitmapをCameraを操作しながらページをめくっているように見えるように描画
3.めくり終わったら、表面のViewは表示しない
超ざっくりですいませんがが、できそうな感じしませんか。
ポイントは2のCamera操作です。
カメラ操作
onDrawでのカメラ操作部分の抜粋です。
@Override protected void onDraw(Canvas canvas) { ... Camera camera = new Camera(); Matrix matrix = new Matrix(); canvas.drawBitmap(mFrontBmp, reightRect, rightRect, null); //左半分を描画 camera.save(); //現在のカメラ位置を覚えておく if (mDegree < 90) { //ページめくり90度までは右半分にめくり中の画像を描画 camera.rotate(0, mDegree, 0); camera.getMatrix(matrix); matrix.preTranslate(-getWidth()/2, -getHeight()/2); matrix.postTranslate(getWidth()/2, getHeight()/2); canvas.concat(matrix); canvas.drawBitmap(mFrontBmp, leftRect, leftRect, null); } else { //ページめくり90度以上は、左半分に裏のViewのめくり中の画像を描画 camera.rotate(0, mDegree - 180, 0); camera.getMatrix(matrix); matrix.preTranslate(-getWidth()/2, -getHeight()/2); matrix.postTranslate(getWidth()/2, getHeight()/2); canvas.concat(matrix); canvas.drawBitmap(mBackBmp, rightRect, rightRect, null); } camera.restore();//復帰 }
13行目:Camera#rotateでカメラをY軸方向に回転させています。
イメージするとこんな感じ。
カメラを回転させることでCanvasの見え方が変わります。
15、16行目:Canvasの位置を(0,0)にCanvasの中心が来るように移動し、描画後に戻すという操作をしています。
これは、カメラの初期位置が(0,0,-8)であるため、ちょうどカメラの真下にCanvasの中心を持ってくることによって、カメラを回転させた時の見え方が、ちょうどページをめくっている感じに見えるようにするためです。
イメージするとこんな感じ。
加えて、カメラのZ軸の位置もめくるピューのサイズによって、丁度いい位置に調整してあげる必要があるかもしれません。
例えば、解像度が高い端末などでは、Canvasとカメラの位置が近すぎてページをめくっている感じに見えなくなる場合があります。
そんな時は、
camera.setLocation(0, 0, -getWidth()/100); // Z軸を調整
などとして、カメラのZ軸位置を調整してみて下さい。
以上、めくり中の画像を描画してあげることにより、なんとなくページをめくっている様に見せることができました。
後は、めくる角度ごとにカメラの角度を変えて描画するのを、角度を変えながら連続で行うことで、ページをめくっているようなアニメーションを行うことができます。
サンプル
冒頭にあげたサンプルアプリのソースコード一式です。
https://github.com/workpiles/TurnablePageViewSample
サンプルでは、(手抜きして)後ろのViewを描画したり、スワイプでめくる操作は端折っています。
単純に、ビューをクリックするとぺろっと表面がめくれるだけ。
スワイプ操作の実装は「スワイプで削除できるリストビュー(RecycelrView)あたりが参考になるかもしれません。
あとがき
とりあえずこんな感じで出来たよレベルですが、そこそこ満足してたりします。
Animationとかで実装できればより汎用的だったりするかなと思ったりもしてますが…まいっか(^_^;)。
ではでは〜。