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

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

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

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

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

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

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

最近项目需要,需要做一个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之圆形进度条总结

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

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

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

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

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

Android自定义view之圆形进度条

本节介绍自定义view-圆形进度条 思路: 根据前面介绍的自定义view内容可拓展得之: 1:新建类继承自View 2:添加自定义view属性 3:重写onDraw(Canvas canvas) 4:实现功能 下面上代码 1.自定义view代码: public class CustomView extends View { //背景圆环颜色 private int circleColor; //进度条颜色&字体颜色(为了美观,所以设计字体颜色和进度条颜色值一致) private int seco

Android自定义View实现左右滑动选择出生年份_Android

自定义view的第三篇,模仿的是微博运动界面的个人出生日期设置view,先看看我的效果图: 支持设置初始年份,左右滑动选择出生年份,对应的TextView的值也会改变.这个动画效果弄了好久,感觉还是比较生硬,与微博那个还是有点区别.大家有改进的方案,欢迎一起交流. 自定义View四部曲,这里依旧是这个套路,看看怎么实现的. 1.自定义view的属性: 在res/values/ 下建立一个attrs.xml , 在里面定义我们的属性以及声明我们的整个样式. <?xml version="1.

Android自定义View实现左右滑动选择出生年份

自定义view的第三篇,模仿的是微博运动界面的个人出生日期设置view,先看看我的效果图: 支持设置初始年份,左右滑动选择出生年份,对应的TextView的值也会改变.这个动画效果弄了好久,感觉还是比较生硬,与微博那个还是有点区别.大家有改进的方案,欢迎一起交流. 自定义View四部曲,这里依旧是这个套路,看看怎么实现的. 1.自定义view的属性: 在res/values/ 下建立一个attrs.xml , 在里面定义我们的属性以及声明我们的整个样式. <?xml version="1.

Android自定义View之使用贝塞尔曲线实现流量进度条

第一次写带图片的博客,多少还是有点紧张,效果不好,请将就着看,前面的图是今天要写的控件的效果图,元素不多,分别是一个按钮和一个自定义的控件. 在此以前,我看过许多的书,比如<Android群英传>.<第一行代码>等,也看了很多大神的博客,但是即便是这样,当我看到这么多代码的时候,一直都没有真正的动手去敲过这些代码,以至于我总是觉得自定义View是一个多么高深莫测的技术,我们这些小白是难以触及的,但是当昨晚看了一篇鸡汤之后,觉得人还是要学会专注,要耐得住寂寞,要沉得住气.所以在未来的