package cn.bingoogolapple.bgabanner;
import android.content.Context;
import android.support.v4.view.VelocityTrackerCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 作者:王浩 邮件:bingoogolapple@gmail.com
* 创建时间:15/6/19 11:23
* 描述:继承ViewPager,通过反射方式实现支持低版本上切换动画
*/
public class BGAViewPager extends ViewPager {
private boolean mAllowUserScrollable = true;
private AutoPlayDelegate mAutoPlayDelegate;
public BGAViewPager(Context context) {
super(context);
}
public BGAViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void setPageTransformer(boolean reverseDrawingOrder, ViewPager.PageTransformer transformer) {
/**
继承ViewPager,重写setPageTransformer方法,移除版本限制,通过反射设置参数和方法
getDeclaredMethod*()获取的是【类自身】声明的所有方法,包含public、protected和private方法。
getMethod*()获取的是类的所有共有方法,这就包括自身的所有【public方法】,和从基类继承的、从接口实现的所有【public方法】。
getDeclaredField获取的是【类自身】声明的所有字段,包含public、protected和private字段。
getField获取的是类的所有共有字段,这就包括自身的所有【public字段】,和从基类继承的、从接口实现的所有【public字段】。
*/
Class viewpagerClass = ViewPager.class;
try {
boolean hasTransformer = transformer != null;
Field pageTransformerField = viewpagerClass.getDeclaredField("mPageTransformer");
pageTransformerField.setAccessible(true);
PageTransformer mPageTransformer = (PageTransformer) pageTransformerField.get(this);
boolean needsPopulate = hasTransformer != (mPageTransformer != null);
pageTransformerField.set(this, transformer);
Method setChildrenDrawingOrderEnabledCompatMethod = viewpagerClass.getDeclaredMethod("setChildrenDrawingOrderEnabledCompat", boolean.class);
setChildrenDrawingOrderEnabledCompatMethod.setAccessible(true);
setChildrenDrawingOrderEnabledCompatMethod.invoke(this, hasTransformer);
Field drawingOrderField = viewpagerClass.getDeclaredField("mDrawingOrder");
drawingOrderField.setAccessible(true);
if (hasTransformer) {
drawingOrderField.setInt(this, reverseDrawingOrder ? 2 : 1);
} else {
drawingOrderField.setInt(this, 0);
}
if (needsPopulate) {
Method populateMethod = viewpagerClass.getDeclaredMethod("populate");
populateMethod.setAccessible(true);
populateMethod.invoke(this);
}
} catch (Exception e) {
}
}
/**
* 设置调用setCurrentItem(int item, boolean smoothScroll)方法时,page切换的时间长度
*
* @param duration page切换的时间长度
*/
public void setPageChangeDuration(int duration) {
try {
Field scrollerField = ViewPager.class.getDeclaredField("mScroller");
scrollerField.setAccessible(true);
scrollerField.set(this, new BGABannerScroller(getContext(), duration));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 切换到指定索引的页面,主要用于自动轮播
*
* @param position
*/
public void setBannerCurrentItemInternal(int position, boolean smoothScroll) {
Class viewpagerClass = ViewPager.class;
try {
Method setCurrentItemInternalMethod = viewpagerClass.getDeclaredMethod("setCurrentItemInternal", int.class, boolean.class, boolean.class);
setCurrentItemInternalMethod.setAccessible(true);
setCurrentItemInternalMethod.invoke(this, position, smoothScroll, true);
ViewCompat.postInvalidateOnAnimation(this);
} catch (Exception e) {
}
}
/**
* 设置是否允许用户手指滑动
*
* @param allowUserScrollable true表示允许跟随用户触摸滑动,false反之
*/
public void setAllowUserScrollable(boolean allowUserScrollable) {
mAllowUserScrollable = allowUserScrollable;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (mAllowUserScrollable) {
return super.onInterceptTouchEvent(ev);
} else {
return false;
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (mAllowUserScrollable) {
if (mAutoPlayDelegate != null && (ev.getAction() == MotionEvent.ACTION_CANCEL || ev.getAction() == MotionEvent.ACTION_UP)) {
mAutoPlayDelegate.handleAutoPlayActionUpOrCancel(getXVelocity());
return false;
} else {
return super.onTouchEvent(ev);
}
} else {
return false;
}
}
private float getXVelocity() {
float xVelocity = 0;
Class viewpagerClass = ViewPager.class;
try {
Field velocityTrackerField = viewpagerClass.getDeclaredField("mVelocityTracker");
velocityTrackerField.setAccessible(true);
VelocityTracker velocityTracker = (VelocityTracker) velocityTrackerField.get(this);
Field activePointerIdField = viewpagerClass.getDeclaredField("mActivePointerId");
activePointerIdField.setAccessible(true);
Field maximumVelocityField = viewpagerClass.getDeclaredField("mMaximumVelocity");
maximumVelocityField.setAccessible(true);
int maximumVelocity = maximumVelocityField.getInt(this);
velocityTracker.computeCurrentVelocity(1000, maximumVelocity);
xVelocity = VelocityTrackerCompat.getXVelocity(velocityTracker, activePointerIdField.getInt(this));
} catch (Exception e) {
}
return xVelocity;
}
public void setAutoPlayDelegate(AutoPlayDelegate autoPlayDelegate) {
mAutoPlayDelegate = autoPlayDelegate;
}
public interface AutoPlayDelegate {
void handleAutoPlayActionUpOrCancel(float xVelocity);
}
}