- 公開日: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 件のコメント:
コメントを投稿