天天看點

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傳送門點選這裡

繼續閱讀