Android中viewpage實(shí)現(xiàn)輪播圖

安卓中今天來(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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容