打造Android一体式轮播广告条
来源:互联网 发布:卡片战斗先导者g爱知 编辑:程序博客网 时间:2024/04/29 19:51
轮播广告条在应用中非常广泛的使用,这次在看公司一个项目时,发现多处都使用到轮播广告条的功能,看到了很多重复的代码,所以萌生了整合的想法。先来看看常见的轮播广告条的样式。ps:标题有点吹牛逼了。嘎嘎
通过上面我们也可以发现,常见的轮播广告条的组成:
- 一个ViewPager控件
- 一个指示器控件
所以在整合的过程中,我就是将ViewPager和指示器部分封装起来了。根据上面的布局,所以我们继承RelativeLayout进行布局。所以我们定义类ViewPagerBarnner
public class ViewPagerBarnner extends RelativeLayout implements OnPageChangeListener { /** * ViewPager对象 */ private ViewPager viewPager; /** * 指示器 */ private LinearLayout indicatorView; private Context context; /** * 图片url地址 */ private List<String> imageUrls = new ArrayList<String>(); /** * 获取的ImageView对象集合 */ private List<ImageView> imageViews = new ArrayList<ImageView>(); /** * 点击ViewPager中ImageView的回调事件 */ private ViewPagerClick viewPagerClick; /** * 指示器的默认大小 */ private float indicatorSize = 15; /** * 指示器的drawable对应的资源id */ private int idBackgroud; /** * 指示器之间的距离 */ private float indicatorMargin = 20; ... }
上面就是我们需要的控件,我们定义了Viewpager和一个LinearLayout,其中LinearLayout用于存储我们的指示器。为了提高定制性,我们自定义了三个属性,如下:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="ViewPager"> <attr name="containerHeight" format="dimension"/> <!-- 容器的高度 --> <attr name="indicatorSize" format="dimension"/> <!-- 指示器大小 --> <attr name="indicatorBackgroud" format="reference"/> <!-- 指示器背景,可以说drawable对象 --> <attr name="indicatorMargin" format="dimension"/> <!-- 指示器之间的间隔 --> </declare-styleable> </resources>
有了自定义的属性,我们在构造函数中进行获取设定的值。这里,我们定义背景为一个reference类型,在使用的过程中我通过type
public ViewPagerBarnner(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; initViews(); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ViewPager); indicatorSize = typedArray.getDimension(R.styleable.ViewPager_indicatorSize, 10); indicatorMargin = typedArray.getDimension(R.styleable.ViewPager_indicatorMargin, 15); idBackgroud = typedArray.getResourceId(R.styleable.ViewPager_indicatorBackgroud, 0); containerHeight = typedArray.getDimension(R.styleable.ViewPager_containerHeight, 20); typedArray.recycle(); } /** * 初始化View的视图 */ private void initViews(){ viewPager = new ViewPager(context); LayoutParams viewPagerParams = new LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); viewPager.setLayoutParams(viewPagerParams); viewPager.setAdapter(viewPagerAdapter); viewPager.setOnPageChangeListener(this); indicatorView = new LinearLayout(context); indicatorView.setOrientation(LinearLayout.HORIZONTAL); LayoutParams layoutParams = new LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,(int)containerHeight); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL); indicatorView.setLayoutParams(layoutParams); addView(viewPager); addView(indicatorView); }
我们初始化ViewPager和LinearLayout,同时对它们进行布局。将LinearLayout放到最底部。接下来就是设置我们的监听事件以及为ViewPager设置Adapter。
/** * ViewPager的适配器 */ private PagerAdapter viewPagerAdapter = new PagerAdapter() { @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public int getCount() { return imageUrls == null ? 0 : imageUrls.size(); } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } @Override public void finishUpdate(ViewGroup container) { } @Override public int getItemPosition(Object object) { return super.getItemPosition(object); } @Override public Object instantiateItem(ViewGroup container, int position) { ImageView imageView = null; if(imageViews != null && imageViews.size() > 0){ imageView = imageViews.get(position); imageView.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { if(viewPagerClick != null){ viewPagerClick.viewPagerOnClick(view); } } }); } container.addView(imageView); return imageView; } }; @Override public void onPageScrollStateChanged(int arg0) { } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageSelected(int location) { setSelectPage(location); }
至此,整体的框架已经完成,然后就是我们为Adapter赋予数据。具体处理如下:
/** * 从url地址创建imageview对象,同时初始化指示器 */ private void createImageView(List<String> imageUrlList){ if(imageUrlList != null && imageUrlList.size() > 0){ ImageView imageView; View pointView; for(String url : imageUrlList){ imageView = new ImageView(context); imageView.setScaleType(ScaleType.FIT_XY); ImageLoader.getInstance().displayImage(url, imageView); imageView.setTag(url); imageViews.add(imageView); pointView = new View(context); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams((int)(indicatorSize),(int)(indicatorSize)); params.rightMargin = (int)indicatorMargin; pointView.setLayoutParams(params); pointView.setBackgroundDrawable(context.getResources().getDrawable(idBackgroud)); pointView.setEnabled(false); indicatorView.addView(pointView); } setSelectPage(0); } } /** * 设置当前选中页面 * @param position */ private void setSelectPage(int position){ for(int index=0; index < indicatorView.getChildCount();index++){ if(position == index){ indicatorView.getChildAt(index).setEnabled(true); }else{ indicatorView.getChildAt(index).setEnabled(false); } } } /** * 设置图片的地址,从网络加载图片 * @param imageUrls */ public void addImageUrls(List<String> imageUrls) { this.imageUrls.addAll(imageUrls); createImageView(imageUrls); viewPagerAdapter.notifyDataSetChanged(); }
至此,就完成了基本的广告条展示功能。我们看下MainActivity和布局中的使用。
<com.lcwang.androidviews.ViewPagerBarnner android:id="@+id/viewPager" android:layout_height="160dp" android:layout_width="match_parent" viewpager:indicatorSize="8dp" viewpager:indicatorMargin="10dp" viewpager:indicatorBackgroud="@drawable/indicator_backgroud" /> @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ViewPagerBarnner viewPagerBarnner = (ViewPagerBarnner) findViewById(R.id.viewPager); List<String> url = new ArrayList<String>(); url.add("http://pic1.nipic.com/2008-12-25/2008122510134038_2.jpg"); url.add("http://pic3.nipic.com/20090525/2416945_231841034_2.jpg"); url.add("http://img3.3lian.com/2013/s1/20/d/57.jpg"); url.add("http://pic1.nipic.com/2008-11-13/2008111384358912_2.jpg"); url.add("http://img.61gequ.com/allimg/2011-4/201142614314278502.jpg"); viewPagerBarnner.addImageUrls(url); viewPagerBarnner.setViewPagerClick(new ViewPagerClick() { @Override public void viewPagerOnClick(View view) { Toast.makeText(MainActivity.this, view.getTag().toString(), Toast.LENGTH_SHORT).show(); } }); }
我们自定义指示器的样式:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" > <item android:state_enabled="true"> <shape android:shape="oval"> <size android:width="3dp" android:height="3dp"/> <solid android:color="#00FF00"/> </shape> </item> <item android:state_enabled="false"> <shape android:shape="oval"> <size android:width="3dp" android:height="3dp"/> <solid android:color="#FFFFFF"/> </shape> </item> </selector>
通过上面的效果图,我们发现基本的效果已经有了,但是还没有实现无限循环以及自动播放的功能。所以接下来我们就是实现无限循环和自动播放的功能。网上流行的两种实现方法,我们先看一种,我画了一个草图:
为了方便我们增加头尾,我将存放url和imageview的集合改为LinkedList。
private LinkedList<String> imageUrls = new LinkedList<String>(); private LinkedList<ImageView> imageViews = new LinkedList<ImageView>();
主要的判断处理就是增加头尾处,这里说一点,在为ImageView的集合增加首尾的时候,为什么重新获取而不是利用集合中已经存在的,这是因为如果我们将该对象进行利用后,持有该对象的引用,然后在切换时,报该ImageView已经有父容器了。(这是我理解的)
@Override public void onPageSelected(int location) { if(location == this.imageUrls.size() -1){ location = 1; viewPager.setCurrentItem(location,false); }else if(location == 0){ location = this.imageUrls.size() -2; viewPager.setCurrentItem(location,false); } currentPostion = location; setSelectPage(location - 1); } /** * 从url地址创建imageview对象,同时初始化指示器 */ private void createImageView(List<String> imageUrlList){ if(imageUrlList != null && imageUrlList.size() > 0){ ImageView imageView; View pointView; //清除头尾 if(imageViews.size() > 1){ imageViews.removeFirst(); imageViews.removeLast(); } for(String url : imageUrlList){ imageView = new ImageView(context); imageView.setScaleType(ScaleType.FIT_XY); ImageLoader.getInstance().displayImage(url, imageView); imageView.setTag(url); imageViews.add(imageView); pointView = new View(context); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams((int)(indicatorSize),(int)(indicatorSize)); params.rightMargin = (int)indicatorMargin; pointView.setLayoutParams(params); pointView.setBackgroundDrawable(context.getResources().getDrawable(idBackgroud)); pointView.setEnabled(false); indicatorView.addView(pointView); } //增加头尾 if(imageViews.size() > 1){ ImageView ivFirst = new ImageView(context); ImageView ivLast = new ImageView(context); ImageLoader.getInstance().displayImage(imageUrls.getLast(),ivLast); ImageLoader.getInstance().displayImage(imageUrls.getFirst(),ivFirst); imageViews.addFirst(ivFirst); imageViews.addLast(ivLast); } viewPagerAdapter.notifyDataSetChanged(); viewPager.setCurrentItem(1); } } /** * 设置当前选中页面 * @param position */ private void setSelectPage(int position){ for(int index=0; index < indicatorView.getChildCount();index++){ if(position == index){ indicatorView.getChildAt(index).setEnabled(true); }else{ indicatorView.getChildAt(index).setEnabled(false); } } } /** * 设置图片的地址,从网络加载图片 * @param imageUrls */ public void addImageUrls(List<String> imageUrls) { if(this.imageUrls.size() > 1){//清除头尾 this.imageUrls.removeFirst(); this.imageUrls.removeLast(); } this.imageUrls.addAll(imageUrls); if(this.imageUrls.size() >1){//增加头尾 String first = this.imageUrls.getFirst(); this.imageUrls.addFirst(this.imageUrls.getLast()); this.imageUrls.addLast(first); } createImageView(imageUrls); }
这样就可以实现了ViewPager的循环,同时我们可以通过addImageUrls方法进行新增页。实现了循环,就开始自动播放,自动播放的实现无外乎几种:
- 1、定时器:Timer
- 2、开子线程 while true 循环
- 3、ColckManager
- 4、 用handler 发送延时信息,实现循环
我们通过Handler进行实现。
private Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { viewPager.setCurrentItem(currentPostion + 1); mHandler.sendEmptyMessageDelayed(0, 3000); } }; /** * 初始化View的视图 */ private void initViews(){ ... mHandler.sendEmptyMessageDelayed(0, 3000); }
这样就完成了一个组合的ViewPager开发。来瞄一眼效果:
至此,这个控件就完成了,可以很方便使用,在也不用去搞很多逻辑判断了。这里面加载网络图片使用的ImageLoader库,需要添加,或者改源码自己修改。
源码下载地址
github
下篇地址:http://blog.csdn.net/Mr_dsw/article/details/50429396
- 打造Android一体式轮播广告条
- 打造Android一体化轮播广告条
- 打造一体式广告轮播条升级版
- Android从零开搞系列:自定义View(11)使用ViewPager打造轮播广告条
- Android轮播广告
- Android广告轮播
- ViewPaper实现轮播广告条
- ViewPaper实现轮播广告条
- ConvenientBanner无线轮播 实现广告条
- ConvenientBanner 广告条的轮播
- 轮播大图,广告条的做法
- android 学习笔记之四 ViewPager 打造不一样的广告轮播切换效果
- ANDROID轮播广告图片
- Android自定义轮播广告
- android Banner 广告轮播
- Android无限广告轮播
- Android无限广告轮播
- Android Viewpager3D广告轮播
- OC-UI-004.纯代码编写按钮的简单方法
- 【Android Studio初级学习】Android Studio如何发布APK
- 用TC、按键、易语言接入百宝云开发注册码系统
- 上拉刷新下拉加载
- WinForm窗体键盘事件,支持方向键和回车键
- 打造Android一体式轮播广告条
- Foundation框架中的NSArray类和NSMutableArray类
- Android中调用startActivity结果导致:java.lang.RuntimeException: Unable to start activity ComponentInfo{xxx}
- Block从简单到高级的使用,以及项目中经常使用的场景
- spring-mvc环境搭建及helloworld的demo实现
- hdoj2012水题
- 30.Evaluate the following CREATE TABLE commands:
- Docker学习一
- char 转 NSString 、NSString 转 char* (const char*)