- 以前からAndroidで標準で用意されている仕組み
-
ViewPager.PageTransformer
を実装(implements)したクラスを作成しViewPager
にセットする
someViewPager.setPageTransformer(
true,
new SomeTransformer()
);
- 第一引数(
boolean: reverseDrawingOrder
)は1枚目のページを2枚目以降のページの上に描画するか否か
汎用的に利用できる PageTransformer を作っておくと便利
PageSwipeTransformer.java
public class PageSwipeTransformer implements ViewPager.PageTransformer {
private float minAlphaOut = 1.0F;
private float minAlphaIn = 1.0F;
private float minScaleOut = 1.0F;
private float minScaleIn = 1.0F;
private float positionXOffsetIn = 1.0F;
private float positionXOffsetOut = -1.0F;
private float positionYOffsetIn = 0.0F;
private float positionYOffsetOut = 0.0F;
public PageSwipeTransformer setMinAlphaOut(float minAlpha) {
this.minAlphaOut = minAlpha;
return this;
}
public PageSwipeTransformer setMinAlphaIn(float minAlpha) {
this.minAlphaIn = minAlpha;
return this;
}
public PageSwipeTransformer setMinScaleOut(float minScale) {
this.minScaleOut = minScale;
return this;
}
public PageSwipeTransformer setMinScaleIn(float minScale) {
this.minScaleIn = minScale;
return this;
}
public PageSwipeTransformer setPositionXOffsetIn(float offsetPositionX) {
this.positionXOffsetIn = offsetPositionX;
return this;
}
public PageSwipeTransformer setPositionXOffsetOut(float offsetPositionX) {
this.positionXOffsetOut = offsetPositionX;
return this;
}
public PageSwipeTransformer setPositionYOffsetIn(float offsetPositionY) {
this.positionYOffsetIn = offsetPositionY;
return this;
}
public PageSwipeTransformer setPositionYOffsetOut(float offsetPositionY) {
this.positionYOffsetOut = offsetPositionY;
return this;
}
@Override
public void transformPage(View page, float position) {
final float width = (float) page.getWidth();
final float height = (float) page.getHeight();
if (-1.0F < position && position <= 0) {
page.setVisibility(View.VISIBLE);
page.setAlpha(Math.max(minAlphaOut, 1 + position));
page.setScaleX(Math.max(minScaleOut, 1 + position));
page.setScaleY(Math.max(minScaleOut, 1 + position));
page.setTranslationX(width * -position + width * -position * positionXOffsetOut);
page.setTranslationY(height * -position * positionYOffsetOut);
}
if (0 < position && position < 1.0F) {
page.setVisibility(View.VISIBLE);
page.setAlpha(Math.max(minAlphaIn, 1 - position));
page.setScaleX(Math.max(minScaleIn, 1 - position));
page.setScaleY(Math.max(minScaleIn, 1 - position));
page.setTranslationX(-width * position + width * position * positionXOffsetIn);
page.setTranslationY(height * position * positionYOffsetIn);
}
if (position <= -1.0F || 1.0F <= position) {
page.setVisibility(View.GONE);
}
}
}
例①: 縮小してスライド
viewPager.setPageTransformer(
true,
new PageSwipeTransformer()
.setMinScaleOut(0.9F)
.setMinScaleIn(0.9F)
);
- 動作イメージ
例②: スライドアウト
viewPager.setPageTransformer(
true,
new PageSwipeTransformer()
.setPositionXOffsetIn(0.0F)
);
- 動作イメージ
例③: スライドイン
viewPager.setPageTransformer(
false,
new PageSwipeTransformer()
.setPositionXOffsetOut(0.0F)
);
- 動作イメージ
例④: スライドアウト + スタック(重なっている)
viewPager.setPageTransformer(
true,
new PageSwipeTransformer()
.setPositionXOffsetIn(0.5F)
);
- 動作イメージ
例⑤: フェードイン
viewPager.setPageTransformer(
false,
new PageSwipeTransformer()
.setPositionXOffsetOut(0.0F)
.setMinAlphaIn(0.0F)
.setPositionXOffsetIn(0.0F)
);
- 動作イメージ
例⑥: 拡大して現れる
viewPager.setPageTransformer(
true,
new PageSwipeTransformer()
.setPositionXOffsetIn(0.0F)
.setMinScaleIn(0.5F)
);
- 動作イメージ
例⑦: 斜め上にスライド
viewPager.setPageTransformer(
true,
new PageSwipeTransformer()
.setPositionYOffsetOut(-0.5F)
.setPositionYOffsetIn(0.5F)
);
- 動作イメージ
おまけ:コードで ViewPager のページを変更すると速すぎる問題
-
setCurrentItem()
の第二引数(boolean: smoothScroll
) にtrue
を指定してもスムーズになってくれない - 解決するには ViewPager を継承したカスタムViewを作る
SmoothScrollViewPager.java
public class SmoothScrollViewPager extends ViewPager {
public SmoothScrollViewPager(Context context) {
super(context);
setMyScroller();
}
public SmoothScrollViewPager(Context context, AttributeSet attr) {
super(context, attr);
setMyScroller();
}
private void setMyScroller() {
try {
Class<?> viewpager = ViewPager.class;
Field scroller = viewpager.getDeclaredField("mScroller");
scroller.setAccessible(true);
scroller.set(this, new MyScroller(getContext()));
} catch (Exception e) {
e.printStackTrace();
}
}
private static class MyScroller extends Scroller {
private MyScroller(Context context) {
super(context, new FastOutSlowInInterpolator());
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
super.startScroll(startX, startY, dx, dy, 500);
}
}
}
-
Interpolator
(前項の例だとFastOutSlowInInterpolator
)とアニメーション時間(前項の例だと500
ミリ秒)はお好みで- レイアウトXMLから指定できるようにすると良いかもしれない