Android封裝Banner控件方法介紹
如上圖所示效果我們應(yīng)該都不陌生,這是一個(gè)簡(jiǎn)單的banner輪播效果,網(wǎng)上也有很多的開源項(xiàng)目,但有時(shí)候可能我們僅僅只需要一些簡(jiǎn)單的效果,并不需要其他過(guò)多的東西。這里簡(jiǎn)單的對(duì)banner進(jìn)行一下封裝,隨時(shí)調(diào)用和添加一些新的功能。
代碼展示
/** * Created by xiaolong on 2018/1/23. */ public class BannerView extends FrameLayout implements ViewPager.OnPageChangeListener{ private ViewPager viewPager; //網(wǎng)絡(luò)圖片地址 private List<String> imageUrls; //指示點(diǎn)的容器 private LinearLayout pointLayout; //當(dāng)前頁(yè)面位置 private int currentItem; //自動(dòng)播放時(shí)間 private int autoPlayTime = 2000; //是否自動(dòng)播放 private boolean isAutoPlay; //是否是一張圖片 private boolean isOneImage; //監(jiān)聽(tīng)事件 private OnBannerItemClick onBannerItemClick; //這里利用handler實(shí)現(xiàn)循環(huán)播放 private Handler handler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { currentItem++; currentItem = currentItem % (imageUrls.size() + 2); viewPager.setCurrentItem(currentItem); handler.sendEmptyMessageDelayed(0,autoPlayTime); return false; } }); public BannerView(@NonNull Context context) { this(context,null); } public BannerView(@NonNull Context context, @Nullable AttributeSet attrs) { this(context, attrs,0); } public BannerView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs,R.styleable.BannerView,0,0); //默認(rèn)自動(dòng)播放 isAutoPlay = typedArray.getBoolean(R.styleable.BannerView_isAutoPlay,true); typedArray.recycle(); viewPager = new ViewPager(getContext()); pointLayout = new LinearLayout(getContext()); //添加監(jiān)聽(tīng)事件 viewPager.addOnPageChangeListener(this); //利用布局屬性將指示器容器放置底部并居中 FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); params.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL; params.bottomMargin = 60; addView(viewPager); addView(pointLayout,params); } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { currentItem = position; if (!isOneImage) { switchToPoint(toRealPosition(position)); } } @Override public void onPageScrollStateChanged(int state) { //根據(jù)滑動(dòng)松開后的狀態(tài),去判斷當(dāng)前的current 并跳轉(zhuǎn)到指定current if (state == ViewPager.SCROLL_STATE_IDLE) { int current = viewPager.getCurrentItem(); int lastReal = viewPager.getAdapter().getCount() - 2; if (current == 0) { viewPager.setCurrentItem(lastReal, false); } else if (current == lastReal + 1) { viewPager.setCurrentItem(1, false); } } } //配置viewpager適配器 private class BannerAdapter extends PagerAdapter { @Override public int getCount() { return imageUrls.size() + 2; } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public Object instantiateItem(ViewGroup container, final int position) { ImageView imageView = new ImageView(getContext()); imageView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (onBannerItemClick != null) { onBannerItemClick.onItemClick(toRealPosition(position)); } } }); imageView.setScaleType(ImageView.ScaleType.FIT_XY); Glide.with(getContext()).load(imageUrls.get(toRealPosition(position))).into(imageView); container.addView(imageView); return imageView; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } } //添加網(wǎng)絡(luò)圖片 public void setImageUrls(List<String> imageUrls) { this.imageUrls = imageUrls; if (imageUrls.size() <= 1) { isOneImage = true; }else { isOneImage = false; } initViewPager(); } //加載viewPager private void initViewPager() { if (!isOneImage) { //添加指示點(diǎn) addPoints(); } BannerAdapter adapter = new BannerAdapter(); viewPager.setAdapter(adapter); //默認(rèn)當(dāng)前圖片 viewPager.setCurrentItem(1); //判斷是否自動(dòng)播放和是否是一張圖片的情況 if (isAutoPlay && !isOneImage) { handler.sendEmptyMessageDelayed(0,autoPlayTime); } } //添加指示點(diǎn) private void addPoints() { LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); lp.setMargins(10, 10, 10, 10); ImageView imageView; int length = imageUrls.size(); for (int i = 0; i < length; i++) { imageView = new ImageView(getContext()); imageView.setLayoutParams(lp); imageView.setImageResource(R.drawable.select_point_bg); pointLayout.addView(imageView); } switchToPoint(0); } //切換指示器 private void switchToPoint(int currentPoint) { for (int i = 0; i < pointLayout.getChildCount(); i++) { pointLayout.getChildAt(i).setEnabled(false); } pointLayout.getChildAt(currentPoint).setEnabled(true); } //返回真實(shí)的位置 private int toRealPosition(int position) { int realPosition; if (imageUrls.size() > 0) { realPosition = (position - 1) % imageUrls.size(); if (realPosition < 0) realPosition += imageUrls.size(); }else{ realPosition = 0; } return realPosition; } public void setAutoPlay(boolean autoPlay) { isAutoPlay = autoPlay; } public void setOnBannerItemClick(OnBannerItemClick onBannerItemClick) { this.onBannerItemClick = onBannerItemClick; } //添加監(jiān)聽(tīng)事件回調(diào) public interface OnBannerItemClick{ void onItemClick(int position); } }
調(diào)用方式
//設(shè)置是否自動(dòng)播放 bannerView.setAutoPlay(true); //添加網(wǎng)絡(luò)圖片 bannerView.setImageUrls(data); //banner的點(diǎn)擊事件 bannerView.setOnBannerItemClick(new BannerView.OnBannerItemClick() { @Override public void onItemClick(int position) { Toast.makeText(MainActivity.this,"圖片" + position,Toast.LENGTH_LONG).show(); } });
代碼分析
這里我只考慮了使用網(wǎng)絡(luò)圖片進(jìn)行展示,使用本地圖片原理是一樣的,在里面多加個(gè)方法即可。此效果代碼不是很復(fù)雜,通俗易懂。唯一值得一說(shuō)的是我在實(shí)現(xiàn)viewpager
無(wú)限滑動(dòng)時(shí)采用的是return imageUrls.size() + 2
的方法。這里我們添加兩條數(shù)據(jù)分別為第一條和最后一條。第一條代表著最后一張圖片而最后一條則代表著第一張圖片,這里手動(dòng)畫個(gè)圖:
通過(guò)此圖我們應(yīng)該不難發(fā)現(xiàn),當(dāng)我們滑動(dòng)到第二個(gè)0的時(shí)候則跳轉(zhuǎn)到第一個(gè)0,滑動(dòng)到第一個(gè)2的時(shí)候則跳轉(zhuǎn)到第二個(gè)2。這里0代表第一張圖片,2代表第二張圖片。這樣就可以實(shí)現(xiàn)無(wú)限滑動(dòng)的效果了,可能有些人會(huì)覺(jué)得這樣做有些復(fù)雜還要判斷真實(shí)的位置不如直接將getConut()
返回一個(gè)最大值然后取其中間值即可。但這樣做其實(shí)代碼性能并不是很高。
結(jié)束
這樣一個(gè)常用的banner就寫好了,當(dāng)我們需要實(shí)現(xiàn)一些滑動(dòng)動(dòng)畫的時(shí)候,可以在里面實(shí)現(xiàn)viewpager
的動(dòng)畫屬性即可。先從簡(jiǎn)單的入手,慢慢的就可以了解更多的原理和知識(shí)點(diǎn),哈哈!這里貼出傳送門以便參考。
到此這篇關(guān)于Android封裝Banner控件方法介紹的文章就介紹到這了,更多相關(guān)Android封裝Banner內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android實(shí)現(xiàn)信號(hào)強(qiáng)度監(jiān)聽(tīng)的方法
這篇文章主要介紹了Android實(shí)現(xiàn)信號(hào)強(qiáng)度監(jiān)聽(tīng)的方法,是Android手機(jī)中很常見(jiàn)的一個(gè)實(shí)用功能,需要的朋友可以參考下2014-08-08Android編程實(shí)現(xiàn)VideoView循環(huán)播放功能的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)VideoView循環(huán)播放功能的方法,結(jié)合簡(jiǎn)單實(shí)例形式分析了Android使用VideoView實(shí)現(xiàn)多媒體播放功能的操作技巧,需要的朋友可以參考下2017-02-02Android中使用itemdecoration實(shí)現(xiàn)時(shí)間線效果
這篇文章主要介紹了Android中使用itemdecoration實(shí)現(xiàn)時(shí)間線效果,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02Android程序開發(fā)之手機(jī)APP創(chuàng)建桌面快捷方式
這篇文章主要介紹了Android程序開發(fā)之手機(jī)APP創(chuàng)建桌面快捷方式 的相關(guān)資料,需要的朋友可以參考下2016-04-04