上一篇部落格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傳送門點選這裡