ViewPager一屏显示多个页面

您所在的位置:网站首页 word一屏显示很多页 ViewPager一屏显示多个页面

ViewPager一屏显示多个页面

2024-06-16 06:27| 来源: 网络整理| 查看: 265

使用ViewPager一般我们只需要一屏只显示一个页面,例如引导页、轮播图等。但它如何能一屏显示多个页面呢?其实很简单就是在控件的父布局或根布局添加clipChildren=false属性即可。

android:clipChildren属性:是否限制子控件在其范围内显示,也就是说当子控件超出父控件规定大小时,超出部分是否显示,clipChildren默认值为true。 也就是不允许超出绘制

效果图

这里写图片描述

示例代码

1:布局文件

2:设置切换动画

public class ZoomOutPageTransformer implements ViewPager.PageTransformer { public static final float MIN_SCALE = 0.8f;//原图片缩小0.8倍 private static final float MIN_ALPHA = 0.6f;//透明度 public void transformPage(View page, float position) { if (position < -1) {//[-Infinity,-1)左边显示出半个的page page.setAlpha(MIN_ALPHA);//设置page的透明度 page.setScaleX(MIN_SCALE); page.setScaleY(MIN_SCALE); } else if (position //[1,0] 第二页向左移动 成currentItem if (position > 0.2) position = 0.2f; page.setAlpha(1f -position*2); page.setScaleY(1f - position); page.setScaleX(1f - position); } } else {//(1,+Infinity]右边显示出半个的page page.setAlpha(MIN_ALPHA); page.setScaleX(MIN_SCALE); page.setScaleY(MIN_SCALE); } } }

postion主要分为

[-Infinity,-1)[-1,1](1,+Infinity]

第一个对应左边显示一点的page,第二个对应中间显示的page,第三个对应右边显示一点的page。 第一个和第三个只需要设置最小值就可以。 第二个还需要细分为(0,-1]和[1,0]

由第一页滑动到第二页来说: 页1的position变化为:从0到-1 页2的position变化为:从1到0

由于Scale缩放倍数是0.8,所以在页面滑动时对position做了一些限制,使其不超过0.8 由于ALPHA透明倍数是0.6,所以在[-1,1]之间需要乘以2,否则透明度过度会很突兀

3:自定义Viewpager

捕获viewpager的父控件的触摸事件,并传递给viewpager,用于全屏滑动

mRoot.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return mVp.dispatchTouchEvent(event); } }); public class ViewPagerAllResponse extends ViewPager { private final static float DISTANCE = 10;//默认距离 private float downX; private float downY; private float upX; private float upY; public ViewPagerAllResponse(Context context) { this(context, null); } public ViewPagerAllResponse(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { downX = ev.getX(); downY = ev.getY(); } else if (ev.getAction() == MotionEvent.ACTION_UP) { upX = ev.getX(); upY = ev.getY(); //滑动时进入 if (Math.abs(upX - downX) > DISTANCE || Math.abs(upY - downY) > DISTANCE) { return super.dispatchTouchEvent(ev); } //点击时进入 View view = clickPageOnScreen(ev); if (view != null) { int index = (Integer) view.getTag(); if (getCurrentItem() != index) { setCurrentItem(index); return true; } } else { return true; } } return super.dispatchTouchEvent(ev); } /** * 是否点击到两边的View * 点到View则返回该View,否则返回null */ private View clickPageOnScreen(MotionEvent ev) { int childCount = getChildCount(); int currentIndex = getCurrentItem(); int[] location = new int[2]; float x = ev.getRawX(); for (int i = 0; i < childCount; i++) { View v = getChildAt(i); int position = (Integer) v.getTag(); v.getLocationOnScreen(location); int minX = location[0]; int maxX = location[0] + v.getWidth(); if (position < currentIndex) { //maxX-view宽度*View缩放了宽度的一半 maxX -= v.getWidth() * (1 - ZoomOutPageTransformer.MIN_SCALE) * 0.5; minX -= v.getWidth() * (1 - ZoomOutPageTransformer.MIN_SCALE) * 0.5; } if ((x > minX && x < maxX)) { return v; } } return null; } /** * 解决当手指在第1页左边空白区域上下滑动时,不让page的点击事件触发 */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: downY = ev.getY(); break; case MotionEvent.ACTION_UP: upY = ev.getY(); if (Math.abs(upY - downY) > DISTANCE) { return true;//拦截事件 传递给自己的onTouchEvent处理 } break; default: break; } return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: downY = ev.getY(); break; case MotionEvent.ACTION_UP: upY = ev.getY(); if (Math.abs(upY - downY) > DISTANCE) { return super.onTouchEvent(ev);//不消费事件,事件继续往上传递 } break; default: break; } return super.onTouchEvent(ev); } } 复写dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent方法,解决在两侧page页上下滑动时,响应点击事件,即阻止了page的点击事件触发复写dispatchTouchEvent方法,在其clickPageOnScreen方法内判断是否为中间page的点击事件,如果是则响应点击事件,否则则只设置setCurrentItem(index)使其跳到中间

4:Activity中设置

ViewpagerAdapter adapter = new ViewpagerAdapter(this, mVp, list); mVp.setAdapter(adapter); //设置缓存数为展示的数目 mVp.setOffscreenPageLimit(list.size()); //设置切换动画 mVp.setPageTransformer(true, new ZoomOutPageTransformer()); //设置Page间间距 mVp.setPageMargin(0);

注意 不设置setPageMargin大小两个page页也是有间距的 间距大小=page原大小*(1-缩放倍数)/2 如图 这里写图片描述

总结

其实效果实现起来并不难,只要理解了clipChildren属性的作用,再自定义一个PageTransformer过渡动画,ViewPager的各种效果也就不难实现了。

当然了,如果你不想用clipChildren属性,或者说使用继承PagerAdapter的方式定义布局不方便,则可以使用Viewpager添加Fragment方式来实现。效果图和上面一样就不再放了,所有实现方式再源码中都有,感兴趣可以戳源码下载。

源码下载 Demo下载



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3