Android仿京東淘寶自動(dòng)無(wú)限循環(huán)輪播控件思路詳解
在App的開(kāi)發(fā)中,很多的時(shí)候都需要實(shí)現(xiàn)類(lèi)似京東淘寶一樣的自動(dòng)無(wú)限輪播的廣告欄,所以就自己寫(xiě)了一個(gè),下面是我自定義控件的思路和過(guò)程。
一、自定義控件屬性
新建自定義控件SliderLayout繼承于RelativeLayout,首先要考慮的就是自定義的控件需要擴(kuò)展那些屬性,把這些屬性列出來(lái)。在這里是要實(shí)現(xiàn)類(lèi)似于京東淘寶的無(wú)限輪播廣告欄,那么首先想到的就是輪播的時(shí)長(zhǎng)、輪播指示器的樣式等等。我在這里列舉了一些并且結(jié)合到了代碼中。
1、擴(kuò)展屬性
(1)是否開(kāi)啟自動(dòng)輪播的功能。
(2)指示器的圖形樣式,一般為圓形和方形兩種。
(3)指示器的位置,一般為底部或者頂部。
(4)指示器被選中和不被選中時(shí)的樣式:顏色、高度、寬度、間隔等。
(5)輪播的時(shí)長(zhǎng)。
(6)加載的如果是網(wǎng)絡(luò)圖片的話,需要默認(rèn)圖片和錯(cuò)誤圖片等。
2、在attrs.xml文件中添加這些擴(kuò)展的屬性。
<declare-styleable name="SliderLayout"> <attr name="sl_is_auto_play" format="boolean"/> <attr name="sl_indicator_shape" format="enum"> <enum name="oval" value="0" /> <enum name="rect" value="1" /> </attr> <attr name="sl_indicator_position" format="enum"> <enum name="centerBottom" value="0" /> <enum name="rightBottom" value="1" /> <enum name="leftBottom" value="2" /> <enum name="centerTop" value="3" /> <enum name="rightTop" value="4" /> <enum name="leftTop" value="5" /> </attr> <attr name="sl_selected_indicator_color" format="color|reference" /> <attr name="sl_unselected_indicator_color" format="color|reference" /> <attr name="sl_selected_indicator_height" format="dimension|reference" /> <attr name="sl_selected_indicator_width" format="dimension|reference" /> <attr name="sl_unselected_indicator_height" format="dimension|reference" /> <attr name="sl_unselected_indicator_width" format="dimension|reference" /> <attr name="sl_indicator_space" format="dimension|reference" /> <attr name="sl_indicator_margin" format="dimension|reference" /> <attr name="sl_auto_play_duration" format="integer|reference" /> <attr name="sl_default_image" format="reference"/> <attr name="sl_error_image" format="reference"/> </declare-styleable>
二、自定義輪播控件的初始化
1、獲取到擴(kuò)展屬性的值
在自定義SliderLayout中獲取到擴(kuò)展的樣式,然后根據(jù)樣式獲取相應(yīng)的屬性值,最好是要先設(shè)置好默認(rèn)值。
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.SliderLayout, defStyleAttr, 0); if (array != null) { isAutoPlay = array.getBoolean(R.styleable.SliderLayout_sl_is_auto_play, isAutoPlay); //get the shape of indicator int intShape = array.getInt(R.styleable.SliderLayout_sl_indicator_shape, indicatorShape.ordinal()); for (IndicatorShape shape : IndicatorShape.values()) { if (shape.ordinal() == intShape) { indicatorShape = shape; break; } } //get the position of indicator int intPosition = array.getInt(R.styleable.SliderLayout_sl_indicator_position, IndicatorPosition.centerBottom.ordinal()); for (IndicatorPosition position : IndicatorPosition.values()) { if (position.ordinal() == intPosition) { indicatorPosition = position; break; } } unSelectedIndicatorColor = array.getColor(R.styleable.SliderLayout_sl_unselected_indicator_color, unSelectedIndicatorColor); selectedIndicatorColor = array.getColor(R.styleable.SliderLayout_sl_selected_indicator_color, selectedIndicatorColor); unSelectedIndicatorHeight = array.getDimension(R.styleable.SliderLayout_sl_unselected_indicator_height, unSelectedIndicatorHeight); unSelectedIndicatorWidth = array.getDimension(R.styleable.SliderLayout_sl_unselected_indicator_width, unSelectedIndicatorWidth); selectedIndicatorHeight = array.getDimension(R.styleable.SliderLayout_sl_selected_indicator_height, selectedIndicatorHeight); selectedIndicatorWidth = array.getDimension(R.styleable.SliderLayout_sl_selected_indicator_width, selectedIndicatorWidth); indicatorSpace = array.getDimension(R.styleable.SliderLayout_sl_indicator_space, indicatorSpace); indicatorMargin = array.getDimension(R.styleable.SliderLayout_sl_indicator_margin, indicatorMargin); autoPlayDuration = array.getInt(R.styleable.SliderLayout_sl_auto_play_duration, autoPlayDuration); defaultImage = array.getResourceId(R.styleable.SliderLayout_sl_default_image, defaultImage); errorImage = array.getResourceId(R.styleable.SliderLayout_sl_error_image, errorImage); }
2、初始化控件
根據(jù)這里所需要實(shí)現(xiàn)的功能,首先需要一個(gè)圖像切換器ImageSwticher,還要指示器,這里就用ImageView了。
switcherImage = new ImageSwitcher(context); switcherImage.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); for (int i = 0; i < itemCount; i++) { ImageView indicator = new ImageView(context); indicator.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); indicator.setPadding((int) (indicatorSpace), (int) (indicatorSpace), (int) (indicatorSpace), (int) (indicatorSpace)); indicator.setImageDrawable(unSelectedDrawable); indicatorContainer.addView(indicator); final int finalI = i; indicator.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { stopAutoPlay(); switchIndicator(finalI); pictureIndex = finalI; handler.sendEmptyMessageDelayed(START_AUTO_PLAY,autoPlayDuration); } }); }
3、初始化選中第一張圖片
專(zhuān)門(mén)寫(xiě)一個(gè)針對(duì)指示器切換的函數(shù),然后在初始化的時(shí)候直接調(diào)用,選中第一個(gè)指示器,就是選中第一張圖片了。
函數(shù)代碼如下。
private void switchIndicator(int index) { for (int i = 0; i < indicatorContainer.getChildCount(); i++) { ((ImageView) indicatorContainer.getChildAt(i)).setImageDrawable(i == index ? selectedDrawable : unSelectedDrawable); } loadImage(index); }
調(diào)用選中第一張圖。
switchIndicator(0);
三、圖片的加載
1、網(wǎng)路圖片的加載
在這里使用Picasso框架來(lái)加載圖片,根據(jù)url來(lái)加載顯示圖片,同時(shí)也要顯示圖片的加載進(jìn)度,這里就需要一個(gè)Dialog提示框了,Dialog的樣式最好是可以自定義的。
private void loadNetImage(int pictureIndex) { if (list != null && list.size() != 0) { Picasso.with(context) .load((String) list.get(pictureIndex)) .placeholder(defaultImage) .error(errorImage) .tag(context) .into(mTarget); } }
下面是圖片的加載提示過(guò)程。
private Target mTarget = new Target() { @Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) { dismissDialog(); ((ImageView) switcherImage.getCurrentView()).setScaleType(ImageView.ScaleType.CENTER_CROP); ((ImageView) switcherImage.getCurrentView()).setLayoutParams(new ImageSwitcher.LayoutParams(ImageSwitcher.LayoutParams.MATCH_PARENT, ImageSwitcher.LayoutParams.MATCH_PARENT)); ((ImageView) switcherImage.getCurrentView()).setImageBitmap(bitmap); } @Override public void onBitmapFailed(Drawable errorDrawable) { dismissDialog(); ((ImageView) switcherImage.getCurrentView()).setImageDrawable(errorDrawable); } @Override public void onPrepareLoad(Drawable placeHolderDrawable) { showDialog(); } };
2、資源圖片的加載
只能加載網(wǎng)絡(luò)圖片是不夠的呢,還需要可以加載資源圖片,加載資源圖片的辦法就更加簡(jiǎn)單了。
private void loadFileImage(int pictureIndex) { if (list != null && list.size() != 0) { switcherImage.setImageResource((Integer) list.get(pictureIndex)); } }
四、設(shè)置圖片切換的動(dòng)畫(huà)
設(shè)置圖片從左往右以及從右往左的動(dòng)畫(huà)效果,并且當(dāng)滑動(dòng)到該圖片時(shí),指示器也要一起變化,這里就簡(jiǎn)單說(shuō)下從左往右的動(dòng)畫(huà)了。
private void SliderLeftToRight() { // get current index pictureIndex = pictureIndex == 0 ? itemCount - 1 : pictureIndex - 1; // set Animation switcherImage.setInAnimation(AnimationUtils.loadAnimation(context, android.R.anim.slide_in_left)); switcherImage.setOutAnimation(AnimationUtils.loadAnimation(context, android.R.anim.slide_out_right)); switchIndicator(pictureIndex); }
從右往左滑動(dòng)時(shí)的代碼和這個(gè)是一樣的,就是換了下方向,需要自己定義下。
五、定義圖片的點(diǎn)擊事件
1、定義interface來(lái)監(jiān)聽(tīng)事件
在自定義控件中自定義一個(gè)interface來(lái)監(jiān)聽(tīng)事件就可以了。
public interface IOnClickListener { void onItemClick(View view, int position); }
2、在onTouch中調(diào)用點(diǎn)擊事件。
這里需要說(shuō)明下為什么在onTouch中處理,因?yàn)閛nTouch是觸摸事件,在滑動(dòng)的過(guò)程中,用戶是觸摸了屏幕的,所以根據(jù)用戶觸摸屏幕時(shí)點(diǎn)擊下的X坐標(biāo)和點(diǎn)擊起來(lái)時(shí)的X坐標(biāo)的對(duì)比來(lái)判斷是左滑還是右滑了,這樣的話,就會(huì)和onClick事件相沖了,所以就想到了一個(gè)辦法,那就是在范圍內(nèi)的話,就默認(rèn)為點(diǎn)擊事件,范圍外就是滑動(dòng)事件了。
if (0==(Math.abs(touchUpX - touchDownX))||(Math.abs(touchUpX - touchDownX))<50) { if (listener != null) { stopAutoPlay(); listener.onItemClick(view, pictureIndex); handler.sendEmptyMessageDelayed(START_AUTO_PLAY,autoPlayDuration); } }
六、效果圖
說(shuō)到了這里,應(yīng)該有所思路了吧,現(xiàn)在就來(lái)看下效果吧。
源代碼目前已經(jīng)開(kāi)放了,放在Github上面,歡迎指導(dǎo)建議。http://www.github.com/LT5505/SliderLayout
以上所述是小編給大家介紹的Android仿京東淘寶自動(dòng)無(wú)限循環(huán)輪播控件思路詳解,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- Android ViewPager實(shí)現(xiàn)無(wú)限循環(huán)輪播廣告位Banner效果
- Android ViewPager循環(huán)播放廣告實(shí)例詳解
- Android實(shí)現(xiàn)Banner界面廣告圖片循環(huán)輪播(包括實(shí)現(xiàn)手動(dòng)滑動(dòng)循環(huán))
- Android 使用 ViewPager循環(huán)廣告位的實(shí)現(xiàn)
- Android 使用viewpager實(shí)現(xiàn)無(wú)限循環(huán)(定時(shí)+手動(dòng))
- Android viewpager中動(dòng)態(tài)添加view并實(shí)現(xiàn)偽無(wú)限循環(huán)的方法
- Android ViewPager實(shí)現(xiàn)無(wú)限循環(huán)效果
- Android實(shí)現(xiàn)輪播圖無(wú)限循環(huán)效果
- Android ViewPager實(shí)現(xiàn)智能無(wú)限循環(huán)滾動(dòng)回繞效果
- Android開(kāi)發(fā)實(shí)現(xiàn)廣告無(wú)限循環(huán)功能示例
相關(guān)文章
Android自定義viewgroup快速滑動(dòng)(4)
這篇文章主要為大家詳細(xì)介紹了Android自定義viewgroup快速滑動(dòng)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12Android從觸碰屏幕開(kāi)始的事件采集解析及分發(fā)
這篇文章主要為大家介紹了Android從觸碰屏幕開(kāi)始的事件采集解析及分發(fā),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06Android開(kāi)發(fā)之使用SQLite存儲(chǔ)數(shù)據(jù)的方法分析
這篇文章主要介紹了Android開(kāi)發(fā)之使用SQLite存儲(chǔ)數(shù)據(jù)的方法,結(jié)合實(shí)例形式分析了Android使用SQLite數(shù)據(jù)庫(kù)實(shí)現(xiàn)針對(duì)數(shù)據(jù)的增刪改查操作相關(guān)技巧,需要的朋友可以參考下2017-07-07Android 簡(jiǎn)易手勢(shì)密碼開(kāi)源庫(kù)詳解
本文主要介紹Android 簡(jiǎn)易手勢(shì)密碼,這里主要介紹手勢(shì)密碼如何實(shí)現(xiàn)及簡(jiǎn)單的示例代碼,有需要的同學(xué)可以參考下2016-08-08Android多國(guó)語(yǔ)言轉(zhuǎn)換Excel及Excel轉(zhuǎn)換為string詳解
這篇文章主要給大家介紹了關(guān)于Android多國(guó)語(yǔ)言轉(zhuǎn)換Excel以及Excel轉(zhuǎn)換為string的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧2019-01-01Android UI控件之ProgressBar進(jìn)度條
這篇文章主要為大家詳細(xì)介紹了Android UI控件之ProgressBar進(jìn)度條的實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12Android UI開(kāi)發(fā) View自繪控件 分享
Android UI開(kāi)發(fā) View自繪控件 分享,需要的朋友可以參考一下2013-05-05Android開(kāi)發(fā)實(shí)現(xiàn)切換主題及換膚功能示例
這篇文章主要介紹了Android開(kāi)發(fā)實(shí)現(xiàn)切換主題及換膚功能,涉及Android界面布局與樣式動(dòng)態(tài)操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2019-03-03Android使用vcard文件的方法簡(jiǎn)單實(shí)例
這篇文章主要介紹了Android使用vcard文件的方法,結(jié)合實(shí)例形式分析了Android針對(duì)vcard文件的打開(kāi)、讀取、寫(xiě)入等相關(guān)操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06