安卓中今天來(lái)講講Android中經(jīng)常用到的輪播圖:
剛開(kāi)始都是用網(wǎng)上的三方庫(kù)寫(xiě)實(shí)現(xiàn)banner圖,看起來(lái)好看還方便,但是用的時(shí)間長(zhǎng)了感覺(jué)我們只是會(huì)用網(wǎng)上的一些庫(kù),但是網(wǎng)上的庫(kù)比較強(qiáng)大,但是代碼也比較多,我們其實(shí)只是用眾多東西中的幾個(gè)類,但是我們到項(xiàng)目的時(shí)候,所有的類都要導(dǎo)入,這樣就增加了我們AndroidStudio的編譯時(shí)1間,有時(shí)要改東西,這些庫(kù)有不怎么支持,就又要換庫(kù),這樣會(huì)就增加了我們的成本:今天就來(lái)分享下我自己寫(xiě)的一個(gè)banner輪播圖:

1.首先寫(xiě)一個(gè)自定義一個(gè)BannerPagerAdapter如下:
public class BannerPagerAdapterextends PagerAdapter {
@Override
? ? public int getCount() {
return Integer.MAX_VALUE;
? ? }
@Override
? ? public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
? ? }
@NonNull
@Override
? ? public ObjectinstantiateItem(@NonNull ViewGroup container, int position) {
View view =adapter.getView(position %adapter.getContent(), getConverViews());
? ? ? ? container.addView(view);
? ? ? ? return view;
? ? }
@Override
? ? public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
? ? container.removeView((View) object);
? }
}
這viewpage的adapter已經(jīng)寫(xiě)完了:然后設(shè)置viewpage:綁定:一個(gè)可以滑動(dòng)的viewpage就可以實(shí)現(xiàn)了:
2.接下來(lái)就是實(shí)現(xiàn)定時(shí)播放viewpage,這里我采用的是hanndler實(shí)現(xiàn)的輪播圖:
private Handlerhandler =new Handler() {
@Override
? ? public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
? ? ? ? switch (msg.what) {
case MESSAGE_WHAT:
setCurrentItem(getCurrentItem() +1);
? ? ? ? ? ? ? ? handler.sendEmptyMessageDelayed(MESSAGE_WHAT, START_TIME);
break;
? ? ? ? }
}
};
然后在就是開(kāi)始播放:
/*開(kāi)啟播放*/
public void setStartbanner() {
handler.removeMessages(MESSAGE_WHAT); // 防止多條消息
? ? handler.sendEmptyMessageDelayed(MESSAGE_WHAT, START_TIME);
}
這樣一個(gè)播放的循環(huán)播放的viewpage就實(shí)現(xiàn)了。
3.這樣當(dāng)我們的Activity關(guān)閉時(shí),handler還在發(fā)消息,這樣就造成內(nèi)存泄漏:
因?yàn)槲覀兊膆anndler是在自定義的viewpage中的我們可以直接調(diào)用onDetachedFromWindow方法在其中移除handler,如果實(shí)在activity可以直接在onDestroy中關(guān)閉消息:
handler.removeMessages(MESSAGE_WHAT);
4.切換速率修改
看起來(lái)我們的自定義viewpage的輪播圖已經(jīng)實(shí)現(xiàn)完畢基本上寫(xiě)完,運(yùn)行起來(lái)一看,這個(gè)切換速率有點(diǎn)快:我們一看網(wǎng)上的三方庫(kù)切換都是有點(diǎn)時(shí)間:接下來(lái)我們就去看看viewpage的源碼,看看這個(gè)切換效率在哪修改我看看源碼發(fā)現(xiàn)了這句畫(huà):

點(diǎn)進(jìn)去一看設(shè)置時(shí)間就在這個(gè)類中:

