Welcome 微信登录

首页 / 移动开发 / Android / Android自定义View实现BMI指数条

最近项目需要,需要做一个BMI指数的指示条,先上效果图:


BMI指数从18到35,然后上面指示条的颜色会随着偏移量的变化而改变,数字显示当前的BMI指数,下面的BMI标准也是根据不同数值的范围来判断的。考虑到这个view的特殊性,最后采用的是自定义的view来完成的。
1.页面布局:

 <LinearLayoutandroid: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的宽高,关于具体设置,可以参考鸿洋大神的相关说明:
http://www.jb51.net/article/86061.htm

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");
然后就达到了预期的效果,代码有点乱~
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。