ViewPage2 的使用相信各位大佬都信手拈来了 这里就跳过设置Adapter的步骤直接来研究他的这个PageTransformer

1 先看API

ViewPage2.setPageTransformer(@Nullable PageTransformer transformer)

public void setPageTransformer(@Nullable PageTransformer transformer)

一看就会的 ViewPage2 的 PageTransformer 的使用!!一起冲晕他

public interface PageTransformer

一看就会的 ViewPage2 的 PageTransformer 的使用!!一起冲晕他

void transformPage(@NonNull View page, float position);

PageTransformer 接口只有一个方法 transformPage(View page, float position) 。 page就是被移动的视图,position如上解释,代表偏移量

其中Page在滑动过程中会被多次回调,并且每次回调的都不一定是同一个Page。因为当你在滑动中时候 你的 page0(当前current Position)往左,而右边的page1也会跟着一起移动,而后面的page2也会同步移动 。其实右边的page1page2的数量是 ,下面的这api的缓存数量来决定的

public void setOffscreenPageLimit(@OffscreenPageLimit int limit)

一看就会的 ViewPage2 的 PageTransformer 的使用!!一起冲晕他
当你的 OffscreenPageLimit = 1 ,那么默认 page1会加载。如果你的 OffscreenPageLimit2。那么page2会被加载,所以得看你的滑动动画ui表现。所以一般情况是不需要使用到page2的视图。所以设置 OffscreenPageLimit = 1 即可

“所以一般情况是不需要使用到page2的视图” 这里意思是,你的滑动中根本看不到page2的ui。所以不需要提前加载page2

分析OffscreenPageLimit = 1

代表缓存中会预加载加载左右两页,其实Viewpage2 内部使用RecycleView来维护的

分析transformPage

接口 PageTransformer 在滑动中回调

void transformPage(@NonNull View page, float position);

而这里会被多次回调,其中如果默认冲position = 0 第一位开始的话 View page 将会是 page0page1。意思是transformPage每次回调有可能是page0,也有可能是page1,在滑动的时候。那么如何知道滑动的距离和情况呢。现在就得观察Postion的变化。

观察Postion

一看就会的 ViewPage2 的 PageTransformer 的使用!!一起冲晕他

问题一 pageX任意一个 , postion = 0.5是什么意思
答:说明有一个页面右滑滑到了当前Viewpage 右边的一半距离了,如图,就说明page1滑到了一半。这里前提是当前的current == 1 ,反之如果是current == 0 就是左滑

一看就会的 ViewPage2 的 PageTransformer 的使用!!一起冲晕他

问题二 Position [0,1],[-1,0] 含义
答:其实Postion是针对可视区域(current)来说的,就是代表当前可视在屏幕中偏移量
0就是完全处于正常居中展示,1就是代表在当前的右边,-1就是在左边

设置属于自己的PageTransformer

一看就会的 ViewPage2 的 PageTransformer 的使用!!一起冲晕他

public class ViewpageActivity extends AppCompatActivity {
    @NonNull
    ActivityViewpageBinding activityViewpageBinding;
    int[] colors = {Color.BLACK, Color.DKGRAY, Color.GRAY, Color.LTGRAY, Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW, Color.CYAN, Color.MAGENTA};
    private int indexColor = 0;
    int getColorByIndex() {
        int c = colors[indexColor++];
        if (indexColor == colors.length) {
            indexColor = 0;
        }
        return c;
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_viewpage);
        activityViewpageBinding = DataBindingUtil.setContentView(this, R.layout.activity_viewpage);
        activityViewpageBinding.idViewpage.setOffscreenPageLimit(1);
        activityViewpageBinding.idViewpage.setAdapter(new RecyclerView.Adapter<SimpleHodler>() {
            @NonNull
            @Override
            public SimpleHodler onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
                return new SimpleHodler(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_bg, parent, false));
            }
            @Override
            public void onBindViewHolder(@NonNull SimpleHodler holder, int position) {
                holder.contentView.setBackgroundColor(getColorByIndex());
            }
            @Override
            public int getItemCount() {
                return Integer.MAX_VALUE;
            }
        });
        activityViewpageBinding.idViewpage.setCurrentItem(Integer.MAX_VALUE / 2);
        activityViewpageBinding.idViewpage.addItemDecoration(new RecyclerView.ItemDecoration() {
            @Override
            public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
                outRect.right = 100;
                outRect.left = 100;
            }
        });
        activityViewpageBinding.idViewpage.setPageTransformer(new ViewPager2.PageTransformer() {
            @Override
            public void transformPage(@NonNull View page, float position) {
                page.setTranslationX(-150 * position);
            }
        });
    }
    static class SimpleHodler extends RecyclerView.ViewHolder {
        View contentView;
        public SimpleHodler(@NonNull View itemView) {
            super(itemView);
            contentView = itemView.findViewById(R.id.id_view);
        }
    }
}

page.setTranslationX(-150 * position); 核心代码,就是让左右两边挤过来。

一看就会的 ViewPage2 的 PageTransformer 的使用!!一起冲晕他

可以这样尝试理解;

当你左边不滑动时候,这个左page TranslationX = -150 * -1 = 150 ;向迁移150个像素

当你右边不滑动时候,这个右page TranslationX = -150 * 1 = -150 ;向迁移150个像素

再配合 ItemDecoration outRect.right = 100; outRect.left = 100; 给每个page增加左右100像素间距

这是就是简单的卡片效果

如果你想加其他效果比如放大/缩小

一看就会的 ViewPage2 的 PageTransformer 的使用!!一起冲晕他

activityViewpageBinding.idViewpage.setPageTransformer(new ViewPager2.PageTransformer() {
    @Override
    public void transformPage(@NonNull View page, float position) {
        page.setTranslationX(-350 * position);
        page.setScaleX(1 - Math.abs(position) * 0.4f);
        page.setScaleY(1 - Math.abs(position) * 0.4f);
    }
});

一看就会的 ViewPage2 的 PageTransformer 的使用!!一起冲晕他

其他效果比如透明度和旋转

一看就会的 ViewPage2 的 PageTransformer 的使用!!一起冲晕他

activityViewpageBinding.idViewpage.setPageTransformer(new ViewPager2.PageTransformer() {
    @Override
    public void transformPage(@NonNull View page, float position) {
        page.setTranslationX(-350 * position);
        page.setScaleX(1 - Math.abs(position) * 0.4f);
        page.setScaleY(1 - Math.abs(position) * 0.4f);
        page.setAlpha(1 - Math.abs(position) * 0.7f);
        page.setRotation(10 * position);
    }
});

一看就会的 ViewPage2 的 PageTransformer 的使用!!一起冲晕他

总结

只要使用中把握住 -1,0,1的变量即可。比如 你需要一个透明渐变 在左右两边是 0.5f alpha,那么你可以先写好,最基本的3个固定值用来观测

左边, position = -1 写成 setAlpha(–1 * 0.5)

中间, position = 0 任意 setAlpha(0 * 0.5)

右边边,position = 1 写成 setAlpha(1 * 0.5)

所以但你要综合情况的时候得出 page.setAlpha(1 – Math.abs(position) * 0.7f); 这公式既满足了 position = -1 也满足 position = 1 也满足 position = 0 。这个代码就是最终的表现方式

其他的也一样道理,如果情况很复杂还可以分别判断

if(position >= 0 ){
    ****
}else if(postion <0){
    ****
}

好了希望能帮到有需要的人