自定义垂直滑动的viewpager,可无限循环,可定时切换

自定义的思路主要是继承viewpager,然后重写swapTouchEvent方法修改切换的手势,改成上下滑动来触发切换事件

public class VerticalViewPager extends ViewPager {
    private boolean isPagingEnabled = true;
    public VerticalViewPager(Context context) {
        super(context);
    }

    public VerticalViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    private MotionEvent swapTouchEvent(MotionEvent event) {
        float width = getWidth();
        float height = getHeight();
        event.setLocation((event.getY() / height) * width, (event.getX() / width) * height);
        return event;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return super.onInterceptTouchEvent(swapTouchEvent(MotionEvent.obtain(event)))&&this.isPagingEnabled;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return super.onTouchEvent(swapTouchEvent(MotionEvent.obtain(ev)))&&this.isPagingEnabled;
    }

    public void setPagingEnabled(boolean b) {
        this.isPagingEnabled = b;
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int height = 0;
        for(int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
            int h = child.getMeasuredHeight();
            if(h > height) height = h;
        }

        heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }



}

这里还涉及高度重绘和是否允许滑动的代码,整个viewpager的高度是通过最大子item的高度决定的,是否滑动可以通过setPagingEnabled来设置,默认是允许滑动

以上只是设置切换手势,切换的动画需要重新设置

public class VerticalTransformer implements ViewPager.PageTransformer{

    @Override
    public void transformPage(View view, float position) {
        view.setTranslationX(view.getWidth() * -position);
        float yPosition = position * view.getHeight();
        view.setTranslationY(yPosition);
    }
}

原本是x方向进行切换,但是设置成-position就抵消了,y方向进行切换,可以设置透明度,有需要可以

设置

mVerticalViewPager.setPageTransformer(true, new VerticalTransformer());

通过以上设置就完成一个垂直切换的viewpager,是不是很简单

下面是完整的调用

 private void initVerticalPager() {
        if (mVerticalViewPager == null) {
            mVerticalViewPager = (VerticalViewPager) getRootView().findViewById(R.id.vertical_viewpager);
            mVerticalPagerAdapter = new VerticalPagerAdapter();
            mVerticalViewPager.setAdapter(mVerticalPagerAdapter);
            mVerticalViewPager.setOverScrollMode(View.OVER_SCROLL_NEVER);
            mVerticalViewPager.setPageTransformer(true, new VerticalTransformer());
        } else {
            mVerticalPagerAdapter.notifyDataSetChanged();
        }
}

适配器

  private class VerticalPagerAdapter extends PagerAdapter {
        @Override
        public int getCount() {
            return Integer.MAX_VALUE;
        }

        @Override
        public boolean isViewFromObject(View view, Object o) {
            return view == o;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            View view = null;
            view = View.inflate(mContext, R.layout.weiget_main_information, null);
            switch(position%count){
            case 0:
                   view = ...;
                   break;
            case 1:
            ...
            }
            container.addView(view);
            return view;
        }
    }

这里设置一个伪无限循环的viewpager,所以在getCount方法中放回整形的最大值,实际上我们使用app的间内几乎不太可能通过滑动达到这个最大值,至于循环,就是根据需求在instantiateItem中实例化新的view,每次都要实例化新的view,并初始化数据,不用担心产生太多垃圾,因为在destroyItem方法中会去掉这个view,等待gc回收


    private static int SWITCH_TIME = 30*1000;
    
    public void startSwitchTask() {

        if (handler == null) {
            handler = new Handler();
        }
        handler.removeCallbacksAndMessages(null);
        handler.postDelayed(runnable,SWITCH_TIME);
    }

    public void stopSwitchTask() {
        if (handler != null) {
            handler.removeCallbacksAndMessages(null);
            handler = null;
        }

    }

  private Runnable runnable = new Runnable( ) {
        public void run ( ) {
            doSwitch();
            handler.postDelayed(this,SWITCH_TIME);
        }
    };

    private void doSwitch() {
        if(mVerticalViewPager ==null){
            return;
        }
        mVerticalViewPager.setCurrentItem(mVerticalViewPager.getCurrentItem()+1);
    }

实现定时的巧妙之处是

先通过handler.postDelayed触发runnable,然后在runnable中完成业务,并触发handler.postDelayed方法,这种方式由于使用了handler,需要在act声明周期内有效,如果act回收的时候,需要在onDestroy方法中调用stopSwitchTask方法,避免内存泄露。

doSwitch方法进行切换viewpager,position自增,无需维护额外的变量

为了避免一开始的时候需要上翻,所以设置position在中间的位置,例如1000,就足够了

 

 

转载于:https://my.oschina.net/carbenson/blog/904103

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值