最近项目需要,需要做一个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 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的宽高,关于具体设置,可以参考鸿洋大神的相关说明:
https://www.oudahe.com/p/17334/
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,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,mWIDth * 12 / 17 + bmiwIDth,drawablePaint); // 画下方的文字 String text = "偏瘦"; Rect textBounds = new Rect(); textPaint = new Paint(); textPaint.setAntiAlias(true); textPaint.setcolor(color.GRAY); textPaint.setTextSize(30); // 获取字体的高宽 textPaint.getTextBounds(text,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,textPaint); canvas.drawText("肥胖",(mWIDth * 12 / 17) + (mWIDth * 5 / 17) / 2 - textWIDth / 2 + bmiwIDth,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,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(),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,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");
然后就达到了预期的效果,代码有点乱~
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。
总结以上是内存溢出为你收集整理的Android自定义View实现BMI指数条全部内容,希望文章能够帮你解决Android自定义View实现BMI指数条所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)