一、自定義BannerViewPager
①、繼承自ViewPager善绎,重寫(xiě)構(gòu)造
②、自定義BannerViewPagerAdapter 繼承PagerAdapter
public class BannerViewPager extends ViewPager{
public BannerViewPager(Context context) {
this(context, null);
}
public BannerViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
private class BannerViewPagerAdapter extends PagerAdapter{
@Override
public int getCount() {
}
@Override
public boolean isViewFromObject(View view, Object object) {
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
}
}
}
③诫尽、創(chuàng)建setAdapter()
public void setAdapter(BannerAdapter adapter) {
this.mAdapter=adapter;
//設(shè)置父類(lèi) ViewPager的Adapter
setAdapter(new BannerViewPagerAdapter());
//可以向左滑動(dòng)
setCurrentItem(mAdapter.getCount() * 1000);
}
其中BannerAdapter 為
public abstract class BannerAdapter {
/**
* 根據(jù)位置獲取ViewPage中的子View
* @param position
* @return
*/
public abstract View getView(int position,View convertView);
/***
* 獲取有多少條
* @return
*/
public abstract int getCount();
}
適配器方法
public int getCount() {
//實(shí)現(xiàn)無(wú)線循環(huán)
return Integer.MAX_VALUE;
}
/**
* 創(chuàng)建條目回調(diào)的方法
*
* @param container
* @param position
* @return
*/
@Override
public Object instantiateItem(ViewGroup container, int position) {
//用Adapter設(shè)計(jì)模式 可以自定義view position%mAdapter.getCount())取余
position %= mAdapter.getCount();
if (position<0){
position=mAdapter.getCount()+position;
}
View bannerItemView = mAdapter.getView(position, getConvertView());
//添加到viewpage中
container.addView(bannerItemView);
return bannerItemView;
}
/**
* 銷(xiāo)毀條目回調(diào)的方法
* @param container
* @param position
* @param object
*/
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View)object);
//界面復(fù)用
mConvertViews.add((View) object);
}
界面復(fù)用
/**
* 界面復(fù)用
* @return
*/
public View getConvertView() {
for (int i = 0; i < mConvertViews.size(); i++) {
//獲取沒(méi)有添加到ViewPage 中的View
if (mConvertViews.get(i).getParent()==null){
return mConvertViews.get(i);
}
}
return null;
}
④自動(dòng)輪播
/**
* 開(kāi)始輪播
*/
public void startRoll(){
isRoll=true;
//清楚消息
mHandler.removeMessages(SCROLL_MSG);
//發(fā)送延遲消息 實(shí)現(xiàn)輪播
mHandler.sendEmptyMessageDelayed(SCROLL_MSG, mCutDownTime);
}
mHandler接收
// 發(fā)送消息的 msg
private final int SCROLL_MSG=0x0011;
//默認(rèn)輪播時(shí)間
private int mCutDownTime=3500;
//是否輪播
private boolean isRoll=false;
private Handler mHandler=new Handler(){
@Override
public void handleMessage(Message msg) {
//調(diào)用 父類(lèi)方法 切換到下一頁(yè)
setCurrentItem(getCurrentItem()+1);
//不斷循環(huán)調(diào)用
startRoll();
}
};
⑤禀酱、改變切換速率 利用反射
public BannerViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
try {
//改變切換速率 duration 持續(xù)時(shí)間為局部變量 要想改變通過(guò)反射
Field field= ViewPager.class.getDeclaredField("mScroller");
//設(shè)置參數(shù)
bannerScroller = new BannerScroller(context);
//設(shè)置強(qiáng)制改變 private
field.setAccessible(true);
field.set(this, bannerScroller);
} catch (Exception e) {
e.printStackTrace();
}
mConvertViews=new ArrayList<>();
}
BannerScroller類(lèi)
public class BannerScroller extends Scroller {
//動(dòng)畫(huà)持續(xù)的時(shí)間
private int mScrollerDuration=950;
/**
* 設(shè)置動(dòng)畫(huà)切換的時(shí)間
* @param mScrollerDuration
*/
public void setmScrollerDuration(int mScrollerDuration) {
this.mScrollerDuration = mScrollerDuration;
}
public BannerScroller(Context context) {
super(context);
}
public BannerScroller(Context context, Interpolator interpolator) {
super(context, interpolator);
}
public BannerScroller(Context context, Interpolator interpolator, boolean flywheel) {
super(context, interpolator, flywheel);
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
super.startScroll(startX, startY, dx, dy, mScrollerDuration);
}
}
⑥、觸摸時(shí)停止輪播
/**
* 觸摸監(jiān)聽(tīng) 停止自動(dòng)輪播
* @param ev
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
//從消息隊(duì)列中移除所有message
//停止輪播
if (isRoll){
mHandler.removeMessages(SCROLL_MSG);
}
break;
case MotionEvent.ACTION_UP:
if (isRoll){
//重新發(fā)送
mHandler.sendEmptyMessageDelayed(SCROLL_MSG, mCutDownTime);
}
break;
}
return super.onTouchEvent(ev);
}
⑦牧嫉、防止泄漏
/**
* Activity銷(xiāo)毀 時(shí)回調(diào)該方法
*
* 防止內(nèi)存泄露
*/
@Override
protected void onDetachedFromWindow() {
mHandler.removeMessages(SCROLL_MSG);
mHandler=null;
//解除綁定
((Activity) getContext()).getApplication().unregisterActivityLifecycleCallbacks(activityLifecycleCallbacks);
super.onDetachedFromWindow();
}
⑧剂跟、不可見(jiàn)時(shí),停止發(fā)送
//Activity生命周期管理
Application.ActivityLifecycleCallbacks activityLifecycleCallbacks=new DefaultActivityLifecycleCallbacks() {
@Override
public void onActivityResumed(Activity activity) {
//實(shí)現(xiàn)輪播 是否是當(dāng)前的Activity
if (activity==getContext()&& isRoll){
//發(fā)送延遲消息 實(shí)現(xiàn)輪播
mHandler.sendEmptyMessageDelayed(SCROLL_MSG, mCutDownTime);
}
}
@Override
public void onActivityPaused(Activity activity) {
if (activity==getContext()&& isRoll){
//停止輪播
mHandler.removeMessages(SCROLL_MSG);
}
}
};
DefaultActivityLifecycleCallbacks類(lèi)實(shí)現(xiàn)
public class DefaultActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
}