一看就会的 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){
    ****
}

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

相关推荐
kyriewen3 小时前
Anthropic 估值逼近万亿美元,Claude Sonnet 5 + Claude Science 一天两连发
前端·ai编程·claude
小徐_23335 小时前
Wot UI 2.2.0 发布:Button 新增 subtle,VideoPreview 预览体验继续增强
前端·微信小程序·uni-app
天蓝色的鱼鱼7 小时前
关于 CSS 你可能不知道的属性,但关键时刻很有用
前端·css
泯泷8 小时前
第 2 篇:设计第一套字节码:Opcode、Instruction 与 Constant Pool
前端·javascript·安全
妙码生花8 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(十五):优化细节、网络请求封装
前端·后端·ai编程
泯泷8 小时前
第 1 篇:从 1 + 2 开始:亲手写出第一台 JSVM
前端·javascript·安全
团团崽_七分甜8 小时前
Spring Boot 核心知识点总结
前端
lichenyang4538 小时前
从一个按钮开始,理解 ASCF 框架到底在做什么
前端
古夕9 小时前
第三方 SSO 接入实践:redirect_uri 编码、回调一致性与跨项目联调
前端·vue.js