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

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

1 先看API

ViewPage2.setPageTransformer(@Nullable PageTransformer transformer)

less 复制代码
public void setPageTransformer(@Nullable PageTransformer transformer) 

public interface PageTransformer

less 复制代码
void transformPage(@NonNull View page, float position);

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

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

less 复制代码
public void setOffscreenPageLimit(@OffscreenPageLimit int limit)

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

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

分析OffscreenPageLimit = 1

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

分析transformPage

接口 PageTransformer 在滑动中回调

less 复制代码
void transformPage(@NonNull View page, float position);

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

观察Postion

问题一 pageX任意一个 , postion = 0.5是什么意思
ini 复制代码
答:说明有一个页面右滑滑到了当前Viewpage 右边的一半距离了,如图,就说明page1滑到了一半。这里前提是当前的current == 1 ,反之如果是current == 0 就是左滑
问题二 Position [0,1],[-1,0] 含义
sql 复制代码
答:其实Postion是针对可视区域(current)来说的,就是代表当前可视在屏幕中偏移量
0就是完全处于正常居中展示,1就是代表在当前的右边,-1就是在左边

设置属于自己的PageTransformer

less 复制代码
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); 核心代码,就是让左右两边挤过来。

可以这样尝试理解;

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

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

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

这是就是简单的卡片效果

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

less 复制代码
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);
    }
});

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

less 复制代码
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);
        
    }
});

总结

只要使用中把握住 -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 。这个代码就是最终的表现方式

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

scss 复制代码
if(position >= 0 ){
    ****
}else if(postion <0){
    ****
}

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

相关推荐
2401_882727571 小时前
低代码配置式组态软件-BY组态
前端·后端·物联网·低代码·前端框架
NoneCoder1 小时前
CSS系列(36)-- Containment详解
前端·css
anyup_前端梦工厂2 小时前
初始 ShellJS:一个 Node.js 命令行工具集合
前端·javascript·node.js
5hand2 小时前
Element-ui的使用教程 基于HBuilder X
前端·javascript·vue.js·elementui
GDAL2 小时前
vue3入门教程:ref能否完全替代reactive?
前端·javascript·vue.js
六卿2 小时前
react防止页面崩溃
前端·react.js·前端框架
z千鑫2 小时前
【前端】详解前端三大主流框架:React、Vue与Angular的比较与选择
前端·vue.js·react.js
m0_748256143 小时前
前端 MYTED单篇TED词汇学习功能优化
前端·学习
小白学前端6664 小时前
React Router 深入指南:从入门到进阶
前端·react.js·react
web130933203984 小时前
前端下载后端文件流,文件可以下载,但是打不开,显示“文件已损坏”的问题分析与解决方案
前端