Android仿京東淘寶自動(dòng)無限循環(huán)輪播控件思路詳解
在App的開發(fā)中,很多的時(shí)候都需要實(shí)現(xiàn)類似京東淘寶一樣的自動(dòng)無限輪播的廣告欄,所以就自己寫了一個(gè),下面是我自定義控件的思路和過程。
一、自定義控件屬性
新建自定義控件SliderLayout繼承于RelativeLayout,首先要考慮的就是自定義的控件需要擴(kuò)展那些屬性,把這些屬性列出來。在這里是要實(shí)現(xiàn)類似于京東淘寶的無限輪播廣告欄,那么首先想到的就是輪播的時(shí)長(zhǎng)、輪播指示器的樣式等等。我在這里列舉了一些并且結(jié)合到了代碼中。
1、擴(kuò)展屬性
(1)是否開啟自動(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、初始化選中第一張圖片
專門寫一個(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框架來加載圖片,根據(jù)url來加載顯示圖片,同時(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);
}
}
下面是圖片的加載提示過程。
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)畫
設(shè)置圖片從左往右以及從右往左的動(dòng)畫效果,并且當(dāng)滑動(dòng)到該圖片時(shí),指示器也要一起變化,這里就簡(jiǎn)單說下從左往右的動(dòng)畫了。
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來監(jiān)聽事件
在自定義控件中自定義一個(gè)interface來監(jiān)聽事件就可以了。
public interface IOnClickListener {
void onItemClick(View view, int position);
}
2、在onTouch中調(diào)用點(diǎn)擊事件。
這里需要說明下為什么在onTouch中處理,因?yàn)閛nTouch是觸摸事件,在滑動(dòng)的過程中,用戶是觸摸了屏幕的,所以根據(jù)用戶觸摸屏幕時(shí)點(diǎn)擊下的X坐標(biāo)和點(diǎn)擊起來時(shí)的X坐標(biāo)的對(duì)比來判斷是左滑還是右滑了,這樣的話,就會(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);
}
}
六、效果圖
說到了這里,應(yīng)該有所思路了吧,現(xiàn)在就來看下效果吧。

源代碼目前已經(jīng)開放了,放在Github上面,歡迎指導(dǎo)建議。http://www.github.com/LT5505/SliderLayout
以上所述是小編給大家介紹的Android仿京東淘寶自動(dòng)無限循環(huán)輪播控件思路詳解,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- Android ViewPager實(shí)現(xiàn)無限循環(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)無限循環(huán)(定時(shí)+手動(dòng))
- Android viewpager中動(dòng)態(tài)添加view并實(shí)現(xiàn)偽無限循環(huán)的方法
- Android ViewPager實(shí)現(xiàn)無限循環(huán)效果
- Android實(shí)現(xiàn)輪播圖無限循環(huán)效果
- Android ViewPager實(shí)現(xiàn)智能無限循環(huán)滾動(dòng)回繞效果
- Android開發(fā)實(shí)現(xiàn)廣告無限循環(huán)功能示例
相關(guān)文章
Android?Flutter在點(diǎn)擊事件上添加動(dòng)畫效果實(shí)現(xiàn)全過程
這篇文章主要給大家介紹了關(guān)于Android?Flutter在點(diǎn)擊事件上添加動(dòng)畫效果實(shí)現(xiàn)的相關(guān)資料,通過實(shí)例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)Android具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-03-03
360瀏覽器文本框獲得焦點(diǎn)后被android軟鍵盤遮罩該怎么辦
最近接了個(gè)項(xiàng)目,項(xiàng)目需求是這樣的,站點(diǎn)上篩選按鈕點(diǎn)擊后彈出層(fixed),當(dāng)輸入框獲取焦點(diǎn)以后彈出系統(tǒng)自帶的軟鍵盤,在android上十款瀏覽器挨個(gè)測(cè)試比對(duì),發(fā)現(xiàn)在360瀏覽器彈出鍵盤以后獲取焦點(diǎn)的文本框被軟鍵盤覆蓋了,下面分享我的解決辦法2015-12-12
Android 使用VideoView播放MP4的簡(jiǎn)單實(shí)現(xiàn)
這篇文章主要介紹了Android 使用VideoView播放MP4的簡(jiǎn)單實(shí)現(xiàn),實(shí)現(xiàn)簡(jiǎn)單的播放功能,播放手機(jī)本地的MP4文件,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-05-05
Android Activity Results API代替onActivityResul
說到onActivityResult,我們已經(jīng)非常熟悉來,通過在A activity啟動(dòng)B activity并且傳入數(shù)據(jù)到B中,然后在A中通過onActivityResult來接收B中返回的數(shù)據(jù)。在最新的activity-ktx的beta版本中,谷歌已經(jīng)廢棄了onActivityResult2022-09-09
Android畢業(yè)設(shè)計(jì)備忘錄APP
這篇文章主要介紹了一個(gè)Android畢業(yè)設(shè)計(jì)備忘錄APP,它很小,但是功能很全,可實(shí)現(xiàn)添加、刪除、修改、查看的功能,使用Java語言開發(fā),風(fēng)格簡(jiǎn)練2021-08-08
Android引用開源框架通過AsyncHttpClient實(shí)現(xiàn)文件上傳
這篇文章主要介紹了Android引用開源框架通過AsyncHttpClient實(shí)現(xiàn)文件上傳,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01
Android中判斷網(wǎng)絡(luò)連接是否可用的方法總結(jié)
這篇文章主要介紹了Android中判斷網(wǎng)絡(luò)連接是否可用的方法總結(jié)的相關(guān)資料,需要的朋友可以參考下2017-04-04

