Android自定义控件案例汇总1(菜单、popupwindow、viewpager)
自定义控件是根据自己的需要自己来编写控件。安卓自带的控件有时候无法满足你的需求,这种时候,我们只能去自己去实现适合项目的控件。同时,安卓也允许你去继承已经存在的控件或者实现你自己的控件以便优化界面和创造更加丰富的用户体验。在平常的项目中,我们人为的把自定义控件分为两种:一种是组合方式实现。一种是通过继承view或viewgroup及其子类实现。两者都可以实现我们想要的效果,因此,我们可以根据自己的需求,选择合适的方案。本文以案例的形式来显示几种较为常见的自定义控件。
案例一优酷菜单:
功能介绍:手机界面的底部中央有一个半圆,初始状态显示三级菜单,由外到内分别是第三级菜单,第二级菜单,第三级菜单。每个菜单中有一些按钮,可以用3个容器(RelativeLayout)来表示3个菜单,往里面添加按钮即可。当再次点击中心位置的图片式,隐藏外面两层的的条目。再次点击重心位置的图片时,旋转出二级菜单。点击二级菜单中心位置时,旋转出三级菜单,再次点击则隐藏三级菜单。以上就是优酷菜单要实现的功能。
实现步骤:
1.完成布局文件。由于控件较多所以优酷菜单的布局较为复杂,但是可以在一个根布局设置三个子线性布局来包裹每一个小的控件。通过调整margin值来是使得界面更加的美观。注意3个菜单布局的顺序,先放men3,然后menu2,然后menu1,顺序不能反,因为越往后放的菜单越在界面的上方,这样面积最小的菜单1会在最上方,菜单1不会遮挡到下面的菜单2和菜单3。
2.完成布局文件后,创建一个类,在该类中实现业务逻辑。首先要创建两个布尔类型的常量存储菜单的状态。通过swich语句判断被点击的控件是二级菜单还是一级菜单。如果是一级菜单的中心被点击,则判断三级菜单是否打开。如果三级菜单打开着,则隐藏一级菜单和二级菜单,并修改状态。如果三级菜单隐藏着则判断二级菜单是否隐藏。如果二级菜单打开着,则隐藏二级菜单。如果二级菜单隐藏则打开二级菜单。如果是二级菜单的中心被点击,则只需要判断三级菜单是否隐藏。如果三级菜单打开着,则隐藏三级菜单。如果三级菜单隐藏则打开三级菜单。同时还要修改菜单的状态。
3.接下来可以在一个工具类中实现动画的效果。步骤2中的隐藏和显示均都是通过动画效果实现的。这里的动画效果用到的是补间动画,为RotateAnimation对象传入起始角度,结束的角度,参考对象和参考点坐标。一个小细节是将setFillAfter属性设为true,表示从结束位置开始动画,避免动画结束后又回到起始位置。隐藏和显示区别是旋转的起始角度和结束角度,这里显示设定的起始角度是-180,结束角度为0。隐藏设定的起始角度为0,结束角度为-180。当然也可以设定为其他值,取决于自己想要的效果。
4.代码优化。快速点击按钮时会发现菜单还没隐藏完就开始显示了,或者还没显示完又隐藏了。解决方案:监听动画的开启次数来判断是否需要执行画,给动画类添加一个监听器。设置一个成员变量。当开始开始动画是执行加一操作,结束动画是执行减一操作。这样只有当常量为零时,才没有动画。因此swich语句中加入判断如果当前存在动画,等待动画执行完之后在进入下面的逻辑。
菜单选择界面的布局:
<?xmlversion="1.0"encoding="utf-8"?> <RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <RelativeLayout android:id="@+id/rl_menu3" android:layout_width="280dp" android:layout_height="140dp" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:background="@drawable/level3"> <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginBottom="6dp" android:layout_marginLeft="12dp" android:background="@drawable/channel1"/> <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginBottom="46dp" android:layout_marginLeft="32dp" android:background="@drawable/channel2"/> <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginBottom="80dp" android:layout_marginLeft="60dp" android:background="@drawable/channel3"/> <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="6dp" android:background="@drawable/channel4"/> <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_marginBottom="80dp" android:layout_marginRight="60dp" android:background="@drawable/channel5"/> <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_marginBottom="46dp" android:layout_marginRight="32dp" android:background="@drawable/channel6"/> <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_marginBottom="6dp" android:layout_marginRight="12dp" android:background="@drawable/channel7"/> </RelativeLayout> <RelativeLayout android:id="@+id/rl_menu2" android:layout_width="180dp" android:layout_height="90dp" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:background="@drawable/level2"> <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginBottom="6dp" android:layout_marginLeft="12dp" android:background="@drawable/icon_search"/> <ImageButton android:id="@+id/btn_menu2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="4dp" android:background="@drawable/icon_menu"/> <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_marginBottom="6dp" android:layout_marginRight="12dp" android:background="@drawable/icon_myyouku"/> </RelativeLayout> <RelativeLayout android:id="@+id/rl_menu1" android:layout_width="100dp" android:layout_height="50dp" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:background="@drawable/level1"> <ImageButton android:id="@+id/btn_menu1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:background="@drawable/icon_home"/> </RelativeLayout> </RelativeLayout>
主界面的布局,在代码中用打气筒把菜单布局打到主界面上。
<?xmlversion="1.0"encoding="utf-8"?> <RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" tools:context="com.example.selectbar.Selectbar"> <com.example.selectbar.Rotate android:layout_centerInParent="true" android:id="@+id/rotate" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </RelativeLayout>
主程序是空实现。
importandroid.os.Bundle; importandroid.support.v7.app.AppCompatActivity; publicclassSelectbarextendsAppCompatActivity{ @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_selectbar); } }
主要逻辑的实现。
importandroid.content.Context; importandroid.util.AttributeSet; importandroid.util.Log; importandroid.view.View; importandroid.widget.RelativeLayout; importcom.example.selectbar.com.example.selectbar.utils.utils; /** *Createdbyhuangon2016/11/22. */ publicclassRotateextendsRelativeLayoutimplementsView.OnClickListener{ privatestaticfinalStringTAG="Rotate"; privateRelativeLayoutrl_menu1,rl_menu2,rl_menu3; privatebooleanmenu2showing=true; privatebooleanmenu3showing=true; publicRotate(Contextcontext){ super(context,null); } publicRotate(Contextcontext,AttributeSetattrs){ super(context,attrs); initdata(context); } privatevoidinitdata(Contextcontext){ Log.i(TAG,"initdata:text"); Viewview=View.inflate(context,R.layout.activity_rolate,null); view.findViewById(R.id.btn_menu1).setOnClickListener(this); view.findViewById(R.id.btn_menu2).setOnClickListener(this); rl_menu1=(RelativeLayout)view.findViewById(R.id.rl_menu1); rl_menu2=(RelativeLayout)view.findViewById(R.id.rl_menu2); rl_menu3=(RelativeLayout)view.findViewById(R.id.rl_menu3); addView(view); } @Override publicvoidonClick(Viewv){ switch(v.getId()){ caseR.id.btn_menu2: if(utils.hasAnimationexcuting()){ return; } if(menu3showing){ utils.hiden(rl_menu3); }else{ utils.show(rl_menu3); } menu3showing=!menu3showing; break; caseR.id.btn_menu1: if(utils.hasAnimationexcuting()){ return; } if(menu3showing){ utils.hiden(rl_menu3); menu3showing=false; utils.hiden(rl_menu2,300); }elseif(menu2showing){ utils.hiden(rl_menu2); }else{ utils.show(rl_menu2); } menu2showing=!menu2showing; break; } } }
还需要一个工具类实现动画的效果。
importandroid.view.View; importandroid.view.ViewGroup; importandroid.view.animation.Animation; importandroid.view.animation.RotateAnimation; /** *Createdbyhuangon2016/11/22. */ publicclassutils{ privatestaticfinalStringTAG="utils"; privatestaticvoidsetviewclickable(Viewview,booleanclickable){ view.setClickable(clickable); if(viewinstanceofViewGroup){ ViewGroupviewgroup=(ViewGroup)view; for(inti=0;i<viewgroup.getChildCount();i++){ Viewchild=((ViewGroup)view).getChildAt(i); child.setClickable(clickable); } } } publicstaticvoidhiden(Viewview){ floatfromDegreeas=0; floattoDegrees=-180f; rotateview(view,fromDegreeas,toDegrees,0l); setviewclickable(view,false); } publicstaticvoidhiden(Viewview,longstartoffset){ floatfromDegreeas=0; floattoDegrees=-180f; rotateview(view,fromDegreeas,toDegrees,startoffset); setviewclickable(view,false); } publicstaticvoidshow(Viewview){ floatfromDegrees=-180f; floattoDegrees=0; rotateview(view,fromDegrees,toDegrees,0l); setviewclickable(view,true); } publicstaticbooleanhasAnimationexcuting(){ returnstartcount>0; } publicstaticvoidrotateview(Viewview,floatfromDegrees,floattoDegrees,longstartoffset){ intpivotXType=RotateAnimation.RELATIVE_TO_SELF; intpivotYType=RotateAnimation.RELATIVE_TO_SELF; floatpivotXValue=0.5f; floatpivatYValue=1.0f; RotateAnimationra=newRotateAnimation(fromDegrees,toDegrees,pivotXType,pivotXValue,pivotYType,pivatYValue); ra.setDuration(500); ra.setFillAfter(true); ra.setStartOffset(startoffset); ra.setAnimationListener(listener); view.startAnimation(ra); } publicstaticintstartcount; staticAnimation.AnimationListenerlistener=newAnimation.AnimationListener(){ @Override publicvoidonAnimationStart(Animationanimation){ startcount++; //Log.i(TAG,"onAnimationStart:"+startcount); } @Override publicvoidonAnimationEnd(Animationanimation){ startcount--; //Log.i(TAG,"onAnimationEnd:"+startcount); } @Override publicvoidonAnimationRepeat(Animationanimation){ } }; }
案例二 popupwindow实现下拉列表:
功能介绍:创建一个textview,当我们点击textview时会弹出一个列表,列表中存放的是数字信息和一张删除图片。列表是用listview实现。点击删除图片可以将本条记录从列表中删除。本案例的有两种,一种是通过动画的缩放实现弹出效果,另一种是采取popupwindow。本文采用的是第二种方案。
实现步骤:
添加布局文件。首先要在界面上放置一个textview,在textview的右边放置一个下拉图片。为了更方便地摆放控件,可以采用相对布局,这样只要保证imageview和textview上对齐、下对齐、右对齐就可以实现要现实的效果。为了是界面更美观,可以把图片设为透明的,即背景为null。这里将popupwindow弹出来的界面用listview表示。因此还要写一个单独的listview以及每一个条目的布局,然后用打气筒打到textview的下方、
Pupupwindow的编写。Popupwindow的编写有两个关键的步骤,一个是new一个pupupwimdow对象,将要显示的布局、布局的高和宽、是否可聚等相关的参数传入。这里pupupwindow的显示界面是用的打气筒把listview加载进来。同时listview条目的布局也用到inflate。因此用到两次打气筒。同时为每一个listview的条目设置条目点击的监听事件,这样在条目被点击时候可以将条目的内容显示在textview中。。Popupwindow的编写另一个关键性的步骤是showAsDropDown,即将要显示在哪个控件下方,偏移量多少出传进来。需要注意的是控件的实际宽高和看到的宽高有一定的误差,只是因为控件的背景用一定的宽度。还有一点就是,按返回键时PopupWindow没法隐藏,给PopupWindow设置一个背景即可解决这个问题,如下:popupWindow.setBackgroundDrawable(newColorDrawable())。每次显示PopupWindow时都创建一个新的PopupWindow对象,其实可以复用一个PopupWindow对象的。即每次创建前先判断popupwindow是否为空。
Listiview条目的编写较为定。这里做了两处的优化。一个是服用conterview,开始操作之前判断conterview是否为空。若为空创建一个新的view,否则复用被回收的conterview。另一处的优化是,每一次finviewbyid会消耗大量的内存。因此可以单独定义一个类,存放控件,在cnterview为空时创建一次。每次调用时只需要调用定义类中的控件。还有一点是,要是条目上的删除图标有用还要对删除图片设定一个点击事件。一个小细节是,当listvie条目中存在button及其子类时,会抢占焦点。因此这里删除图片的标签用的是imageview。当然你也可以采取其他方式,比如,在条目的根布局加上这个属性:android:descendantFocusability="blocksDescendants"。
主界面的布局:
<?xmlversion="1.0"encoding="utf-8"?> <RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="17dp" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.popuwindow.MainActivity"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <EditText android:id="@+id/et_number" android:layout_width="200dp" android:layout_height="wrap_content" android:hint="输入账号"/> <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@id/et_number" android:layout_alignRight="@id/et_number" android:layout_alignTop="@id/et_number" android:background="@null" android:onClick="showNumberListToggle" android:src="@mipmap/down_arrow"/> </RelativeLayout> </RelativeLayout>
listview条目的布局
<?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="horizontal" android:padding="6dp"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/user"/> <TextView android:id="@+id/tv_numer" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="6dp" android:layout_weight="1" android:text="10000" android:textSize="18sp"/> <ImageView android:id="@+id/ib_del" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@null" android:src="@mipmap/delete"/> </LinearLayout>
单独写一个listview。
<?xmlversion="1.0"encoding="utf-8"?> <ListViewxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:cacheColorHint="@null" android:background="@mipmap/listview_background" android:descendantFocusability="blocksDescendants"> </ListView>
主程序中的逻辑。
importandroid.graphics.drawable.ColorDrawable; importandroid.os.Bundle; importandroid.support.v7.app.AppCompatActivity; importandroid.view.View; importandroid.widget.AdapterView; importandroid.widget.EditText; importandroid.widget.ListView; importandroid.widget.PopupWindow; publicclassMainActivityextendsAppCompatActivity{ privateEditTextet_number; privatePopupWindowpopupwindow; @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_number=(EditText)findViewById(R.id.et_number); } publicvoidshowNumberListToggle(Viewview){ if(popupwindow==null){//复用popupwindow ViewcontentView=createContent(); intwidth=et_number.getWidth()-4; intheight=400; booleanfocusable=true; popupwindow=newPopupWindow(contentView,width,height,focusable); popupwindow.setBackgroundDrawable(newColorDrawable()); } Viewanchor=et_number; intxoff=2; intyoff=-5; popupwindow.showAsDropDown(anchor,xoff,yoff); } privateViewcreateContent(){ ListViewlv=(ListView)View.inflate(this,R.layout.activity_list,null); lv.setAdapter(newNumberListAdapter()); lv.setVerticalScrollBarEnabled(false); lv.setOnItemClickListener(monitemclickListener); returnlv; } AdapterView.OnItemClickListenermonitemclickListener=newAdapterView.OnItemClickListener(){ @Override publicvoidonItemClick(AdapterView<?>parent,Viewview,intposition,longid){ Stringnumber=(String)parent.getItemAtPosition(position); et_number.setText(number); popupwindow.dismiss(); } }; }
适配器的编写
importandroid.view.View; importandroid.view.ViewGroup; importandroid.widget.BaseAdapter; importandroid.widget.ImageView; importandroid.widget.TextView; importjava.util.ArrayList; /** *Createdbyhuangon2016/11/22. */ publicclassNumberListAdapterextendsBaseAdapter{ privateArrayList<String>numbers=newArrayList(); { for(inti=0;i<30;i++){ numbers.add(10000+i+""); } } @Override publicintgetCount(){ returnnumbers.size(); } @Override publicObjectgetItem(intposition){ returnnumbers.get(position); } @Override publiclonggetItemId(intposition){ returnposition; } @Override publicViewgetView(finalintposition,ViewconvertView,ViewGroupparent){ Viewview; viewHolderholder; if(convertView==null){ view=View.inflate(parent.getContext(),R.layout.item_number_list,null); holder=newviewHolder(); holder.ib_del=(ImageView)view.findViewById(R.id.ib_del); holder.tv_number=(TextView)view.findViewById(R.id.tv_numer); view.setTag(holder); }else{ view=convertView; holder=(viewHolder)view.getTag(); } holder.ib_del.setImageResource(R.mipmap.delete); holder.tv_number.setText(numbers.get(position)); holder.ib_del.setOnClickListener(newView.OnClickListener(){ @Override publicvoidonClick(Viewv){ numbers.remove(position); notifyDataSetChanged(); } }); returnview; } staticclassviewHolder{ TextViewtv_number; ImageViewib_del; } }
案例三viewpager实现轮播图:
功能介绍: 广告条的实现,又被称为轮播图。在手机界面的最上方放置一个ViewPager功能,实现界面的左右滑动。滑动又分为两种,一种是间隔一定的时间自动滑动,同时还支持手势的左右滑动。一个小细节是在轮播图底部放置和图片数量相等的小点,用于表示当前哪个图片被选中。
实现步骤:
1.布局文件有两部分组成,一个是viewpager,一个是底部的条和小圆点。Viewpager存在于v4包下,因此可兼容到Android1.6。底部的条和小圆点放在一个线性布局中,让放在viewpager的底部,同时文字和圆点为中心位置。这里特别说一下小圆点的实现。小圆点使用shape图做出来的。由于无法再布局文件中获取圆点的个数,因此可以在布局文件中放置一个LinearLayout,然后在java代码中将view对象向该LinearLayout中添加。同时将白点和黑点的状态选择器设置为view的背景。
2.接下来是viewpager的编写。编写viewpager的关键是写适配器。写一个类继承PagerAdapter,重写其中的方法。Viewpager默认是加载三张图片,屏幕中间一张,屏幕左边和屏幕右边各一张。我们希望轮播图能够循环的播放,因此可以给getcount返回一个足够大的值,初始化轮播图时,将轮播图的初始位置设置在中间,这样就可以实现循环播放。当我们把getcount返回值设为一个很大的值时,在instantiateItem中也要对position进行判断。传入的的position是一个极大的值,但是图片的数量确实有限的,因此可以对position取余,这样就可以把position的位置和图片的数量对应起来。
3.实现自动播放需要用到消息机制,间隔三秒调用显示下一张图片的方法。显示下一张图片是调用viewpager的setCurrentItem,传入下一个图片的item数。手指滑动时viewpager自身就有的功能,因此不需要再定义。
4.最后要实现的功能是,viewpager底部的文字和小圆点跟随图片变化。这时候可以设定一个viewpager的监听事件,当图片发生改变时改变textview的值。然后遍历linearlayout的子view(子view中存发的是小圆点),当圆点的序列号和图片的序列号一直是,则选中圆点。当然,这里同样要对position取余,将position转化到于图片大小一致的范围。
主界面的实现:
<?xmlversion="1.0"encoding="utf-8"?> <RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.advertisement.MainActivity"> <android.support.v4.view.ViewPager android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="150dp"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignBottom="@id/view_pager" android:background="@color/trans_balck" android:gravity="center" android:orientation="vertical" android:padding="5dp"> <TextView android:id="@+id/tv_desc" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="图片描述" android:textColor="@android:color/white"/> <LinearLayout android:id="@+id/ll_dots" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"></LinearLayout> </LinearLayout> </RelativeLayout>
状态选择器
<?xmlversion="1.0"encoding="utf-8"?> <selectorxmlns:android="http://schemas.android.com/apk/res/android"> <itemandroid:state_selected="true"android:drawable="@drawable/shape_dot_select"/> <itemandroid:drawable="@drawable/shape_dot_normal"/> </selector>
shape图的绘制
<?xmlversion="1.0"encoding="utf-8"?> <shapexmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solidandroid:color="@color/trans_balck"/> </shape> <节省空间,两个写下一起> <?xmlversion="1.0"encoding="utf-8"?> <shapexmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solidandroid:color="@android:color/white"/> </shape>
主程序中的业务逻辑
importandroid.os.Bundle; importandroid.os.Handler; importandroid.support.v4.view.ViewPager; importandroid.support.v7.app.AppCompatActivity; importandroid.util.Log; importandroid.view.View; importandroid.widget.LinearLayout; importandroid.widget.TextView; publicclassMainActivityextendsAppCompatActivity{ privatestaticfinalStringTAG="MainActivity"; privateint[]imageResids={R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e}; privateString[]desc={ "巩俐不低俗,我就不能低俗", "扑树又回来啦!再唱经典老歌引万人大合唱", "揭秘北京电影如何升级", "乐视网TV版大派送", "热血屌丝的反杀" }; privateLinearLayoutll_dots; privateTextViewtv_desc; privateViewPagerviewpager; privatestaticfinalintSHOW_NEXT_PAGE=0; privateHandlerhandler=newHandler(); @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ll_dots=(LinearLayout)findViewById(R.id.ll_dots); tv_desc=(TextView)findViewById(R.id.tv_desc); viewpager=(ViewPager)findViewById(R.id.view_pager); viewpager.setAdapter(newBannerAapter(imageResids)); viewpager.setOnPageChangeListener(listener); initDot(); changeDotandDesc(0); viewpager.setCurrentItem(viewpager.getAdapter().getCount()/2); handler.postDelayed(mRunnable,3000); } RunnablemRunnable=newRunnable(){ @Override publicvoidrun(){ shownextpage(); } }; /**初始化小圆点*/ privatevoidinitDot(){ for(inti=0;i<imageResids.length;i++){ int_5dp=dp2px(5); LinearLayout.LayoutParamsparams=newLinearLayout.LayoutParams(_5dp,_5dp); params.leftMargin=_5dp; Viewdot=newView(this); dot.setLayoutParams(params); dot.setBackgroundResource(R.drawable.select_dot); ll_dots.addView(dot); } } /**将pd数据转化为px数据*/ privateintdp2px(intpd){ floatdesity=getResources().getDisplayMetrics().density; return(int)(pd*desity+0.5f); } ViewPager.OnPageChangeListenerlistener=newViewPager.OnPageChangeListener(){ @Override publicvoidonPageScrolled(intposition,floatpositionOffset,intpositionOffsetPixels){ } @Override publicvoidonPageSelected(intposition){ changeDotandDesc(position); } @Override publicvoidonPageScrollStateChanged(intstate){ } }; publicvoidchangeDotandDesc(intposition){ position=position%ll_dots.getChildCount(); tv_desc.setText(desc[position]); for(inti=0;i<ll_dots.getChildCount();i++){ Log.i(TAG,"changeDotandDesc:"+i+""+position); ll_dots.getChildAt(i).setSelected(i==position); } } privatevoidshownextpage(){ intcurrenItem=viewpager.getCurrentItem(); viewpager.setCurrentItem(currenItem+1); handler.postDelayed(mRunnable,3000); } }
适配器的编写:
importandroid.support.v4.view.PagerAdapter; importandroid.view.View; importandroid.view.ViewGroup; importandroid.widget.ImageView; /** *Createdbyhuangon2016/11/22. */ publicclassBannerAapterextendsPagerAdapter{ privateint[]imageResIds; publicBannerAapter(int[]imageResIds){ this.imageResIds=imageResIds; } @Override publicintgetCount(){ returnimageResIds.length*10000*100; } @Override publicbooleanisViewFromObject(Viewview,Objectobject){ returnview==object; } @Override publicObjectinstantiateItem(ViewGroupcontainer,intposition){ ImageViewimageview=newImageView(container.getContext()); position=position%imageResIds.length; imageview.setBackgroundResource(imageResIds[position]); container.addView(imageview); returnimageview; } @Override publicvoiddestroyItem(ViewGroupcontainer,intposition,Objectobject){ container.removeView((ImageView)object); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。