Android自定義輪播圖效果
本文實(shí)例為大家分享了Android自定義輪播圖效果的具體代碼,供大家參考,具體內(nèi)容如下
概述
1、寫一個(gè)布局,其中有ViewPager,TextView,LinearLayout.
- ViewPager:用來(lái)承載圖片
- TextView:用來(lái)展示文字描述
- LinearLayout:用來(lái)展示指示器
2、自定義ConstraintLayout, 在該控件中處理頁(yè)面切換邏輯等.
分析
1、獲取自定義屬性以及設(shè)置一些屬性
public BannerY(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
initXmlParams(context, attrs, defStyleAttr);
fixParams();
initListener();
initLists();
initImageLoader();
}
/**
* 初始化ImageLoader
*/
private void initImageLoader() {
ImageLoader.getInstance().init(ImageLoaderConfiguration.createDefault(mContext));
}
/**
* 將布局填充進(jìn)BannerY,獲取VP,TextView,LinearLayout控件
*
* @param context
*/
private void initView(Context context) {
mContext = context;
LayoutInflater.from(context).inflate(R.layout.layout_banner, this);
mVp = (ViewPager) findViewById(R.id.vp);
mTvDesc = (TextView) findViewById(R.id.tv_desc);
mLLPoint = (LinearLayout) findViewById(R.id.ll_point);
}
/**
* 獲取自定義屬性
*
* @param context
* @param attrs
* @param defStyleAttr
*/
private void initXmlParams(Context context, AttributeSet attrs, int defStyleAttr) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BannerY, defStyleAttr, 0);
mPointSize = typedArray.getDimensionPixelSize(R.styleable.BannerY_point_size, 8);
mPointBG = typedArray.getResourceId(R.styleable.BannerY_point_bg, R.drawable.point_selector);
mInterval = typedArray.getInteger(R.styleable.BannerY_banner_interval, 2000);
mTvBottomMargin = typedArray.getDimensionPixelSize(R.styleable.BannerY_desc_bottom_margin, 8);
mPointBottomMargin = typedArray.getDimensionPixelSize(R.styleable.BannerY_point_bottom_margin, 8);
mDescColor = typedArray.getColor(R.styleable.BannerY_desc_color, Color.BLACK);
mDescSize = typedArray.getDimensionPixelSize(R.styleable.BannerY_desc_size, 14);
mScaleType = typedArray.getInt(R.styleable.BannerY_banner_scaletype, -1);
typedArray.recycle();
}
/**
* 通過自定義屬性調(diào)整指示器與文字描述位置
*/
private void fixParams() {
//描述控件
LayoutParams mTvDescLayoutParams = (LayoutParams) mTvDesc.getLayoutParams();
mTvDescLayoutParams.bottomMargin = (int) mTvBottomMargin;
mTvDesc.setLayoutParams(mTvDescLayoutParams);
mTvDesc.setTextColor(mDescColor);
mTvDesc.getPaint().setTextSize(mDescSize);
//指示器
LayoutParams mLLPointLayoutParams = (LayoutParams) mLLPoint.getLayoutParams();
mLLPointLayoutParams.bottomMargin = (int) mPointBottomMargin;
mLLPoint.setLayoutParams(mLLPointLayoutParams);
}
/**
* 創(chuàng)建數(shù)據(jù)源集合以及創(chuàng)建Handler對(duì)象
*/
@SuppressLint("HandlerLeak")
private void initLists() {
mImageViewList = new ArrayList<>();
mDescList = new ArrayList<>();
mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
// 獲取ViewPager當(dāng)前展示圖片的索引值
int currentItem = mVp.getCurrentItem();
// 切換到下一個(gè)圖片
mVp.setCurrentItem(currentItem + 1);
// 間隔一定時(shí)間發(fā)送一個(gè)消息,間隔時(shí)長(zhǎng)由自定義屬性值控制.
mHandler.sendEmptyMessageDelayed(1, mInterval);
}
};
}
/**
* 為ViewPager設(shè)置滑動(dòng)監(jiān)聽
*/
private void initListener() {
mVp.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
// ViewPager總共設(shè)置有Integer.MAX_VALUE個(gè)視圖
// position取模,轉(zhuǎn)換為mImageViewList對(duì)應(yīng)的索引.
int realPosition = position % mImageViewList.size();
if (mDescList.size() == mImageViewList.size()) {
// 文字描述集合與圖片集合長(zhǎng)度相等,那么就為文字描述TextView展示對(duì)應(yīng)的文字內(nèi)容.
String desc = mDescList.get(realPosition);
mTvDesc.setText(desc);
} else {
if (BuildConfig.DEBUG) {
Log.d(TAG, "文字集合和圖片集合長(zhǎng)度不相等");
}
}
// 上一個(gè)頁(yè)面對(duì)應(yīng)的指示器設(shè)置為沒有選中
mLLPoint.getChildAt(prePosition).setEnabled(false);
// 從裝有指示器的LinearLayout中獲得當(dāng)前視圖對(duì)應(yīng)的指示器,然后設(shè)置指示器當(dāng)前是選中,從而改變指示器顏色.
mLLPoint.getChildAt(realPosition).setEnabled(true);
prePosition = realPosition;
}
@Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_DRAGGING) {//正在滑動(dòng)
// 手動(dòng)觸碰ViewPager,使之正在處于滑動(dòng)狀態(tài),Handler就停止發(fā)送消息.
isDragging = true;
mHandler.removeCallbacksAndMessages(null);
}
if (state == ViewPager.SCROLL_STATE_IDLE && isDragging) {//空閑狀態(tài)
// ViewPager手動(dòng)滑動(dòng)停止之后,重新開啟Handler發(fā)送消息.
mHandler.removeCallbacksAndMessages(null);
mHandler.sendEmptyMessageDelayed(1, mInterval);
}
}
});
}
2、設(shè)置圖片源集合
/**
* 設(shè)置圖片源
* @param imagesRes
* @param <T>
*/
public <T> void setImagesRes(ArrayList<T> imagesRes) {
if (judgeLenght(imagesRes)) {
mImageViewList.clear();
// 初始化圖片列表
initImageList(imagesRes);
// 創(chuàng)建Adapter
mBannerAdapter = new BannerAdapter(mImageViewList);
mVp.setAdapter(mBannerAdapter);
// 設(shè)置ViewPager當(dāng)前視圖為中間位置, 因?yàn)閂iewPager視圖個(gè)數(shù)為Integer.MAX_VALUE(在ViewPagerAdapter中設(shè)置的).
int position = Integer.MAX_VALUE / 2 - Integer.MAX_VALUE / 2 % mImageViewList.size();
// 設(shè)置當(dāng)前ViewPager展示哪個(gè)視圖
mVp.setCurrentItem(position);
// 開啟消息循環(huán)
mHandler.sendEmptyMessageDelayed(1, mInterval);
if (mDescList.size() == mImageViewList.size()) {
// 設(shè)置文字描述展示
mTvDesc.setText(mDescList.get(prePosition));
}
}
}
/**
* 初始化圖片列表
*/
private void initImageList(ArrayList imagesRes) {
Class<?> imageResClass = imagesRes.get(0).getClass();
for (int i = 0; i < imagesRes.size(); i++) {
// 創(chuàng)建ImageView
ImageView imageView = createImageView(imagesRes, i, imageResClass);
// 為ImageView設(shè)置點(diǎn)擊事件
setImageViewListener(imageView);
// 將ImageView添加進(jìn)集合中
mImageViewList.add(imageView);
//添加指示器
addPoint(i);
}
}
/**
* 根據(jù)參數(shù)創(chuàng)建ImageView對(duì)象
*
* @param imagesRes
* @param i
* @param imageResClass
* @return
*/
private ImageView createImageView(ArrayList imagesRes, int i, Class<?> imageResClass) {
ImageView imageView = new ImageView(mContext);
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
imageView.setLayoutParams(layoutParams);
ImageView.ScaleType scaleType = sScaleTypeArray[mScaleType];
imageView.setScaleType(scaleType);
if (imageResClass.equals(String.class)) {
// 假如圖片數(shù)據(jù)源集合是url,網(wǎng)址圖片
String url = (String) imagesRes.get(i);
// 使用ImageLoader將圖片展示到ImageView中
ImageLoader.getInstance().displayImage(url, imageView);
} else if (imageResClass.equals(Integer.class)) {
// 假如圖片數(shù)據(jù)源集合是圖片資源ID
Integer resId = (Integer) imagesRes.get(i);
imageView.setImageResource(resId);
}
return imageView;
}
/**
* 為ImageView對(duì)象設(shè)置點(diǎn)擊事件和觸摸事件
*
* @param imageView
*/
@SuppressLint("ClickableViewAccessibility")
private void setImageViewListener(ImageView imageView) {
imageView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 當(dāng)手指在ImageView下按下,那么停止handler發(fā)送切換圖片的消息
mHandler.removeCallbacksAndMessages(null);
break;
case MotionEvent.ACTION_UP:
// 當(dāng)手指抬起,正常發(fā)送切換圖片消息.
mHandler.removeCallbacksAndMessages(null);
mHandler.sendEmptyMessageDelayed(1, mInterval);
break;
}
return false;
}
});
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mIClickBanner != null) {
// 當(dāng)點(diǎn)擊ImageView時(shí),通過getTage()獲取圖片當(dāng)前對(duì)應(yīng)的視圖索引值.
// 該值是在ViewPagerAdapter中的instantiateItem()中設(shè)置的.
int positon = (int) v.getTag();
int i = positon % mImageViewList.size();
mIClickBanner.click(i);
} else {
if (BuildConfig.DEBUG) {
Log.e(TAG, "圖片回調(diào)方法為不存在");
}
}
}
});
}
3、BannerY的Adapter
public class BannerAdapter<T> extends PagerAdapter {
private final static String TAG = BannerAdapter.class.getName();
ArrayList<ImageView> mImageViewList;
/**
* @param mImageViewList ImageView 控件列表,該列表中中的IamgeView都設(shè)置了圖片資源還有點(diǎn)擊事件等.
*/
public BannerAdapter(ArrayList<ImageView> mImageViewList) {
this.mImageViewList = mImageViewList;
}
@Override
public int getCount() {
// 設(shè)置ViewPager的視圖個(gè)數(shù),Integer.MAX_VALUE是一個(gè)非常大的數(shù)字, 不管輪詢多久都很難到盡頭.
return Integer.MAX_VALUE;
}
@SuppressLint("ClickableViewAccessibility")
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, final int position) {
// position這個(gè)數(shù)字很大, 取模之后就能夠?qū)?yīng)mImageViewList集合中的索引值了.
final int realPosition = position % mImageViewList.size();
ImageView imageView = mImageViewList.get(realPosition);
// 將索引值與ImageView綁定,當(dāng)被點(diǎn)擊的時(shí)候可以取出該索引值.
imageView.setTag(position);
ViewParent viewParent = imageView.getParent();
if (viewParent != null) {
// 這里是防止ViewPager重復(fù)添加圖片.
((ViewGroup) viewParent).removeView(imageView);
}
// 將圖片添加進(jìn)ViewPager中
container.addView(imageView);
return imageView;
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android模擬開關(guān)按鈕點(diǎn)擊打開動(dòng)畫(屬性動(dòng)畫之平移動(dòng)畫)
這篇文章主要介紹了Android模擬開關(guān)按鈕點(diǎn)擊打開動(dòng)畫(屬性動(dòng)畫之平移動(dòng)畫)的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09
Android仿網(wǎng)易一元奪寶客戶端下拉加載動(dòng)畫效果(一)
本文通過一個(gè)demo給大家介紹了android仿網(wǎng)易一元奪寶客戶端下拉加載動(dòng)畫效果,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09
Android應(yīng)用中炫酷的橫向和環(huán)形進(jìn)度條的實(shí)例分享
這篇文章主要介紹了Android應(yīng)用中炫酷的橫向和圓形進(jìn)度條的實(shí)例分享,文中利用了一些GitHub上的插件進(jìn)行改寫,也是一片很好的二次開發(fā)教學(xué),需要的朋友可以參考下2016-04-04
Android實(shí)現(xiàn)數(shù)字跳動(dòng)效果的TextView方法示例
數(shù)字跳動(dòng)效果相信大家應(yīng)該都見過,在開發(fā)加上這種效果后會(huì)讓ui交互看起來(lái)非常不錯(cuò),所以下面這篇文章主要給大家介紹了Android實(shí)現(xiàn)數(shù)字跳動(dòng)的TextView的相關(guān)資料,文中給出了詳細(xì)的示例代碼,需要的朋友可以參考學(xué)習(xí),下面來(lái)一起看看吧。2017-04-04
Android自定義EditText實(shí)現(xiàn)淘寶登錄功能
這篇文章主要為大家詳細(xì)介紹了Android自定義EditText實(shí)現(xiàn)淘寶登錄功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12
Android實(shí)現(xiàn)收到新短信后自動(dòng)發(fā)郵件功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)收到新短信后自動(dòng)發(fā)郵件功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05

