首页 > 系统 > Android > 正文

Android绘图基本用法Demo

2019-11-08 00:14:03
字体:
来源:转载
供稿:网友

Android绘图是开发中比较常用的功能,虽然我用的少(层次不够^O^ ),对绘图的基本用法,适当记录一下。

Android绘图用到的两个重要的类是:

Paint.class(画笔)Canvas.class (画布)

View绘图分三个重要步骤:

Measure 测量Layout 布局Draw 绘制

知道了这些,就开始我们的demo吧。

Demo介绍:血糖含量在不同日期的变化折线图。

先上效果图:

这里写图片描述

xml布局:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/color_white"> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="200dp" android:layout_margin="10dp" card:cardBackgroundColor="@color/color_blue" card:cardCornerRadius="5dp" card:cardElevation="1dp" card:cardMaxElevation="1dp" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/tv_health_data_bloodsugar" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:layout_marginTop="5dp" android:text="血糖 6.5mmol/L" android:textColor="@android:color/white" android:textSize="16sp"/> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingLeft="10dp"> <Button android:id="@+id/btn_health_item_day" style="@style/item_health_data_buttonStyle" android:text="日"/> <Button android:id="@+id/btn_health_item_week" style="@style/item_health_data_buttonStyle" android:text="周"/> <Button android:id="@+id/btn_health_item_month" style="@style/item_health_data_buttonStyle" android:text="月"/> <Button android:id="@+id/btn_health_item_year" style="@style/item_health_data_buttonStyle" android:text="年" /> </LinearLayout> <com.doctor.comonent.MyHealthDataView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="5dp" /> </LinearLayout> </android.support.v7.widget.CardView></LinearLayout>

自定义绘制View

import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Path;import android.util.AttributeSet;import android.view.View;import com.doctor.util.LogUtil;import com.doctor.util.NumberUtil;/** * Created by hgb * Date 2016/8/30 17:01. * Description : 自定义健康数据的view,用于用户健康数据的展示 */public class MyHealthDataView extends View { PRivate Paint paint; //画笔 private int width; //视图宽度 private int height; //视图的高度 //坐标原点位置 private int originX = 50; private int originY = 400; //画笔颜色 private int paint_color_grey = Color.rgb(118, 188, 240); //表示最下面的日期. private String[] arrStr = new String[]{"19", "20", "21", "22", "23", "24", "25"}; //对应日期不同的血糖值.空腹血糖正常范围是 3.9-6.1mmol/L(70-110mg/dL),正常餐后两小时血糖范围是 3.9-7.8mmol/L(70-140mg/dL) private Float[] arrFloat = new Float[]{1.9f, 5.4f, 6.1f, 4.0f, 5.5f, 2.5f, 4.8f}; private float fSpace; //水平方向x轴的间距. private int size; //代表需要绘制的数据量 private Float[] arrScale; //点的高度占整体高度的比例 public MyHealthDataView(Context context) { super(context); initPaint(); } public MyHealthDataView(Context context, AttributeSet attrs) { super(context, attrs); initPaint(); } public MyHealthDataView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initPaint(); } /** * 开始进行绘制 */ public void setData() { postInvalidate(); } /** * 初始化view */ private void initPaint() { //创建画笔. paint = new Paint(); paint.setColor(paint_color_grey); //设置画笔宽度 paint.setStrokeWidth(3); //设置画笔抗锯齿 paint.setAntiAlias(true); } /** * 测量 * * @param widthMeasureSpec 宽 * @param heightMeasureSpec 高 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); width = MeasureSpec.getSize(widthMeasureSpec); LogUtil.e("width", width + ""); height = MeasureSpec.getSize(heightMeasureSpec) - 60; LogUtil.e("height", height + ""); // originX = 15; originY = height; } /** * 在ViewGroup位置中所处的位置 * * @param changed 当前View的大小和位置改变了 * @param left 左部位置(相对于父视图) * @param top 顶部位置(相对于父视图) * @param right 右部位置(相对于父视图) * @param bottom 底部位置(相对于父视图) */ @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); } /** * 绘制 * * @param canvas 画布 */ @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //绘制Y轴 drawAxisY(canvas, paint); //绘制X轴坐标线(及下面的数据) drawAxisScaleMarkX(canvas, paint); //绘制水平的浅线 drawHorizontalLine(canvas, paint); //绘制数据点,根据点连线 drawPoint(canvas, paint); //根据点连线 drawLine(canvas, paint); } /** * 绘制横坐标轴(X轴) */ private void drawAxisX(Canvas canvas, Paint paint) { //画竖轴(Y) canvas.drawLine(originX, originY, originX, originY - height, paint);//参数说明:起始点左边x,y,终点坐标x,y,画笔 } /** * 绘制纵坐标轴(Y轴) */ private void drawAxisY(Canvas canvas, Paint paint) { //画横轴(X) canvas.drawLine(originX, originY, width - originX, originY, paint); } /** * 绘制X轴刻度线及下面的数据 * * @param canvas * @param paint */ private void drawAxisScaleMarkX(Canvas canvas, Paint paint) { paint.setTextSize(40); size = arrStr.length; //文本数量 int axisX = originX - 5; //x轴距离,-5是为了让坐标点和数据对齐 int axisY = originY + 40; //Y轴坐标刻度值 fSpace = ((float) width - 2 * originX) / (size - 1) - 3.0f;//Y轴数据之间的间距 for (int i = 0; i < size; i++) { canvas.drawText(arrStr[i], axisX + fSpace * i, axisY, paint); } } /** * 绘制数据点 * * @param canvas * @param paint */ private void drawPoint(Canvas canvas, Paint paint) { //重写选取给paint赋值属性 paint.setColor(Color.WHITE); //设置画笔颜色 paint.setStyle(Paint.Style.STROKE); //设置画笔模式为描边 paint.setStrokeWidth(10f); //设置画笔宽度为10px arrScale = NumberUtil.getArrScale(arrFloat); //获取数组中每个值与最大值的比 //绘制一组点,坐标位置由float数组指定 for (int i = 0; i < size; i++) { canvas.drawPoint(originX + fSpace * i, (height - height * arrScale[i] + 10), paint); } } /** * 绘制水平横线 * * @param canvas * @param paint */ private void drawHorizontalLine(Canvas canvas, Paint paint) { int unit = -70; canvas.drawLines(new float[]{ originX, originY + unit, width - originX, originY + unit, originX, originY + unit * 2, width - originX, originY + unit * 2, originX, originY + unit * 3, width - originX, originY + unit * 3, originX, originY + unit * 4, width - originX, originY + unit * 4, originX, originY + unit * 5, width - originX, originY + unit * 5 }, paint); } /** * 根据点来连线 * * @param canvas * @param paint */ private void drawLine(Canvas canvas, Paint paint) { paint.setStrokeWidth(5f); //设置画笔宽度为10px Path path = new Path(); // 创建Path path.moveTo(originX, height - height * arrScale[0] + 10); // moveTo 把动作的起点移动到第一个点 for (int i = 1; i < size; i++) { path.lineTo(originX + fSpace * i, height - height * arrScale[i] + 10); // lineTo 把剩下的点连接起来. } canvas.drawPath(path, paint); // 绘制Path }}

代码中用到的一个工具类NumberUtil

/** * Created by hgb * Date 2016/8/31 15:16. * Description : 处理数值的一些逻辑 */public class NumberUtil { /** * 获取一个float数组中的最大值 * * @param arrFloat float类型数组 * @return 返回数值中的最大值. */ public static float getMaxNum(Float[] arrFloat) { int i; float max; int size = arrFloat.length; max = arrFloat[0]; for (i = 0; i < size; i++) { if (arrFloat[i] > max) // 判断最大值 max = arrFloat[i]; } return max; } /** * 获取数组中每个值与最大值的比 * * @param arrFloat float类型数组 * @return 比例 */ public static Float[] getArrScale(Float[] arrFloat) { float maxNum = getMaxNum(arrFloat); int i; int size = arrFloat.length; Float[] arrScale = new Float[size]; for (i = 0; i < size; i++) { arrScale[i] = arrFloat[i] / maxNum; } return arrScale; }}

这样,一个图表基本上就完成了。 Android中有很多复杂的绘图,paint和canvas的方法也多种多样,具体参见api详细文档。

Paint

Canvas


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表