Android心率热图实现

Android心率热图实现_第1张图片

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Shader;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import com.careeach.sport.R;
import java.util.List;

/**
 * 心率热图
 */
public class HeartRateView extends View {
    private List values;
    private int[] guidesValues;
    private float height;
    private float width;
    private Paint linkLinePoint;
    private Paint shadePoint;
    private Paint xTextPoint;
    private Paint xLintPoint;
    private Paint yTextPoint;

    private float itemHeight;

    //ATTR
    private int attrXTextColor;
    private float attrXTextSize;
    private int attrXLineColor;
    private float attrXLineWidth;
    private int attrYTextColor;
    private float attrYTextSize;
    private float attrLineWidth;
    private int attrLinkLineColor;
    private int attrShadeColor;
    private float attrGuidesTextMarginLeft;
    private float attrGuidesTextMarginRight;
    private float attrPaddingRight;
    private int maxValue; // 最大值
    private float itemWidth;

    private float contentEndY;
    private float contentStartX;


    public HeartRateView(Context context) {
        super(context);
    }

    public HeartRateView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public HeartRateView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);

    }

    public HeartRateView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HeartRateView);
        attrLineWidth = typedArray.getDimension(R.styleable.HeartRateView_hr_lineWidth, dip2px(0.5f));
        attrLinkLineColor = typedArray.getColor(R.styleable.HeartRateView_hr_linkLineColor, Color.RED);
        attrShadeColor = typedArray.getColor(R.styleable.HeartRateView_hr_shadeColor, Color.RED);
        maxValue = typedArray.getInteger(R.styleable.HeartRateView_hr_maxValue, 180);
        attrXTextColor = typedArray.getColor(R.styleable.HeartRateView_hr_xTextColor, Color.GRAY);
        attrXTextSize = typedArray.getDimension(R.styleable.HeartRateView_hr_xTextSize, 20);
        attrXLineColor = typedArray.getColor(R.styleable.HeartRateView_hr_xLineColor, Color.GRAY);
        attrYTextSize = typedArray.getDimension(R.styleable.HeartRateView_hr_yTextSize, 20);
        attrYTextColor = typedArray.getColor(R.styleable.HeartRateView_hr_yTextColor, Color.GRAY);
        attrXLineWidth = typedArray.getDimension(R.styleable.HeartRateView_hr_xLineWidth, dip2px(0.5f));
        attrGuidesTextMarginLeft = typedArray.getDimension(R.styleable.HeartRateView_hr_guidesTextMarginLeft, 20);
        attrGuidesTextMarginRight = typedArray.getDimension(R.styleable.HeartRateView_hr_guidesTextMarginRight, 20);
        attrPaddingRight = typedArray.getDimension(R.styleable.HeartRateView_hr_paddingRight, 20);
        typedArray.recycle();

        linkLinePoint = new Paint();
        linkLinePoint.setColor(attrLinkLineColor);
        linkLinePoint.setStrokeWidth(attrLineWidth);
        linkLinePoint.setStyle(Paint.Style.STROKE);
        linkLinePoint.setAntiAlias(true);

        shadePoint = new Paint();
        shadePoint.setStyle(Paint.Style.FILL);


        xTextPoint = new Paint();
        xTextPoint.setColor(attrXTextColor);
        xTextPoint.setTextSize(attrXTextSize);
        xTextPoint.setAntiAlias(true);

        yTextPoint = new Paint();
        yTextPoint.setColor(attrYTextColor);
        yTextPoint.setTextSize(attrYTextSize);
        yTextPoint.setAntiAlias(true);

        xLintPoint = new Paint();
        xLintPoint.setColor(attrXLineColor);
        xLintPoint.setStrokeWidth(attrXLineWidth);
        xLintPoint.setAntiAlias(true);
        xLintPoint.setStyle(Paint.Style.STROKE);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getMeasuredWidth();
        height = getMeasuredHeight();
        contentEndY = height - measureTextHeight(xTextPoint);
        itemHeight = contentEndY / maxValue;
        contentStartX = attrGuidesTextMarginLeft + yTextPoint.measureText(String.valueOf(maxValue)) + attrGuidesTextMarginRight;
    }

    public static float measureTextHeight(Paint paint) {
        float height = 0f;
        if (null == paint) {
            return height;
        }
        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        height = fontMetrics.descent - fontMetrics.ascent;
        return height;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (guidesValues != null && guidesValues.length > 0) {
            for (int guidesValue : guidesValues) {
                float x = attrGuidesTextMarginLeft;
                float y = contentEndY - guidesValue * itemHeight;
                canvas.drawText(String.valueOf(guidesValue), x, y, yTextPoint);
            }
        }

        if (values != null && values.size() > 1) {
            Path path = new Path();
            Path pathLine = new Path();
            path.moveTo(contentStartX, contentEndY - values.get(0) * itemHeight);
            pathLine.moveTo(contentStartX, contentEndY - values.get(0) * itemHeight);
            for (int i = 1; i < values.size(); i++) {
                float x = contentStartX + i * itemWidth;
                float y = contentEndY - values.get(i) * itemHeight;
                // 为了美观,计算误差在最后一个点消除
                if (i == values.size() - 1) {
                    x = width - attrPaddingRight;
                }
                path.lineTo(x, y);
                pathLine.lineTo(x, y);
            }
            path.lineTo(width - attrPaddingRight, contentEndY);
            path.lineTo(contentStartX, contentEndY);
            path.lineTo(contentStartX, contentEndY - values.get(0) * itemHeight);
            path.close();
            Shader mShader = new LinearGradient(0, contentEndY, 0, 0, Color.WHITE, attrShadeColor, Shader.TileMode.MIRROR);
            shadePoint.setShader(mShader);
            canvas.drawPath(path, shadePoint);
            canvas.drawPath(pathLine, linkLinePoint);
        }

        // X 轴
        canvas.drawLine(0, contentEndY, width, contentEndY, xLintPoint);
    }

    public void setValues(List values) {
        this.values = values;
        itemWidth = (width - attrPaddingRight - contentStartX) / values.size();
        postInvalidate();
    }

    /**
     * 设置参考值
     *
     * @param values
     */
    public void setGuidesValues(int[] values) {
        this.guidesValues = values;
    }

    private float dip2px(float dpValue) {
        final float scale = getContext().getResources().getDisplayMetrics().density;
        return (dpValue * scale + 0.5f);
    }
}

attrs.xml添加属性


    
    
    
    
    
    
    
    
    
    
    
    
    

你可能感兴趣的:(android)