Android自定义View实现BMI指数条
程序员文章站
2024-03-02 13:22:40
最近项目需要,需要做一个bmi指数的指示条,先上效果图:
bmi指数从18到35,然后上面指示条的颜色会随着偏移量的变化而改变,数字显示当前的bmi指数,下面的...
最近项目需要,需要做一个bmi指数的指示条,先上效果图:
bmi指数从18到35,然后上面指示条的颜色会随着偏移量的变化而改变,数字显示当前的bmi指数,下面的bmi标准也是根据不同数值的范围来判断的。考虑到这个view的特殊性,最后采用的是自定义的view来完成的。
1.页面布局:
<linearlayout android:layout_width="fill_parent" android:layout_height="100dp" android:layout_marginleft="5dp" android:layout_marginright="5dp" android:layout_margintop="50dp" android:background="@color/white" android:orientation="horizontal" > <textview style="@style/w_wrap_h_wrap" android:layout_margintop="@dimen/login_hei" android:text="@string/bmi_text" android:textcolor="@color/gray" android:textsize="@dimen/login_edit_border_margin" /> <com.jxj.jwotchhelper.view.newbmiview android:id="@+id/bmiview" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </linearlayout>
左边是bmi文字,右边是自定义的view,没啥说的,下面是view的具体过程:
2.代码实现:
新建一个newbmiview类,并且继承自view类,然后添加构造方法;
public class newbmiview extends view { /** 分段颜色 */ private static final int[] section_colors = { color.rgb(255, 204, 47), color.green, color.red }; /** 画笔 */ private paint mpaint; private paint textpaint; private paint drawablepaint; private paint drawablebmipaint; private paint bmitextpaint; private int bmiwidth, mwidth, mheight, widthsum; private double value; private double i; private double bmi; private float valuewidth; private string bmitext; // 定义计算颜色的参数 private int x, y, z; public newbmiview(context context) { super(context); initviews(context); } public newbmiview(context context, attributeset attrs) { super(context, attrs); initviews(context); } public newbmiview(context context, attributeset attrs, int defstyleattr) { super(context, attrs, defstyleattr); initviews(context); } private void initviews(context context) { }
然后就是重写onmeasure与ondraw这两个方法,通过onmeasure这个方法获取到了view的宽高,关于具体设置,可以参考鸿洋大神的相关说明:
protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { int widthspecmode = measurespec.getmode(widthmeasurespec); int widthspecsize = measurespec.getsize(widthmeasurespec); int heightspecmode = measurespec.getmode(heightmeasurespec); int heightspecsize = measurespec.getsize(heightmeasurespec); if (widthspecmode == measurespec.exactly || widthspecmode == measurespec.at_most) { widthsum = widthspecsize; } else { widthsum = 0; } if (heightspecmode == measurespec.at_most || heightspecmode == measurespec.unspecified) { mheight = diptopx(15); } else { mheight = heightspecsize; } setmeasureddimension(widthsum, mheight); }
然后重点就是ondraw这个方法了:
// 画自定义的渐变条 mpaint = new paint(); // 去除锯齿 mpaint.setantialias(true); // 自定义圆角的弧度 int round = mheight / 20; // 新建矩形 rectf rectbg = new rectf(bmiwidth, mheight - (mheight * 1 / 2), mwidth + bmiwidth, mheight - (mheight * 2 / 5)); // 设置渐变色 // clamp重复最后一个颜色至最后 // mirror重复着色的图像水平或垂直方向已镜像方式填充会有翻转效果 // repeat重复着色的图像水平或垂直方向 lineargradient shader = new lineargradient(bmiwidth, mheight - (mheight * 1 / 2), mwidth + bmiwidth, mheight - (mheight * 2 / 5), section_colors, null, shader.tilemode.mirror); mpaint.setshader(shader); // rect:rectf对象。x方向上的圆角半径。ry:y方向上的圆角半径。paint:绘制时所使用的画笔。 canvas.drawroundrect(rectbg, round, round, mpaint); // 画下面的小箭头 drawablepaint = new paint(); drawablepaint.setantialias(true); bitmap arrowbitmap = bitmapfactory.decoderesource(getresources(), r.drawable.arrow_up); canvas.drawbitmap(arrowbitmap, mwidth * 2 / 17 + bmiwidth, mheight - (mheight * 2 / 5) + 5, drawablepaint); canvas.drawbitmap(arrowbitmap, mwidth * 7 / 17 + bmiwidth, mheight - (mheight * 2 / 5) + 5, drawablepaint); canvas.drawbitmap(arrowbitmap, mwidth * 12 / 17 + bmiwidth, mheight - (mheight * 2 / 5) + 5, drawablepaint); // 画下方的文字 string text = "偏瘦"; rect textbounds = new rect(); textpaint = new paint(); textpaint.setantialias(true); textpaint.setcolor(color.gray); textpaint.settextsize(30); // 获取字体的高宽 textpaint.gettextbounds(text, 0, text.length(), textbounds); float textwidth = textbounds.width(); float textheight = textbounds.height(); canvas.drawtext("偏瘦", (mwidth * 2 / 17) / 2 - textwidth / 2 + bmiwidth, mheight * 7 / 10 + textheight / 2 + 10, textpaint); canvas.drawtext("标准", (mwidth * 2 / 17) + (mwidth * 5 / 17) / 2 - textwidth / 2 + bmiwidth, mheight * 7 / 10 + textheight / 2 + 10, textpaint); canvas.drawtext("超重", (mwidth * 7 / 17) + (mwidth * 5 / 17) / 2 - textwidth / 2 + bmiwidth, mheight * 7 / 10 + textheight / 2 + 10, textpaint); canvas.drawtext("肥胖", (mwidth * 12 / 17) + (mwidth * 5 / 17) / 2 - textwidth / 2 + bmiwidth, mheight * 7 / 10 + textheight / 2 + 10, textpaint); // 画上方偏移的小方块 drawablebmipaint = new paint(); drawablebmipaint.setantialias(true); // 设置颜色 // 通过bmi来rgb计算颜色 i = (value - 18) * (34 / 17); if (i >= 0 && i <= 17) { x = (int) ((17 - i) * (255 / 17)); y = 204; z = 47; } if (i > 17 && i <= 34) { x = (int) ((i - 17) * (255 / 17)); y = (int) ((34 - i) * (255 / 17)); z = 0; } drawablebmipaint.setcolor(color.rgb(x, y, z)); system.out.println("颜色值为" + string.valueof(x) + string.valueof(y) + string.valueof(z)); canvas.drawrect(getvalue(), mheight / 6, getvalue() + bmibitmap.getwidth(), bmibitmap.getheight()+mheight / 6, drawablebmipaint); system.out.println("偏移量为" + getvalue()); canvas.drawbitmap(bmibitmap, getvalue(), mheight / 6, drawablepaint); // 画上方偏移的小方块里面的文字 string bmitext = "40.0"; rect bmitextbounds = new rect(); bmitextpaint = new paint(); bmitextpaint.setantialias(true); bmitextpaint.settextsize(35); bmitextpaint.setcolor(color.white); // 获取字体的高宽 bmitextpaint.gettextbounds(bmitext, 0, bmitext.length(), bmitextbounds); canvas.drawtext(bmitext, getvalue() - (bmitextbounds.width() / 2) + bmiwidth, mheight / 3 + (bmitextbounds.height() / 3), bmitextpaint);
其中需要注意的是,这里小方块的颜色值我是根据bmi值大小,算出rgb三原色的渐变值,没有找到系统自带渲染渐变条的方法中,提供的颜色值,所以就用这种方法计算出来,会有一定得误差。
然后就是关于textview,因为自带宽高,所以在绘制textview的时候,需要考虑宽高再绘制。
通过set方法传递参数
public void setbmi(double bmi) { this.value = bmi; // 设置颜色 if (value < 18) { this.value = 18; } else if (value > 35) { this.value = 35; } invalidate(); } public void setbmitext(string bmitext) { this.bmitext = bmitext; }
最后就是在activity中应用了:
bmiview= (newbmiview) getview().findviewbyid(r.id.bmiview); //将bmi指数传递过去 bmiview.setbmi(35); bmiview.setbmitext("35.0");
然后就达到了预期的效果,代码有点乱~
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 基于thinkPHP框架实现留言板的方法
下一篇: mybatisPlus 实现条件查询总结