Android自定义View实现BMI指数条_Android

最近项目需要,需要做一个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的宽高,关于具体设置,可以参考鸿洋大神的相关说明:

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");

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索android
, view
BMI
自定义view实现动画、自定义view实现滑动、自定义viewgroup实现、自定义view实现跑马灯、bmi指数,以便于您获取更多的相关知识。

时间: 2024-09-24 14:54:44

Android自定义View实现BMI指数条_Android的相关文章

Android自定义View实现BMI指数条

最近项目需要,需要做一个BMI指数的指示条,先上效果图: BMI指数从18到35,然后上面指示条的颜色会随着偏移量的变化而改变,数字显示当前的BMI指数,下面的BMI标准也是根据不同数值的范围来判断的.考虑到这个view的特殊性,最后采用的是自定义的view来完成的. 1.页面布局: <LinearLayout android:layout_width="fill_parent" android:layout_height="100dp" android:la

Android自定义View实现等级滑动条的实例

Android自定义View实现等级滑动条的实例 实现效果图: 思路: 首先绘制直线,然后等分直线绘制点: 绘制点的时候把X值存到集合中. 然后绘制背景图片,以及图片上的数字. 点击事件down的时候,换小图片为大图片.move的时候跟随手指移动. up的时候根据此时的X计算最近的集合中的点,然后自动吸附回去. 1,自定义属性 <?xml version="1.0" encoding="utf-8"?> <resources> <dec

Android自定义View之圆形进度条式按钮_Android

介绍 今天上班的时候有个哥们问我怎么去实现一个按钮式的进度条,先来看看他需要实现的效果图. 和普通的圆形进度条类似,只是中间的地方有两个状态表示,未开始,暂停状态.而且他说圆形进度的功能已经实现了.那么我们只需要对中间的两个状态做处理就行了. 先来看看实现的效果图: 上面说了我们只需要处理中间状态的变化就可以了,对于进度的处理直接使用了弘洋文章中实现: http://blog.csdn.net/lmj623565791/article/details/43371299 下面开始具体实现. 具体实

Android自定义View之圆形进度条总结

最近撸了一个圆形进度条的开源项目,算是第一次完完整整的使用自定义 View .在此对项目开发思路做个小结,欢迎大家 Star 和 Fork. 该项目总共实现了三种圆形进度条效果 CircleProgress:圆形进度条,可以实现仿 QQ 健康计步器的效果,支持配置进度条背景色.宽度.起始角度,支持进度条渐变 DialProgress:类似 CircleProgress,但是支持刻度 WaveProgress:实现了水波纹效果的圆形进度条,不支持渐变和起始角度配置,如需此功能可参考 CircleP

Android自定义View实现水面上涨效果_Android

实现效果如下: 实现思路: 1.如何实现圆中水面上涨效果:利用Paint的setXfermode属性为PorterDuff.Mode.SRC_IN画出进度所在的矩形与圆的交集实现 2.如何水波纹效果:利用贝塞尔曲线,动态改变波峰值,实现"随着进度的增加,水波纹逐渐变小的效果" 话不多说,看代码. 首先是自定义属性值,有哪些可自定义属性值呢? 圆的背景颜色:circle_color,进度的颜色:progress_color,进度显示文字的颜色:text_color,进度文字的大小:tex

Android自定义View之圆形进度条式按钮

介绍 今天上班的时候有个哥们问我怎么去实现一个按钮式的进度条,先来看看他需要实现的效果图. 和普通的圆形进度条类似,只是中间的地方有两个状态表示,未开始,暂停状态.而且他说圆形进度的功能已经实现了.那么我们只需要对中间的两个状态做处理就行了. 先来看看实现的效果图: 上面说了我们只需要处理中间状态的变化就可以了,对于进度的处理直接使用了弘洋文章中实现: http://blog.csdn.net/lmj623565791/article/details/43371299 下面开始具体实现. 具体实

Android自定义View实现字母导航栏_Android

很多的Android入门程序猿来说对于Android自定义View,可能都是比较恐惧的,但是这又是高手进阶的必经之路,所有准备在自定义View上面花一些功夫,多写一些文章. 思路分析: 1.自定义View实现字母导航栏 2.ListView实现联系人列表 3.字母导航栏滑动事件处理 4.字母导航栏与中间字母的联动 5.字母导航栏与ListView的联动 效果图: 首先,我们先甩出主布局文件,方便后面代码的说明 <!--?xml version="1.0" encoding=&qu

Android自定义View软键盘实现搜索_Android

1. xml文件中加入自定义 搜索view <com.etoury.etoury.ui.view.IconCenterEditText android:id="@+id/search_et" style="@style/StyleEditText" android:hint="搜索景点信息" /> 2. 自定义的   view java文件 IconCenterEditText.java package com.etoury.etou

Android自定义View实现折线图效果_Android

下面就是结果图(每种状态用一个表情图片表示): 一.主页面的布局文件如下: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height=&quo