Android自定义控件实现简单的轮播图控件
最近要做一个轮播图的效果,网上看了几篇文章,基本上都能找到实现,效果还挺不错,但是在写的时候感觉每次都要单独去重新在activity里写一堆代码。于是自己封装了一下。本篇轮播图实现原理原文出处:循环广告位组件的实现,这里只是做了下封装成一个控件,不必每次重复写代码了。
效果图:
实现分析
轮播图的功能就是实现左右滑动的广告、图片信息展示,那我们就用viewpager来实现,由于考虑到用户体验,我们还需要在下面加一个指示器来标示滑动到了第几张轮播图。指示器我们可以用一个线性布局来根据要展示的轮播图设置显示的view,我们要做这样的一个控件没有什么特殊的效果,其实就是两个控件的组合,只是我们要在内部处理好它们之间的交互关系(其实就是viewpager滚动的时候,下面指示器的展示),所以我们就用自定义控件当中的组合方式来实现。
下面开始
1、定义一个控件继承framelayout,写一个xml文件
public class carouselview extends framelayout implements viewpager.onpagechangelistener { private context context; private int totalcount =100;//总数,这是为实现无限滑动设置的 private int showcount;//要显示的轮播图数量 private int currentposition =0;//当前viewpager的位置 private viewpager viewpager; private linearlayout carousellayout;//展示指示器的布局 private adapter adapter; private int pageitemwidth;//每个指示器的宽度 private boolean isusertouched = false; public carouselview(context context) { super(context); this.context = context; } public carouselview(context context, attributeset attrs) { super(context, attrs); this.context = context; } public carouselview(context context, attributeset attrs, int defstyleattr) { super(context, attrs, defstyleattr); this.context = context; } <?xml version="1.0" encoding="utf-8"?> <framelayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v4.view.viewpager android:id="@+id/gallery" android:layout_width="match_parent" android:layout_height="match_parent" android:unselectedalpha="1"> </android.support.v4.view.viewpager> <linearlayout android:layout_height="wrap_content" android:layout_width="fill_parent" android:orientation="horizontal" android:gravity="center" android:layout_gravity="center|bottom" android:id="@+id/carousellayoutpage" android:padding="10dip"> </linearlayout> </framelayout>
上面的代码把两个要用到的控件viewpager和carousellayout都包含在定义的carouselview里面了,下面就是要获取
2、onfinishinflate()中获取我们需要的控件
@override protected void onfinishinflate() { super.onfinishinflate(); view view = layoutinflater.from(context).inflate(r.layout.carousel_layout,null); this.viewpager = (viewpager) view.findviewbyid(r.id.gallery); this.carousellayout = (linearlayout)view.findviewbyid(r.id.carousellayoutpage); pageitemwidth = convertutils.dip2px(context,5); this.viewpager.addonpagechangelistener(this); addview(view); }
onfinishinflate()方法是自定义控件中常用的一个方法,它表示从xml加载组件完成了,在该方法中我们通过layoutinflater.from(context).inflate 获取到个viewpager对象和carousellayout对象,并对pageitemwidth进行了赋值。
同时为viewpager设置addonpagechangelistener。这里别忘记调用addview();否则控件就展示不了啦!
3、通过设置set方法来获取数据,同时初始化界面效果
到这一步我们已经获取到了展示轮播图的viewpager对象,那接下来要让它展示你肯定想到了写个类继承pageradapter,然后重写getcount,isviewfromobject,isviewfromobject,destroyitem等方法来让viewpager展示轮播图。但是我们又不能写得太固定,因为可能每个人想要展示的数据不一样,所以我们定义一个接口来给外部使用的人写自己的逻辑。上代码:
//定义一个接口让外部设置展示的view public interface adapter{ boolean isempty(); view getview(int position); int getcount(); } //viewpager的适配器 class viewpageradapter extends pageradapter { @override public int getcount() { return totalcount; } @override public boolean isviewfromobject(view view, object object) { return view==object; } @override public object isviewfromobject(viewgroup container, int position) { position %= showcount; //调用接口的getview()获取使用者要展示的view; view view = adapter.getview(position); container.addview(view); return view; } @override public void destroyitem(viewgroup container, int position, object object) { container.removeview((view) object); } @override public int getitemposition(object object) { return super.getitemposition(object); } @override public void finishupdate(viewgroup container) { super.finishupdate(container); int position = viewpager.getcurrentitem(); //实现viewpager到第一页的实现能向左滑动 if (position==0){ position=showcount; viewpager.setcurrentitem(position,false); }else if (position==totalcount-1){//viewpager到最后一页的实现向又滑动 position = showcount - 1; viewpager.setcurrentitem(position,false); } } } //为外部提供设置数据源的方法,同时为viewpager做展示 public void setadapter(adapter adapter){ this.adapter = adapter; if (adapter!=null){ init(); } }
上面的代码就是定义了一个接口让外部来设置数据,提供setadapter来为adapter赋值,同时初始化界面效果,init()方法中就是数据的初始化,代码如下:
private void init() { viewpager.setadapter(null); carousellayout.removeallviews();//清空之前的数据 if (adapter.isempty()){ return; } int count = adapter.getcount(); showcount = adapter.getcount(); for (int i=0;i<count;i++){ view view = new view(context); //用来做指示器的view,通过state来做展示效果 if (currentposition==i){ view.setpressed(true); linearlayout.layoutparams params = new linearlayout.layoutparams(pageitemwidth + convertutils.dip2px(context,3),pageitemwidth + convertutils.dip2px(context,3)); params.setmargins(pageitemwidth, 0, 0, 0); view.setlayoutparams(params); }else { linearlayout.layoutparams params = new linearlayout.layoutparams(pageitemwidth,pageitemwidth); params.setmargins(pageitemwidth,0,0,0); view.setlayoutparams(params); } view.setbackgroundresource(r.drawable.carousel_layout_page); carousellayout.addview(view); } viewpager.setadapter(new viewpageradapter()); viewpager.setcurrentitem(0); //让手指触碰到的时候自动轮播不起效 this.viewpager.setontouchlistener(new ontouchlistener() { @override public boolean ontouch(view v, motionevent event) { switch (event.getaction()){ case motionevent.action_down: case motionevent.action_move: isusertouched = true; break; case motionevent.action_up: isusertouched = false; break; } return false; } }); mtimer.schedule(mtimertask, 3000, 3000); }
主要的逻辑代码就是这样啦,一个轮播图的控件就做好了。下面来看一下使用:
4、使用
xml中写我们的轮播图控件:
<com.yangqiangyu.test.carouselview.carouselview android:layout_width="match_parent" android:layout_height="220dp"> </com.yangqiangyu.test.carouselview.carouselview>
java代码中获取控件,同时设置接口
carouselview carouselview = (carouselview) findviewbyid(r.id.carouselview); carouselview.setadapter(new carouselview.adapter() { @override public boolean isempty() { return false; } @override public view getview(int position) { view view = minflater.inflate(r.layout.item,null); imageview imageview = (imageview) view.findviewbyid(r.id.image); imageview.setimageresource(mimagessrc[position]); return view; } @override public int getcount() { return mimagessrc.length; } });
返回是否为空,在getview(int position)中return我们想返回的view,就是这么简单了啦。
希望本文所述对大家学习android软件编程有所帮助。
上一篇: 深入理解python中的select模块