看見(jiàn)這個(gè)設(shè)置時(shí)間,系統(tǒng)是250ms我們將這個(gè)時(shí)間修改了,應(yīng)該就把完成了,突然發(fā)現(xiàn):
private ScrollermScroller;
這個(gè)屬性在源碼中是私有的,這我們想到用java的反射拿出來(lái),修改:
/**
* 設(shè)置viewpage切切換時(shí)間
*/
private void initViewPagerScroll() {
try {
Field mField = ViewPager.class.getDeclaredField("mScroller");
? ? ? ? mField.setAccessible(true);
? ? ? ? BannerScroller mScroller =new BannerScroller(viewPage.getContext(), new AccelerateInterpolator());
? ? ? ? mField.set(viewPage, mScroller);
? ? }catch (Exception e) {
Log.e("viewpage切換速率", e.getMessage());
? ? }
}
接下來(lái)運(yùn)行起來(lái),這樣速度也可以了:
5.處理滑動(dòng)和定時(shí)的沖突:
我們運(yùn)行完,發(fā)現(xiàn)還不錯(cuò),用手按住滑動(dòng)發(fā)現(xiàn):這個(gè)拖動(dòng)的時(shí)候,還在定時(shí)運(yùn)行,接下來(lái),我們?cè)谔幚硐掠|摸時(shí)間和定時(shí):
1.在我們觸摸banner是結(jié)束定時(shí),離開(kāi)試重新計(jì)時(shí):
2,在dispatchTouchEvent方法中處理觸摸事件:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
handler.removeMessages(MESSAGE_WHAT);
break;
? ? ? ? case MotionEvent.ACTION_UP:
setStartbanner();
break;
? ? }
return super.dispatchTouchEvent(ev);
}
接下來(lái)就是處理小圓點(diǎn)了,這個(gè)我用的是自定義view畫(huà)了兩個(gè):
這個(gè)比較簡(jiǎn)單,就不講了:
6.viewpage的界面復(fù)用問(wèn)題:
最后就是我沒(méi)問(wèn)在用的時(shí)候一直是再去創(chuàng)建view,每次都是new,發(fā)現(xiàn)我們的界面是可以回傳過(guò)來(lái)復(fù)用的:
用一個(gè)集合講viewpage的adapter中銷(xiāo)毀的時(shí)候destroyItem將view保存起來(lái):
/*
*? 界面復(fù)用
* */
private ViewgetConverViews() {
for (int i =0; i
if (mConvertViews.get(i).getParent() ==null) {
return mConvertViews.get(i);
? ? ? ? }
}
return null;
}
這個(gè)是保存view的:最后就是回傳回來(lái):
最后的用法:、
如下:
banner = ((BannerView) findViewById(R.id.banner_view));
banner.setAdapter(new BannerAdapter() {
@Override
? ? public ViewgetView(final int position, View contrtView) {
ImageView imageView =null;
? ? ? ? if (contrtView ==null) {
imageView =new ImageView(MainActivity.this);
? ? ? ? ? ? imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
? ? ? ? }else {
imageView = (ImageView) contrtView;
? ? ? ? }
? imageView.setImageResource(R.mipmap.banner2);
imageView.setOnClickListener(new View.OnClickListener() {
@Override
? ? ? ? ? ? public void onClick(View v) {
Toast.makeText(MainActivity.this, "點(diǎn)擊" +position, Toast.LENGTH_SHORT).show();
? ? ? ? ? ? }
});
? ? ? ? return imageView;
? ? }
@Override
? ? public int getContent() {
return arrrar.size();
? ? }
});
banner.setStartbanner();
最后,這個(gè)項(xiàng)目地址:https://github.com/raotongGitup/BannerViewpage
這個(gè)banner只是我這個(gè)架構(gòu)中的viewpage,所有的類都在banner保包中:用法在上面中,各位感覺(jué)我這寫(xiě)的不錯(cuò)的可以點(diǎn)下星
這個(gè)新增了viewpage2的banner實(shí)現(xiàn)方式地址:? https://github.com/raotongGitup/Banner