这篇博文是对viewpager自定义时一些零零散散的归纳,目的是能最方便地实现app中常见的banner广告。
---------------- 割 割 割-----------------
定制1:带有纵深的切换效果
方法:通过自定义PageTransformer,实现transformPage(View page, float position)方法。
PageTransformer depthTransformer = new PageTransformer() {
@Override
public void transformPage(View page, float position) {
int pageWidth = page.getWidth();
if (position < -1) { // [-Infinity,-1)
page.setAlpha(0);
} else if (position <= 0) { // [-1,0]
// Use the default slide transition when moving to the left page
page.setAlpha(1);
page.setTranslationX(0);
page.setScaleX(1);
page.setScaleY(1);
} else if (position <= 1) { // (0,1]
// Fade the page out.
page.setAlpha(1 - position);
// Counteract the default slide transition
page.setTranslationX(pageWidth * -position);
// Scale the page down (between MIN_SCALE and 1)
float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position));
page.setScaleX(scaleFactor);
page.setScaleY(scaleFactor);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
page.setAlpha(0);
}
}
};
viewpager.setPageTransformer(true, depthTransformer);
定制2:全自动轮播
方法:利用Handler.postDelay()方法,轮询调用Runnable自身
int maxCount = 0;
@Override
public void setAdapter(PagerAdapter adapter) {
super.setAdapter(adapter);
maxCount = getAdapter().getCount();
if (maxCount > 0 && AUTO_ANIM) {
mHandler.postDelayed(autoRun, DURATION);
}
}
Runnable autoRun = new Runnable() {
@Override
public void run() {
try {
mHandler.postDelayed(this, DURATION);
int nextPosition = getCurrentItem() + 1;
setCurrentItem(nextPosition % maxCount);
} catch (Exception e) {
}
}
};
定制3:控制切换动画的速度
setCurrentItem执行时会有一个切换的效果,时长很短,一闪而过,我们需要适当的延长切换动画。
另外当item横跨区间超过2个时,切换效果很糟糕,我们需要屏蔽切换动画。
上面的这两个需求,都可以通过自定义Scroller来实现。
public class MScroller extends Scroller {
private int mScrollDuration = 1000; //切换动画时长
private static final Interpolator sInterpolator = new Interpolator() {
@Override
public float getInterpolation(float t) {
t -= 1.0f;
return t * t * t * t * t + 1.0f;
}
};
public boolean noDuration;
public void setNoDuration(boolean noDuration) {
this.noDuration = noDuration;
}
public MScroller(Context context) {
this(context, sInterpolator);
}
public MScroller(Context context, Interpolator interpolator) {
super(context, interpolator);
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
if (noDuration) {
//不需要时间间隔
super.startScroll(startX, startY, dx, dy, 0);
} else {
super.startScroll(startX, startY, dx, dy, mScrollDuration);
}
}
}
然后在自定义vp初始化时通过反射设置vp的mScroller为自定义Scroller
private void init() {
scroller = new MScroller(getContext());
Class<ViewPager> cl = ViewPager.class;
try {
Field field = cl.getDeclaredField("mScroller");
field.setAccessible(true);
//利用反射设置mScroller域为自己定义的MScroller
field.set(this, scroller);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
设置跨度超过1个禁止动画的规则,重写setCurrentItem
@Override
public void setCurrentItem(int item, boolean smoothScroll) {
if (Math.abs(getCurrentItem() - item) > 1) {
scroller.setNoDuration(true);
super.setCurrentItem(item, smoothScroll);
scroller.setNoDuration(false);
} else {
scroller.setNoDuration(false);
super.setCurrentItem(item, smoothScroll);
}
}
完工!看下效果: