轮播图是 Android 常用功能之一,效果大概是这样的:

之前我封装写了一个,基本达到了要求,是继承了 Fragment(当时脑袋肯定锈掉了),里面 Viewpager add Fragment,这次项目多处有轮播图,发现之前封装的不够用,简直漏洞百出:1、比如底部 point 的位置,之前固定在中间,现在可能要放在右下角,point 最好也能动态改图片;2、现在项目跟微信一样,底部 tab 切换,中间是 Fragment 替换,发现轮播图有问题,Fragment A 循环的 point 的 positoin 居然影响到了 Fragment B,照理,这是两个 BannerFragment,不会影响的啊,报以下错误:

java.lang.IllegalStateException: The application's PagerAdapter changed the adapter's
contents without calling PagerAdapter#notifyDataSetChanged!

经过排查,找到了原因,因为 Viewpager add Fragment 我全部放在一个类,因此:

public static List<Object> bannerList = new ArrayList<>();

这里 static 坏事了,之前一个 banner 没有暴露出来。3、继承了 Fragment,引用比较麻烦,Fragment 有两者引用方法,xml 和代码,两者方式 addData 却报错;4、banner 没有写点击回调。

再次封装

综合以上问题,我进行了优化,继承 LinearLayout,当一个控件来引用,省去不必要的麻烦,底部 point 的位置可以设置:

pointLayout.setGravity(bannerPointGravity);

另外自定义了属性,动态设置 point 大小和图片,轮播图循环时间,也能代码设置,完整代码示例:

 * Created by WuXiaolong on 2017/8/24.* 个人博客:http://wuxiaolong.me*/public class BannerLayout extends LinearLayout {private ViewPager viewPager;private LinearLayout pointLayout;private ScheduledExecutorService scheduler;private int mPosition = 0;private int mBannerCount = 1;private Context context;private Activity activity;private int bannerPointSize;private int bannerPointGravity;private int bannerPointDrawableSelected, bannerPointDrawableUnselected;private int bannerDelaySecond;public BannerLayout(Context context) {this(context, null);}public BannerLayout(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public BannerLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initView(context, attrs);}private void initView(Context context, AttributeSet attrs) {this.context = context;activity = (Activity) context;TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BannerLayout);bannerPointSize = typedArray.getDimensionPixelSize(R.styleable.BannerLayout_bannerPointSize, 10);bannerPointGravity = typedArray.getInt(R.styleable.BannerLayout_bannerPointGravity, Gravity.CENTER);bannerDelaySecond = typedArray.getInt(R.styleable.BannerLayout_bannerDelaySecond, 5);bannerPointDrawableSelected = typedArray.getResourceId(R.styleable.BannerLayout_bannerPointDrawableSelected, R.mipmap.point01);bannerPointDrawableUnselected = typedArray.getResourceId(R.styleable.BannerLayout_bannerPointDrawableUnselected, R.mipmap.point02);typedArray.recycle();View view = View.inflate(context, R.layout.banner_view_pager, null);addView(view);viewPager = (ViewPager) view.findViewById(R.id.viewPager);pointLayout = (LinearLayout) view.findViewById(R.id.pointLayout);pointLayout.setGravity(bannerPointGravity);viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}@Overridepublic void onPageSelected(int position) {addPointLayout(position);}@Overridepublic void onPageScrollStateChanged(int state) {}});}public void start(List<Object> bannerList) {bannerShutdown();mBannerCount = bannerList.size();BannerPagerAdapter bannerPagerAdapter = new BannerPagerAdapter(context, bannerList);viewPager.setAdapter(bannerPagerAdapter);addPointLayout(0);startScheduler();}private void addPointLayout(int position) {pointLayout.removeAllViews();for (int i = 0; i < mBannerCount; i++) {ImageView imageView = new ImageView(context);LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(bannerPointSize, bannerPointSize);layoutParams.setMargins(10, 0, 0, 0);imageView.setLayoutParams(layoutParams);if (position == i) {imageView.setImageResource(bannerPointDrawableSelected);} else {imageView.setImageResource(bannerPointDrawableUnselected);}pointLayout.addView(imageView);}}private void startScheduler() {scheduler = Executors.newSingleThreadScheduledExecutor();scheduler.scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {mPosition = viewPager.getCurrentItem();if (mPosition < mBannerCount - 1) {mPosition++;} else {mPosition = 0;}activity.runOnUiThread(new Runnable() {@Overridepublic void run() {viewPager.setCurrentItem(mPosition);}});}}, 1, bannerDelaySecond, TimeUnit.SECONDS);}public void bannerShutdown() {if (scheduler != null)scheduler.shutdown();}private class BannerPagerAdapter extends PagerAdapter {private List<Object> bannerList = new ArrayList<>();private Context context;BannerPagerAdapter(Context context, List<Object> bannerList) {this.context = context;this.bannerList.clear();this.bannerList.addAll(bannerList);}@Overridepublic int getCount() {return bannerList.size();}@Overridepublic boolean isViewFromObject(View view, Object object) {return view == object;}@Overridepublic Object instantiateItem(ViewGroup container, final int position) {ImageView imageView = new ImageView(context);imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);Object object = bannerList.get(position);//这里我封装了 Glide 4.0 的工具类,用于显示图片ImageLoaderUtil.load(context, object, imageView);container.addView(imageView);return imageView;}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {container.removeView((View) object);}}public int dp2px(float var0) {float var1 = context.getResources().getDisplayMetrics().density;return (int) (var0 * var1 + 0.5F);}public void setBannerPointSize(int bannerPointSize) {this.bannerPointSize = dp2px(bannerPointSize);}public void setBannerPointGravity(int bannerPointGravity) {this.bannerPointGravity = bannerPointGravity;pointLayout.setGravity(bannerPointGravity);}public void setBannerPointDrawableSelected(int bannerPointDrawableSelected) {this.bannerPointDrawableSelected = bannerPointDrawableSelected;}public void setBannerPointDrawableUnselected(int bannerPointDrawableUnselected) {this.bannerPointDrawableUnselected = bannerPointDrawableUnselected;}public void setBannerDelaySecond(int bannerDelaySecond) {this.bannerDelaySecond = bannerDelaySecond;}}

其中自定义属性的attrs.xml:

<resources><declare-styleable name="BannerLayout"><!--轮播图点的大小--><attr name="bannerPointSize" format="dimension" /><!--轮播图点的位置,分别有左中右--><attr name="bannerPointGravity" format="enum"><enum name="left" value="3" /><enum name="center" value="17" /><enum name="right" value="5" /></attr><!--轮播图点选中的图片--><attr name="bannerPointDrawableSelected" format="reference" /><!--轮播图点未选中的图片--><attr name="bannerPointDrawableUnselected" format="reference" /><!--轮播图循环时间,单位秒--><attr name="bannerDelaySecond" format="integer" /></declare-styleable>
</resources>

使用说明

xml

<com.wuxiaolong.bannersample.BannerLayoutandroid:id="@+id/bannerView"android:layout_width="match_parent"android:layout_height="198dp"app:bannerDelaySecond="3"app:bannerPointDrawableSelected="@drawable/gray_radius"app:bannerPointDrawableUnselected="@drawable/white_radius"app:bannerPointGravity="right"app:bannerPointSize="10dp" />

调用:

public class MainActivity extends AppCompatActivity {private BannerLayout bannerView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);bannerView = (BannerLayout) findViewById(R.id.bannerView);List<Object> bannerList = new ArrayList<>();bannerList.add(R.mipmap.horizontal_default);bannerList.add("http://pic1.win4000.com/wallpaper/5/598161750eddb.jpg");bannerList.add("http://pic1.win4000.com/wallpaper/4/597efb5b6aae8.jpg");bannerView.setBannerPointSize(10);bannerView.setBannerPointGravity(Gravity.CENTER);bannerView.setBannerPointDrawableSelected(R.drawable.gray_radius);bannerView.setBannerPointDrawableUnselected(R.mipmap.point01);bannerView.setBannerDelaySecond(5);//banner 设置方法完毕时最后调用 start 方法bannerView.start(bannerList);}@Overrideprotected void onStop() {super.onStop();bannerView.bannerShutdown();}
}

最后

欢迎加入Android进阶交流群;701740775。进群可免费领取一份最新技术大纲和Android进阶资料。请备注csdn

Android 轮播图从 0 到 1相关推荐

  1. android github轮播图,GitHub - ZTJzzz/Banner: Android轮播图

    Android轮播图 - Banner 纵观Android古今,轮播图已然泛滥成灾!大神们各显神通大兴土木,所起楼台之高让后来者心生膜拜,纷纷Star!但不法分子也是层出不穷,为求"大神&q ...

  2. android轮播图实现方案,Android轮播图实现教程

    ListView的headerView设置为轮播图之后结合上/下拉刷新/加载的模式成为现在大多数APP的一个必须具备的功能,对于许多初学者来说想要实现轮播图这样一个集线程睡眠.自动处理.替换过程中刷新 ...

  3. android轮播图简单实现(左右无限滑动,自动轮播)

    直接上代码了,都有注释,原理很简单 public class MainActivity extends AppCompatActivity { private static final String ...

  4. Android轮播图原理思路分析+实现方案

    来自:http://blog.csdn.net/wubihang/article/details/52512597 ListView的headerView设置为轮播图之后结合上/下拉刷新/加载的模式成 ...

  5. Android轮播换背景,Android 轮播图的实现方法总结

    SliderLayout LoopViewPage BGABanner 自定义view实现轮播 仿魅族的banner轮播图 1. SliderLayout 预览效果如下 687474703a2f2f7 ...

  6. Android轮播图

    轮播图是很常用的一个效果 核心功能已经实现 没有什么特殊需求 自己没事研究的 所以封装的不太好 一些地方还比较糙 为想要研究轮播图的同学提供个参考 目前测试图片为mipmap中的图片 没有写从网络加载 ...

  7. android开发banner框架,Android 轮播图 最火的banner框架 (包含demo和代码解释)

    在android里,轮播图的实现可以使用viewpage的控件实现,但由于实现有点繁琐,可以使用banner框架,方便快捷的实现轮播图的效果.这里首先贴上github的banner框架地址:https ...

  8. android 轮播图

    最近做项目,自己封装了一个图片轮播的组件,主要的思想就采用ViewPager和ScrollGater实现,图片加载用的Imageloader,也可以换其他的,比如Glide.具体封装的组件件源码,这里 ...

  9. Android轮播图 banner,图片视频混播banner

    1.使用Android循环滚动控件--ViewFlipper实现方法:https://blog.csdn.net/meixi_android/article/details/84615857 2.使用 ...

最新文章

  1. linux网络配置答案,Linux网络配置与管理作业3答案.doc
  2. Python sys.path详解
  3. T1-TensorFlow基础
  4. 【2018.5.12】模拟赛之一-ssl2413 排名【玄学】
  5. 图像算法五:【图像小波变换】多分辨率重构、Gabor滤波器、Haar小波
  6. STM32-关于Proteus 仿真无法运行STM32CubeMX自动生成的代码
  7. python 颜色大全
  8. 紫薇在线排盘php源码,灵匣网紫微斗数在线排盘系统
  9. 图片旋转90度解决的方法
  10. C/C++结构体内存对齐问题
  11. 调试python程序---pdb
  12. tar .........
  13. 维基解密网站网址是什么
  14. netstat命令输出详解
  15. MIPCMS模板开发之404页面
  16. mysql桥梁模式_桥接模式(Bridge Pattern)
  17. Linux/Ubuntu操作系统及常用命令
  18. html中%3ch3%3e有颜色吗,在增强 iOS 通知系统这件事上,IFTTT 和 Pushover 谁做得更好?...
  19. echars实现中国地图 省级自动切换
  20. 简单探讨可牛影像软件中具有肤质保留功能的磨皮算法及其实现细节

热门文章

  1. FIFO队列 ADT接口 链表实现
  2. java 多线程 day06 threadLocal
  3. 学习OpenCV——BOW特征提取函数(特征点篇)
  4. Uva_11427 Expect the Expected
  5. Aptana Studio 3 如何汉化,实现简体中文版
  6. 練習重繪TreeView控件
  7. 如何使用JMeter发送Post请求
  8. linux vi 编辑器用法
  9. weblogic 文件打开数_WebLogic任意文件上传漏洞(CVE20192618)复现
  10. python处理子进程_Python多处理+子进程问题