- 公開日:2018年02月23日
記事概要
java-programming向けの詳細な記事を書く時間が取れないので、ざっくりとこちらに情報を載せます。
ViewPagerアニメーションの学習と研究をしていたので、そのまとめ記事です。
環境
- Android Studio 3.0.1
概要
ViewPagerはよく使いますが、きちんと内部コードを追って学習したことはほとんどありませんでした。
記事の内容は、この公式ドキュメントがベースです。さらに深掘りしています。
ViewPagerのアニメーション方法を変更するには、ViewPager.PageTransformerを使います。ViewPager.PageTransformerはtransformPageが宣言されているInterfaceです。
public interface PageTransformer { /** * Apply a property transformation to the given page. * * @param page Apply the transformation to this page * @param position Position of page relative to the current front-and-center * position of the pager. 0 is front and center. 1 is one full * page position to the right, and -1 is one page position to the left. */ void transformPage(@NonNull View page, float position); }
画面切り替え時にtransformPageメソッドが呼び出されます。
PageTransformerで実装した内容を有効にするには、setPageTransformerメソッドを使います。
mPager.setPageTransformer(true, new SamplePageTransformer());
上記のように設定すると、実装した具体的なPageTransformerクラスがmPageTransformer変数に設定され、onPageScrolledメソッドで呼び出されます。
if (mPageTransformer != null) { final int scrollX = getScrollX(); final int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { final View child = getChildAt(i); final LayoutParams lp = (LayoutParams) child.getLayoutParams(); if (lp.isDecor) continue; final float transformPos = (float) (child.getLeft() - scrollX) / getClientWidth(); mPageTransformer.transformPage(child, transformPos); } }
具体的なPageTransformerクラスは、PageTransformerをimplementsして実装します。サンプルとしてZoomOutPageTransformerクラスを実装してみます。
public class ZoomOutPageTransformer implements ViewPager.PageTransformer { private static final float MIN_SCALE = 0.85f; private static final float MIN_ALPHA = 0.5f; @Override public void transformPage(@NonNull View page, float position) { int pageWidth = page.getWidth(); int pageHeight = page.getHeight(); Log.d("ZoomOutPage", "position :" + position + ", view id : " + page.getId()); Log.d("ZoomOutPage", "pageWidth :" + pageWidth + ", view id : " + page.getId()); Log.d("ZoomOutPage", "pageWidth :" + pageHeight + ", view id : " + page.getId()); if (position < -1) { // 透明にする page.setAlpha(0.0f); } else if (position <= 1) { // -1 < posiiton < 1 // 多分、徐々に小さくするため float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position)); // margin 黒枠のところ // 縦 top bottomやな float vertMargin = pageHeight * (1 - scaleFactor) / 2; // 水平 名前が left rightだと float horzMargin = pageWidth * (1 - scaleFactor) / 2; // if (position < 0) { // // 相対的に動かす。これが無いと画像が動かないのでおかしくなるはず。 // page.setTranslationX(horzMargin - vertMargin / 2); // } else { // page.setTranslationX(-horzMargin + vertMargin / 2); // } // Scale the page down (between MIN_SCALE and 1) page.setScaleX(scaleFactor); page.setScaleY(scaleFactor); // Fade the page relative to its size. page.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA)); } else { // 透明にする page.setAlpha(0.0f); } } }
positionはページ数でなく、引数のページの相対的な位置です。-1 < x < 1までの範囲の値をとり、0が中央, -1が左, 1が右となります。
vertMarginとhorzMarginはページ切り替え時に、ページ間のviewの距離を詰めるための計算に使っています。setTranslationXでviewの位置をずらすことで、ページ移動のアニメーションをスムーズに見せています。名称がわかりにくいので、topBottomMarginとleftRightMarginで実装した方がわかりやすいと思います。
続いて、DepthPageTransformerを実装してみます。
public class DepthPageTransformer implements ViewPager.PageTransformer { private static final float MIN_SCALE = 0.75f; @Override public void transformPage(@NonNull View page, float position) { int pageWidth = page.getWidth(); if (position < -1) { // 透明にする page.setAlpha(0.0f); } else if (position <= 0) { // [-1 : 0] // Use the default slide transition when moving to the left page page.setAlpha(1); page.setTranslationX(0); page.setScaleX(1); page.setScaleY(1); } else if (position <= 1) { // [0 : 1] // Fade the page out. page.setAlpha(1 - position); // Counteract the default slide transition page.setTranslationX(pageWidth * -position); // Scale the page down (between MIN_SCALE and 1) float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position)); page.setScaleX(scaleFactor); page.setScaleY(scaleFactor); } else { // 透明にする page.setAlpha(0.0f); } } }
こちらの方が理解しやすですね。左と右で綺麗に処理が分割されています。position <= 0, つまり左側はただスライドするだけです。
page.setAlphaで透過状態を管理しています。徐々に薄くなったり、濃くなったりしています。
ズームも同じで、大から小, 小から大へとviewを変化させています。setScaleX, setScaleYで拡大縮小をしています。
page.setTranslationX(pageWidth * -position);で画面が停止しているように見えるようにしています。
結論
ViewPager.PageTransformerを使うことで、アニメーションを実装できます。色々とやってみようと思います。
0 件のコメント:
コメントを投稿