Android自定义圆点指示器
程序员文章站
2022-06-16 20:32:08
本文实例为大家分享了android自定义圆点指示器的具体代码,供大家参考,具体内容如下先上效果图大概思路就是自定义view 从左至右绘制圆点 然后在viewpager的onpagechangelist...
本文实例为大家分享了android自定义圆点指示器的具体代码,供大家参考,具体内容如下
先上效果图
大概思路就是自定义view 从左至右绘制圆点 然后在viewpager的onpagechangelistener中设置当前页面的圆点
下面是代码
先定义属性
<resources> <attr name="selectedcolor" format="color"/> <attr name="unselectedcolor" format="color"/> <declare-styleable name="indicator"> <attr name="selectedcolor"/> <attr name="unselectedcolor"/> </declare-styleable> </resources>
接下来是自定义的view
public class indicator extends view{ private static final int default_total_index = 5; private static final int default_current_index = 0; private static final int default_circle_distance = 40; private static final int default_circle_radius = 8; private static final int default_circle_selected_radius = 11; private int selectedcolor; private int unselectedcolor; private int currentindex; private int totalindex; private paint paint; private int startx; private int startselectedy; private int starty; private int centrex; public indicator(context context) { this(context,null); } public indicator(context context, attributeset attrs) { this(context, attrs,0); } public indicator(context context, attributeset attrs, int defstyleattr) { super(context, attrs, defstyleattr); typedarray typedarray = context.gettheme().obtainstyledattributes(attrs,r.styleable.indicator,defstyleattr,0); selectedcolor = typedarray.getcolor(r.styleable.indicator_selectedcolor, color.ltgray); unselectedcolor = typedarray.getcolor(r.styleable.indicator_unselectedcolor,color.white); typedarray.recycle(); totalindex = default_total_index; currentindex = default_current_index; paint = new paint(); }
从typedarray中获取自定义的属性,totalindex是总的圆点个数,currentindex是当前页面的圆点
接下来是重写的ondraw()方法
@override protected void ondraw(canvas canvas) { super.ondraw(canvas); centrex = getwidth() / 2; startselectedy = getheight() / 2 - default_circle_selected_radius; starty = getheight() / 2 - default_circle_radius; if (totalindex % 2 == 0){ startx = centrex - (int)(1.0 * (totalindex - 1)/2 * default_circle_distance); }else{ startx = centrex - totalindex / 2 * default_circle_distance; } paint.setantialias(true); paint.setcolor(unselectedcolor); int tempx = startx; for(int i = 0 ; i < totalindex ; i++ ){ rectf rectf = new rectf(tempx - default_circle_radius,starty, tempx + default_circle_radius,starty + 2 * default_circle_radius); if (i == currentindex) { paint.setcolor(selectedcolor); rectf = new rectf(tempx - default_circle_selected_radius,startselectedy, tempx + default_circle_selected_radius,startselectedy + 2 * default_circle_selected_radius); } canvas.drawoval(rectf,paint); if (paint.getcolor() == selectedcolor) paint.setcolor(unselectedcolor); tempx += default_circle_distance; } }
因为当前页面的圆点和未选中页面的圆点要设置不同的大小 所以分别设置每个圆点的坐标 然后用for循环绘制圆点
这里有一点要注意 new rectf() 的四个参数分别是圆点外面的矩形的左上角的x,y和右下角的x,y
接下来是设置当前页面的圆点的方法
public void setcurrentindex(int currentindex){ //if (currentindex < 0) // currentindex += totalindex ; //if (currentindex > totalindex - 1) // currentindex %= totalindex; this.currentindex = currentindex; invalidate(); }
注释里的代码是当页面可以循环的时候设置的
接下来是设置总的圆点个数的方法
public void settotalindex(int totalindex){ int oldtotalindex = this.totalindex; if (totalindex < 1) return; if (totalindex < oldtotalindex){ if (currentindex == totalindex ) currentindex = totalindex - 1; } this.totalindex = totalindex; invalidate(); }
当删除圆点的时候 如果currentindex是最后一个 让currentindex向前移动
接下来是重写的onmeasure()方法
@override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { setmeasureddimension(measurewidth(widthmeasurespec),measureheight(heightmeasurespec)); } private int measureheight(int measurespec){ int result; int specmode = measurespec.getmode(measurespec); int specsize = measurespec.getsize(measurespec); int desired = default_circle_selected_radius * 2 + getpaddingbottom() + getpaddingtop(); if(specmode == measurespec.exactly) { result = math.max(desired,specsize); }else{ if(specmode == measurespec.at_most){ result = math.min(desired,specsize); } else result = desired; } return result; } private int measurewidth(int measurespec){ int result; int specmode = measurespec.getmode(measurespec); int specsize = measurespec.getsize(measurespec); int desired = (totalindex - 1) * default_circle_distance + default_circle_selected_radius * 2 + getpaddingleft() + getpaddingright(); if(specmode == measurespec.exactly) { result = math.max(desired,specsize); }else{ if(specmode == measurespec.at_most){ result = math.min(desired,specsize); }else result = desired; } return result; }
下面是mainactivity的布局代码,很简单
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.lzh123.learnviewpager.mainactivity"> <android.support.v4.view.viewpager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent"/> <com.example.lzh123.learnviewpager.indicator app:selectedcolor="#ffffff" app:unselectedcolor="#c7c7c7" android:id="@+id/indicator" android:layout_centerinparent="true" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </relativelayout>
下面是mainactivity的代码
public class mainactivity extends appcompatactivity { view layout1,layout2,layout3; viewpager viewpager; indicator indicator; list<view> viewlist; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); viewpager = (viewpager) findviewbyid(r.id.viewpager); layoutinflater inflater = getlayoutinflater(); layout1 = inflater.inflate(r.layout.layout1,null); layout2 = inflater.inflate(r.layout.layout2,null); layout3 = inflater.inflate(r.layout.layout3,null); viewlist = new arraylist<>(); viewlist.add(layout1); viewlist.add(layout2); viewlist.add(layout3); indicator = (indicator) findviewbyid(r.id.indicator); indicator.settotalindex(viewlist.size()); pageradapter pageradapter = new pageradapter() { @override public int getcount() { return viewlist.size(); } @override public void destroyitem(viewgroup container, int position, object object) { container.removeview(viewlist.get(position)); } @override public object instantiateitem(viewgroup container, int position) { container.addview(viewlist.get(position)); return position; } @override public boolean isviewfromobject(view view, object object) { return view == viewlist.get(integer.parseint(object.tostring())); } }; viewpager.setadapter(pageradapter); viewpager.setonpagechangelistener(new pagechangelistener()); } public class pagechangelistener implements viewpager.onpagechangelistener{ @override public void onpageselected(int position) { indicator.setcurrentindex(position); } @override public void onpagescrollstatechanged(int state) { } @override public void onpagescrolled(int position, float positionoffset, int positionoffsetpixels) { } }
viewpager里添加了三个空页面 然后设置指示器的圆点个数,最后在viewpager的onpagechangelistener中设置当前的 页面的圆点。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。