天天看点

viewpager从入门到精通4 优化轮播viewpager ViewPagerScroller PageTransformer

上一篇博客viewpager从入门到精通3 无限轮播viewpager 我们做了一个无限轮询的viewpager但是这个pager的效果不是很贴切,滑动不是很美观这里我们需要两个辅助帮助我们的viewpager滑动更流畅。

首先要介绍的是ViewPagerScroller 代码如下

public class ViewPagerScroller extends Scroller {
    private int mDuration;

    public ViewPagerScroller(Context context) {
        super(context);
    }

    public ViewPagerScroller(Context context, Interpolator interpolator) {
        super(context, interpolator);
    }

    public void setDuration(int mDuration) {
        this.mDuration = mDuration;
    }

    @Override
    public void startScroll(int startX, int startY, int dx, int dy) {
        super.startScroll(startX, startY, dx, dy, this.mDuration);
    }

    @Override
    public void startScroll(int startX, int startY, int dx, int dy, int duration) {
        super.startScroll(startX, startY, dx, dy, this.mDuration);
    }
}
           

都是实现的Scroller 的一些方法,接下来我们就将这个scoller放到自定义viewpager中去。

public class MyViewPager extends ViewPager {
    private static final int START_SCROLL_ANIM = ;//开启滚动处理
    private static final int STOP_SCROLL_ANIM = ;//关闭滚动处理
    private static final int LOOP_MESSAGE = ;//循环消息
    MyHeaderPagerHandler handler;
    private int changePagerSpeed = ;//切换页面速度
    private int loopSpeed = ;//每个item切换间隔
    private boolean ifStopAnim = false;

    public MyViewPager(Context context) {
        this(context, null);
    }

    public MyViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        handler = new MyHeaderPagerHandler(new WeakReference<>(this));
        setViewPagerScrollSpeed();
    }
    //pager切换控制--------------------------------------------------------------------------------------------------------------------------
    private void setViewPagerScrollSpeed() {
        try {
            Field field = ViewPager.class.getDeclaredField("mScroller");
            field.setAccessible(true);
            ViewPagerScroller viewPagerScroller = new ViewPagerScroller(getContext(), new AccelerateDecelerateInterpolator());
            field.set(this, viewPagerScroller);
            viewPagerScroller.setDuration(changePagerSpeed);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    //滑动控制--------------------------------------------------------------------------------------------------------------------------
    public void startScroll() {
        ifStopAnim = false;
        Message message = new Message();
        message.what = START_SCROLL_ANIM;
        handler.sendMessage(message);
    }

    public void startScroll(long delay) {
        ifStopAnim = false;
        Message message = new Message();
        message.what = START_SCROLL_ANIM;
        handler.sendMessageDelayed(message, delay);
    }

    public void stopScroll() {
        ifStopAnim = true;
        handler.removeCallbacksAndMessages(null);
    }

    private void loopMessage() {
        Message message = new Message();
        message.what = LOOP_MESSAGE;
        handler.sendMessageDelayed(message, loopSpeed);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                stopScroll();
                break;
            case MotionEvent.ACTION_UP:
                startScroll();
                break;
        }
        return super.onTouchEvent(ev);
    }

    private static class MyHeaderPagerHandler extends Handler {
        private WeakReference<MyViewPager> myPager;

        MyHeaderPagerHandler(WeakReference<MyViewPager> myPager) {
            this.myPager = myPager;
        }

        @Override
        public void handleMessage(Message msg) {
            if (myPager.get() == null) return;
            if (myPager.get().ifStopAnim) return;
            super.handleMessage(msg);
            switch (msg.what) {
                case START_SCROLL_ANIM:
                    myPager.get().loopMessage();
                    break;
                case STOP_SCROLL_ANIM:
                    break;
                case LOOP_MESSAGE:
                    myPager.get().setCurrentItem(myPager.get().getCurrentItem() + , true);
                    myPager.get().loopMessage();
                    break;
            }
        }
    }
}
           

重点是setViewPagerScrollSpeed这个方法我们再里面通过反射获取到了mScroller这个Field 然后通过field.set(this, viewPagerScroller); viewPagerScroller.setDuration(changePagerSpeed);设置切换时长以及切换的动画,这里我选择了AccelerateDecelerateInterpolator这个动画差值器即刚开始缓慢中间加速再到最后减速。

到这里其实我们的viewpager已经滑动非常流畅了效果也不错,为了更加提升显示效果我们这里可以给viewpager添加一个PageTransformer更改滑动过程的效果。

代码如下

public class MyPageTransform implements ViewPager.PageTransformer {
    private static final float MIN_SCALE = f;
    private static final float MIN_ALPHA = f;

    public void transformPage(View view, float position) {
        int pageWidth = view.getWidth();
        int pageHeight = view.getHeight();
        if (position < -) { // [-Infinity,-1)
            view.setAlpha();
        } else if (position <= ) { // [-1,1]//a页滑动至b页 ; a页从 0.0 -1 ;b页从1 ~ 0.0
            float scaleFactor = Math.max(MIN_SCALE,  - Math.abs(position));
            float vertMargin = pageHeight * ( - scaleFactor) / ;
            float horzMargin = pageWidth * ( - scaleFactor) / ;
            if (position < ) {
                view.setTranslationX(horzMargin - vertMargin / );
            } else {
                view.setTranslationX(-horzMargin + vertMargin / );
            }
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);
            view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / ( - MIN_SCALE) * ( - MIN_ALPHA));
        } else { // (1,+Infinity]// This page is way off-screen to the right.
            view.setAlpha();
        }
    }
}
           

实现也是非常简单的接下来就是调用过程代码如下。

public class MainActivity4 extends AppCompatActivity {
    private MyViewPager vp_mian1;
    private MyPagerAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main4);
        vp_mian1 = findViewById(R.id.vp_mian1);
        List<View> itemViews = installItems();
        adapter = new MyPagerAdapter(itemViews);
        vp_mian1.setAdapter(adapter);
        vp_mian1.setCurrentItem(itemViews.size() * );
        vp_mian1.setPageTransformer(true, new MyPageTransform());
        vp_mian1.startScroll();
    }

    public List<View> installItems() {
        List<View> views = new ArrayList<>();
        int drawables[] = {R.drawable.d_01, R.drawable.d_02, R.drawable.d_03, R.drawable.d_04, R.drawable.d_05};
        for (int i = ; i < ; i++) {
            RelativeLayout rlHeaderItem = (RelativeLayout) LayoutInflater.from(this).inflate(R.layout.header_pager_view, null);
            ImageView ivItem = rlHeaderItem.findViewById(R.id.iv_header_item);
            ivItem.setBackgroundDrawable(getResources().getDrawable(drawables[i]));
            views.add(rlHeaderItem);
        }
        return views;
    }

    @Override
    protected void onDestroy() {
        vp_mian1.stopScroll();
        super.onDestroy();
    }
}
           

通过 vp_mian1.setPageTransformer(true, new MyPageTransform());设置viewpager的PageTransforme,这样viewpager的效果就更加漂亮了。

接下来我们介绍在listview的headerview中添加viewpager链接如下。

viewpager从入门到精通5 listview中headerview添加viewpager

GitHub传送门点击这里

继续阅读