软件编程
位置:首页>> 软件编程>> Android编程>> Android自定义View实现BMI指数条

Android自定义View实现BMI指数条

作者:tyktfj0910  发布时间:2021-08-28 18:12:12 

标签:Android,View,BMI

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

Android自定义View实现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的宽高,关于具体设置,可以参考鸿洋大神的相关说明:

https://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");

然后就达到了预期的效果,代码有点乱~

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com