Android自定義輪播圖效果
本文實例為大家分享了Android自定義輪播圖效果的具體代碼,供大家參考,具體內(nèi)容如下
概述
1、寫一個布局,其中有ViewPager,TextView,LinearLayout.
- ViewPager:用來承載圖片
- TextView:用來展示文字描述
- LinearLayout:用來展示指示器
2、自定義ConstraintLayout, 在該控件中處理頁面切換邏輯等.
分析
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對象 */ @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(); // 切換到下一個圖片 mVp.setCurrentItem(currentItem + 1); // 間隔一定時間發(fā)送一個消息,間隔時長由自定義屬性值控制. mHandler.sendEmptyMessageDelayed(1, mInterval); } }; } /** * 為ViewPager設(shè)置滑動監(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個視圖 // position取模,轉(zhuǎn)換為mImageViewList對應(yīng)的索引. int realPosition = position % mImageViewList.size(); if (mDescList.size() == mImageViewList.size()) { // 文字描述集合與圖片集合長度相等,那么就為文字描述TextView展示對應(yīng)的文字內(nèi)容. String desc = mDescList.get(realPosition); mTvDesc.setText(desc); } else { if (BuildConfig.DEBUG) { Log.d(TAG, "文字集合和圖片集合長度不相等"); } } // 上一個頁面對應(yīng)的指示器設(shè)置為沒有選中 mLLPoint.getChildAt(prePosition).setEnabled(false); // 從裝有指示器的LinearLayout中獲得當(dāng)前視圖對應(yīng)的指示器,然后設(shè)置指示器當(dāng)前是選中,從而改變指示器顏色. mLLPoint.getChildAt(realPosition).setEnabled(true); prePosition = realPosition; } @Override public void onPageScrollStateChanged(int state) { if (state == ViewPager.SCROLL_STATE_DRAGGING) {//正在滑動 // 手動觸碰ViewPager,使之正在處于滑動狀態(tài),Handler就停止發(fā)送消息. isDragging = true; mHandler.removeCallbacksAndMessages(null); } if (state == ViewPager.SCROLL_STATE_IDLE && isDragging) {//空閑狀態(tài) // ViewPager手動滑動停止之后,重新開啟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)前視圖為中間位置, 因為ViewPager視圖個數(shù)為Integer.MAX_VALUE(在ViewPagerAdapter中設(shè)置的). int position = Integer.MAX_VALUE / 2 - Integer.MAX_VALUE / 2 % mImageViewList.size(); // 設(shè)置當(dāng)前ViewPager展示哪個視圖 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è)置點擊事件 setImageViewListener(imageView); // 將ImageView添加進(jìn)集合中 mImageViewList.add(imageView); //添加指示器 addPoint(i); } } /** * 根據(jù)參數(shù)創(chuàng)建ImageView對象 * * @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對象設(shè)置點擊事件和觸摸事件 * * @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)點擊ImageView時,通過getTage()獲取圖片當(dāng)前對應(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è)置了圖片資源還有點擊事件等. */ public BannerAdapter(ArrayList<ImageView> mImageViewList) { this.mImageViewList = mImageViewList; } @Override public int getCount() { // 設(shè)置ViewPager的視圖個數(shù),Integer.MAX_VALUE是一個非常大的數(shù)字, 不管輪詢多久都很難到盡頭. return Integer.MAX_VALUE; } @SuppressLint("ClickableViewAccessibility") @NonNull @Override public Object instantiateItem(@NonNull ViewGroup container, final int position) { // position這個數(shù)字很大, 取模之后就能夠?qū)?yīng)mImageViewList集合中的索引值了. final int realPosition = position % mImageViewList.size(); ImageView imageView = mImageViewList.get(realPosition); // 將索引值與ImageView綁定,當(dāng)被點擊的時候可以取出該索引值. 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) { } }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android模擬開關(guān)按鈕點擊打開動畫(屬性動畫之平移動畫)
這篇文章主要介紹了Android模擬開關(guān)按鈕點擊打開動畫(屬性動畫之平移動畫)的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-09-09Android仿網(wǎng)易一元奪寶客戶端下拉加載動畫效果(一)
本文通過一個demo給大家介紹了android仿網(wǎng)易一元奪寶客戶端下拉加載動畫效果,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-09-09Android應(yīng)用中炫酷的橫向和環(huán)形進(jìn)度條的實例分享
這篇文章主要介紹了Android應(yīng)用中炫酷的橫向和圓形進(jìn)度條的實例分享,文中利用了一些GitHub上的插件進(jìn)行改寫,也是一片很好的二次開發(fā)教學(xué),需要的朋友可以參考下2016-04-04Android實現(xiàn)數(shù)字跳動效果的TextView方法示例
數(shù)字跳動效果相信大家應(yīng)該都見過,在開發(fā)加上這種效果后會讓ui交互看起來非常不錯,所以下面這篇文章主要給大家介紹了Android實現(xiàn)數(shù)字跳動的TextView的相關(guān)資料,文中給出了詳細(xì)的示例代碼,需要的朋友可以參考學(xué)習(xí),下面來一起看看吧。2017-04-04Android自定義EditText實現(xiàn)淘寶登錄功能
這篇文章主要為大家詳細(xì)介紹了Android自定義EditText實現(xiàn)淘寶登錄功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-12-12Android實現(xiàn)收到新短信后自動發(fā)郵件功能
這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)收到新短信后自動發(fā)郵件功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-05-05