Android view自定义带文字带进度的控件
程序员文章站
2023-11-27 12:50:28
目标:自定义一个带文字带进度的控件,具体内容如下
效果图:
不啰嗦先看东西:
步骤分析
提取自定义属性
//提供对外暴露的属性,如有不够自己扩...
目标:自定义一个带文字带进度的控件,具体内容如下
效果图:
不啰嗦先看东西:
步骤分析
提取自定义属性
//提供对外暴露的属性,如有不够自己扩展 <declare-styleable name="descprogressview"> <attr name="dpv_text_normal_color" format="color" /> <attr name="dpv_text_seleced_color" format="color" /> <attr name="dpv_text_size" format="dimension" /> <attr name="dev_progress_bg_color" format="color" /> <attr name="dev_progress_small_circle_color" format="color" /> <attr name="dev_progress_big_circle_color" format="color" /> </declare-styleable>
解析自定义属性
private void initattrs(context context, @nullable attributeset attrs, int defstyleattr) { typedarray typedarray = context.gettheme().obtainstyledattributes(attrs, r.styleable.descprogressview, defstyleattr, r.style.def_descprogressviewstyle); int indexcount = typedarray.getindexcount(); for (int i = 0; i < indexcount; i++) { int attr = typedarray.getindex(i); switch (attr) { case r.styleable.descprogressview_dpv_text_normal_color: textnormalcolor = typedarray.getcolor(attr, color.black); break; case r.styleable.descprogressview_dpv_text_seleced_color: textselectedcolor = typedarray.getcolor(attr, color.black); break; case r.styleable.descprogressview_dpv_text_size: dpvtextsize = typedarray.getdimensionpixelsize(attr, 0); break; case r.styleable.descprogressview_dev_progress_bg_color: dpvprogressbgcolor = typedarray.getcolor(attr, color.black); break; case r.styleable.descprogressview_dev_progress_small_circle_color: dpvsmallciclecolor = typedarray.getcolor(attr, color.black); break; case r.styleable.descprogressview_dev_progress_big_circle_color: dpvbigcirclecolor = typedarray.getcolor(attr, color.black); break; } } typedarray.recycle(); }
测量ui图的比例(包含图标大小比例,位置比例)
//这里大家可以根据自己的习惯来,我习惯用view的尺寸当做参照,来约束界面的view,各有利弊,也可以暴露出属性设置具体的dp值,根据比例的话,调整好比例后,所有的绘制内容会统一约束 private static final float scale_of_progress_height = 70.f / 120; private static final float scale_of_top_and_bottom_padding = 10.f / 120; private static final float scale_of_left_and_right_padding = 20.f / 120; private static final float scale_of_text_desc_container = 50.f / 120; private static final float scale_of_big_circle_height = 22.f / 120; private static final float scale_of_small_circle_height = 16.f / 120; private static final float scale_of_line_height = 4.f / 120; private static final float def_view_height = 120.f;
提取绘制的各个元素的位置属性坐标等
这个view的唯一要提前确定的就是文字的位置,文字的位置确定需要知道所有文字的长度,左右间距,计算出中间的白色间隔
代码如下
/** * 获取文字在画布中的位置 */ private void getdesctextregonpoint() { for (int i = 0; i < descs.size(); i++) { point textregonpoint = new point(); int sumx = 0; //非常重要:计算各个文字在view中的具体坐标,体会下这个二级for循环,子循环是确定每个描述文本的位置 for (int j = 0; j < i; j++) { point tempsum = alldesctextpoints.get(j); sumx += tempsum.x; } sumx += i * gettextdescspace(); textregonpoint.x = sumx + leftandrightpadding; textregonpoint.y = dpviewheight - topandbottompadding - textdesccontainerheight / 2; textpoints4draw.add(textregonpoint); } }
/** * 获取文字的间距 * * @return 获取文字的间距 */ private float gettextdescspace() { float alldescwith = 0; for (point tempdesc : alldesctextpoints) { alldescwith += tempdesc.x; } int textcontainerw = (int) (dpviewwidth - leftandrightpadding * 2 - alldescwith); if (descs != null && descs.size() > 1) { int spacecount = descs.size() - 1; return textcontainerw * 1.f / spacecount; } return 0; }
绘制
我们在view测量确定了尺寸完毕之后,直接绘制即可
@override protected void onsizechanged(int w, int h, int oldw, int oldh) { // 确定各个比例的大小 super.onsizechanged(w, h, oldw, oldh); dpviewheight = h; dpviewwidth = w; progresscontainerheight = (int) (scale_of_progress_height * dpviewheight); topandbottompadding = (int) (scale_of_top_and_bottom_padding * dpviewheight); leftandrightpadding = (int) (scale_of_left_and_right_padding * dpviewheight); textdesccontainerheight = (int) (scale_of_text_desc_container * dpviewheight); smallcircleradio = (int) (scale_of_small_circle_height * dpviewheight / 2); bigcircleradio = (int) (scale_of_big_circle_height * dpviewheight / 2); lineheight = (int) (scale_of_line_height * dpviewheight); // 获取各个部分所需要的约束坐标 getdesctextwidthandheight(); getdesctextregonpoint(); getbglinerectf(); getbgcirclepoints(); getselectedrectf(); getcolorfullrectf(); getgrayrectf(); }
@override protected void ondraw(canvas canvas) { super.ondraw(canvas); drawdesctext(canvas); drawbgline(canvas); drawselectedline(canvas); drawgrayrectf(canvas); drawselectedcircles(canvas); } //绘制部分的代码就是canvas 的api的使用,没有什么技术含量. //最后暴露给外面设置数据的接口 public void setprogressdescs(list<string> descs, int currentselectposition) { this.currentselectposition = currentselectposition; if (descs != null && descs.size() > 1) { this.descs.clear(); this.descs.addall(descs); this.alldesctextpoints.clear(); invalidate(); } }
源代码下载地址https://github.com/guofeilong/descpbview来个star就更好了谢谢!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 简单实现Android本地音乐播放器