Android封装Banner控件方法介绍
作者:萌动小彩笔
android-banner实现了一般banner循环轮播的效果,一页只显示一张图片,也可以一页显示一张图和相邻两个图片的一部分,此项目仅仅是banner展示图片,没有多余的诸如指示器、页面切换动画等效果代码,详见效果图和案例代码
如上图所示效果我们应该都不陌生,这是一个简单的banner轮播效果,网上也有很多的开源项目,但有时候可能我们仅仅只需要一些简单的效果,并不需要其他过多的东西。这里简单的对banner进行一下封装,随时调用和添加一些新的功能。
代码展示
/** * Created by xiaolong on 2018/1/23. */ public class BannerView extends FrameLayout implements ViewPager.OnPageChangeListener{ private ViewPager viewPager; //网络图片地址 private List<String> imageUrls; //指示点的容器 private LinearLayout pointLayout; //当前页面位置 private int currentItem; //自动播放时间 private int autoPlayTime = 2000; //是否自动播放 private boolean isAutoPlay; //是否是一张图片 private boolean isOneImage; //监听事件 private OnBannerItemClick onBannerItemClick; //这里利用handler实现循环播放 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); //默认自动播放 isAutoPlay = typedArray.getBoolean(R.styleable.BannerView_isAutoPlay,true); typedArray.recycle(); viewPager = new ViewPager(getContext()); pointLayout = new LinearLayout(getContext()); //添加监听事件 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) { //根据滑动松开后的状态,去判断当前的current 并跳转到指定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); } } //添加网络图片 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) { //添加指示点 addPoints(); } BannerAdapter adapter = new BannerAdapter(); viewPager.setAdapter(adapter); //默认当前图片 viewPager.setCurrentItem(1); //判断是否自动播放和是否是一张图片的情况 if (isAutoPlay && !isOneImage) { handler.sendEmptyMessageDelayed(0,autoPlayTime); } } //添加指示点 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); } //返回真实的位置 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; } //添加监听事件回调 public interface OnBannerItemClick{ void onItemClick(int position); } }
调用方式
//设置是否自动播放 bannerView.setAutoPlay(true); //添加网络图片 bannerView.setImageUrls(data); //banner的点击事件 bannerView.setOnBannerItemClick(new BannerView.OnBannerItemClick() { @Override public void onItemClick(int position) { Toast.makeText(MainActivity.this,"图片" + position,Toast.LENGTH_LONG).show(); } });
代码分析
这里我只考虑了使用网络图片进行展示,使用本地图片原理是一样的,在里面多加个方法即可。此效果代码不是很复杂,通俗易懂。唯一值得一说的是我在实现viewpager
无限滑动时采用的是return imageUrls.size() + 2
的方法。这里我们添加两条数据分别为第一条和最后一条。第一条代表着最后一张图片而最后一条则代表着第一张图片,这里手动画个图:
通过此图我们应该不难发现,当我们滑动到第二个0的时候则跳转到第一个0,滑动到第一个2的时候则跳转到第二个2。这里0代表第一张图片,2代表第二张图片。这样就可以实现无限滑动的效果了,可能有些人会觉得这样做有些复杂还要判断真实的位置不如直接将getConut()
返回一个最大值然后取其中间值即可。但这样做其实代码性能并不是很高。
结束
这样一个常用的banner就写好了,当我们需要实现一些滑动动画的时候,可以在里面实现viewpager
的动画属性即可。先从简单的入手,慢慢的就可以了解更多的原理和知识点,哈哈!这里贴出传送门以便参考。
到此这篇关于Android封装Banner控件方法介绍的文章就介绍到这了,更多相关Android封装Banner内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!