Help us understand the problem. What is going on with this article?

[Android] ViewPagerの遷移アニメーションをカスタマイズする

More than 1 year has passed since last update.

[Android] ViewPagerの遷移アニメーションをカスタマイズする

by hkusu
1 / 23
  • 以前から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から指定できるようにすると良いかもしれない

END

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした