Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

Android 自定义View练习:雷达图(比重)绘制

$
0
0

这里写图片描述

code:

package com.louisgeek.louiscustomviewstudy;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;

import static android.content.ContentValues.TAG;

/**
 * Created by louisgeek on 2016/10/27.
 */

public class RadarView08 extends View {
    private Paint mPaint;
    private int mViewWidth, mViewHeight,mScreenWidth,mScreenHeight;
    /**
     *文字与边缘点的距离
     */
    private final float mText_ContentDisance = 10;
    /**
     *线的粗细
    */
    private  int mLinesWidth = this.dp2px(1);

    //顺时针  对应的数据
    // private float[] mDataValue={1f,1f,1f,1f,0.8f,0.6f,0.4f,1f,0.4f,1f};//10
    private float[] mDataValue = {1f, 0.1f, 1f, 1f, 0.8f, 0.6f, 0.4f, 0.4f};//8
    //private float[] mDataValue={1f,0.8f,0.6f,0.4f,1f,0.4f};//6
    // private float[] mDataValue={1f,0.8f,0.6f,0.4f};//4
    // private float[] mDataValue={1f,1f,1f};//3
    private String[] mDataName = {"豌豆荚", "应用宝", "百度91安卓", "安智市场", "小米应用商店", "OPPO应用商店", "魅族应用商店", "360手机助手", "华为应用市场", "移动MM商店"};

    /**
     * 最大形状的半径
     */
   private int mRadius = this.dp2px(50);//max
    /**
     * 小圆点半径
     */
    private int mPointRadius = this.dp2px(2);
    private int mPointColor = Color.GRAY;

    private int mContentColor=Color.BLUE;
    private int mLinesColor=Color.LTGRAY;
    private int mTextColor=Color.RED;
    private int mTextSize=this.dp2px(14);
    /**
     * 角度
     */
    private int mDegreesAngle;
    private int mContentAlpha=150;//must in (0-225)
    //点的数量
    private int mPointsCount;

    private Paint mPaintText=new Paint();

    private  Context mContext;

    public RadarView08(Context context) {
        this(context, null);
    }

    public RadarView08(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RadarView08(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext=context;
        TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.RadarView08);
       mLinesWidth = ta.getDimensionPixelOffset(R.styleable.RadarView08_linesWidth, mLinesWidth);
        mRadius = ta.getDimensionPixelOffset(R.styleable.RadarView08_maxCircleRadius, mRadius);
        mPointRadius = ta.getDimensionPixelOffset(R.styleable.RadarView08_pointRadius, mPointRadius);
        mContentColor = ta.getColor(R.styleable.RadarView08_contentColor, mContentColor);
        mPointColor = ta.getColor(R.styleable.RadarView08_pointColor, mPointColor);
        mLinesColor = ta.getColor(R.styleable.RadarView08_linesColor, mLinesColor);
        mContentAlpha = ta.getInteger(R.styleable.RadarView08_contentAlpha, mContentAlpha);
        mTextColor = ta.getColor(R.styleable.RadarView08_titleColor, mTextColor);
        mTextSize = ta.getDimensionPixelOffset(R.styleable.RadarView08_titleTextSize, mTextSize);
        //
        ta.recycle();
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.LTGRAY);
        mPaint.setStrokeWidth(mLinesWidth);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        //
        mPaintText=new Paint();
        mPaintText.setColor(mTextColor);
        mPaintText.setTextSize(mTextSize);
        mPaintText.setAntiAlias(true);
        mPaintText.setStyle(Paint.Style.FILL);


        //must in (0-225)
        mContentAlpha=mContentAlpha<0?0:mContentAlpha;
        mContentAlpha=mContentAlpha>255?255:mContentAlpha;
        Log.d(TAG, "init: mContentAlpha:"+mContentAlpha);
        //
        mPointsCount = mDataValue.length;
        mDegreesAngle = 360 / mPointsCount;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         /*mWidth =getMeasuredWidth();
         mHeight = getMeasuredHeight();*/

//        mScreenWidth=getScreenWidth(mContext);
//        mScreenHeight=getScreenHeight(mContext);
       /* int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);*/



        int maxLen=0;
        String maxLenName=mDataName[0];
        for (int i = 0; i < mDataValue.length; i++) {
           int len= mDataName[i].length();
            if (len>maxLen){
                maxLen=len;
                maxLenName=mDataName[i];
            }

        }
        float fixWidth_Height=mPaintText.measureText(maxLenName);
        /**
         * 实际的内容宽和高
         */
        int contentWidthSize = (int) (fixWidth_Height*2+mRadius*2+Math.max(mPointRadius,mLinesWidth)*1.0f/2+this.getPaddingLeft()+this.getPaddingRight());
        int contentHeightSize = (int) (fixWidth_Height*2+mRadius*2+Math.max(mPointRadius,mLinesWidth)*1.0f/2+this.getPaddingTop()+this.getPaddingBottom());


        //getDefaultSize()
        int width = resolveSize(contentWidthSize, widthMeasureSpec);
        int height = resolveSize(contentHeightSize, heightMeasureSpec);

        /**
         * 修正xml设置太小的情况
         */
        width=width<contentWidthSize?contentWidthSize:width;
        height=height<contentHeightSize?contentHeightSize:height;

        /**
         *
         */
        setMeasuredDimension(width, height);

        mViewWidth = width;
        mViewHeight = height;


    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //
        canvas.translate(mViewWidth/ 2, mViewHeight / 2);

        if (mPointsCount > 10 || mPointsCount < 3) {
            Log.e(TAG, "onDraw: 只能是3~10个数据");
            return;
        }
        drawFramesAndLines(canvas);
        //
        drawContent(canvas);

        drawTexts(canvas);
    }

    private void drawContent(Canvas canvas) {
        Paint paintContent = new Paint();
        //paintContent.setColor(mContentColor);
        paintContent.setAntiAlias(true);
        paintContent.setStyle(Paint.Style.FILL);
        paintContent.setStrokeCap(Paint.Cap.ROUND);
        Path path = new Path();

        for (int i = 0; i < mPointsCount; i++) {
            //!!!加上原有占width的笔触  mPointsCount-1条线 mLineWidth/2*(mPointsCount-1)
            float nowContentDisance = (mRadius - mLinesWidth / 2) * mDataValue[i];
            if (i == 0) {
                path.moveTo(nowContentDisance, 0);
                //绘制小圆点
                paintContent.setColor(mPointColor);
                canvas.drawCircle(nowContentDisance, 0, mPointRadius, paintContent);
            } else {
                float nowDegreesAngle = mDegreesAngle * i;
                double nowRadiansAngle = Math.toRadians(nowDegreesAngle);
                //sinA=对边/Radius
                //cosA=领边/Radius
                float tempX = (float) (nowContentDisance * Math.cos(nowRadiansAngle));
                float tempY = (float) (nowContentDisance * Math.sin(nowRadiansAngle));
                path.lineTo(tempX, tempY);
                //绘制小圆点
                paintContent.setColor(mPointColor);
                canvas.drawCircle(tempX, tempY, mPointRadius, paintContent);
            }
        }
        paintContent.setColor(mContentColor);
        paintContent.setAlpha(mContentAlpha);
        canvas.drawPath(path, paintContent);
    }

    /**
     * 绘制文字
     */
    private void drawTexts(Canvas canvas) {
       /* Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
        float fontHeight = fontMetrics.descent - fontMetrics.ascent;*/

        /**
         * 参考圆
         */
        //###canvas.drawCircle(0,0,mRadius+mText_ContentDisance,mPaint);

        for (int i = 0; i < mPointsCount; i++) {
            if (i == 0) {
                //获取文字度量信息
                Paint.FontMetrics fontMetrics = mPaintText.getFontMetrics();
                float textHeight = fontMetrics.descent - fontMetrics.ascent;
                float baseLineYDis = textHeight / 2 - Math.abs(fontMetrics.descent);
                float tempXFix = mText_ContentDisance;
                float tempYFix = baseLineYDis;
                canvas.drawText(mDataName[i], mRadius + tempXFix, 0 + tempYFix, mPaintText);
            } else {
                float nowDegreesAngle = mDegreesAngle * i;
                double nowRadiansAngle = Math.toRadians(nowDegreesAngle);
                //sinA=对边/Radius
                //cosA=领边/Radius
                float tempX = (float) (mRadius * Math.cos(nowRadiansAngle));
                float tempY = (float) (mRadius * Math.sin(nowRadiansAngle));
                //
               /* Rect rect_bounds=new Rect();
                paintText.getTextBounds(mDataName[i],0,mDataName[i].length(),rect_bounds);
                int textWidth=rect_bounds.width();
                int textHeight=rect_bounds.height();*/
                //获取文字度量信息
                Paint.FontMetrics fontMetrics = mPaintText.getFontMetrics();
                float textHeight = fontMetrics.descent - fontMetrics.ascent;
                float textWidth = mPaint.measureText(mDataName[i]);

                float baseLineYDis = textHeight / 2 - Math.abs(fontMetrics.descent);
                float tempXFix;
                float tempYFix;
                if (nowDegreesAngle > 0 && nowDegreesAngle <= 90) {
                    tempXFix = mText_ContentDisance - textWidth / 2;
                    tempYFix = mText_ContentDisance + textHeight / 2 + baseLineYDis;
                    canvas.drawText(mDataName[i], tempX + tempXFix, tempY + tempYFix, mPaintText);
                } else if (nowDegreesAngle > 90 && nowDegreesAngle < 180) {
                    tempXFix = mText_ContentDisance + textWidth;
                    tempYFix = mText_ContentDisance + textHeight / 2 + baseLineYDis;
                    canvas.drawText(mDataName[i], tempX - tempXFix, tempY + tempYFix, mPaintText);
                } else if (nowDegreesAngle == 180) {
                    //###tempXFix=mText_ContentDisance+textWidth;//这里感觉计算不准 改变计算方式弥补下
                    /** 换个计算方法*/
                    Rect rectBounds = new Rect();
                    mPaintText.getTextBounds(mDataName[i], 0, mDataName[i].length(), rectBounds);
                    int textNewWidth = rectBounds.width();
                    tempXFix = mText_ContentDisance + textNewWidth;
                    tempYFix = baseLineYDis;
                    //mRadius
                    canvas.drawText(mDataName[i], -mRadius - tempXFix, 0 + tempYFix, mPaintText);
                } else if (nowDegreesAngle > 180 && nowDegreesAngle <= 270) {
                    tempXFix = mText_ContentDisance + textWidth;
                    tempYFix = mText_ContentDisance + textHeight / 2 - baseLineYDis;
                    canvas.drawText(mDataName[i], tempX - tempXFix, tempY - tempYFix, mPaintText);
                } else if (nowDegreesAngle > 270 && nowDegreesAngle <= 360) {
                    tempXFix = mText_ContentDisance - textWidth / 2;
                    tempYFix = mText_ContentDisance + textHeight / 2 - baseLineYDis;
                    canvas.drawText(mDataName[i], tempX + tempXFix, tempY - tempYFix, mPaintText);
                }
            }
        }


    }

    private void drawFramesAndLines(Canvas canvas) {
        Path path = new Path();
        int mDisance = mRadius / (mPointsCount - 1);
        /**
         * 循环出多个正六边形
         */
        for (int j = 0; j < mPointsCount - 1; j++) {
            float nowRadius = mDisance * ((mPointsCount - 1) - j);

            /**
             * 画每一个正六边形
             */
            for (int i = 0; i < mPointsCount; i++) {
                // path.reset();
                /**
                 * 顺时针  从最右边画
                 */
                if (i == 0) {
                    path.moveTo(nowRadius, 0);

                    /**
                     * 画从中点到最右边点的线
                     */
                    Path pathLines = new Path();
                    pathLines.lineTo(nowRadius, 0);
                    mPaint.setColor(mLinesColor);
                    canvas.drawPath(pathLines, mPaint);
                } else {
                    float nowDegreesAngle = mDegreesAngle * i;
                    double nowRadiansAngle = Math.toRadians(nowDegreesAngle);
                    //sinA=对边/Radius
                    //cosA=领边/Radius
                    float tempX = (float) (nowRadius * Math.cos(nowRadiansAngle));
                    float tempY = (float) (nowRadius * Math.sin(nowRadiansAngle));
                    path.lineTo(tempX, tempY);
                    /**
                     * 画从当前点到中点的线
                     */
                    Path pathLines = new Path();
                    pathLines.moveTo(tempX, tempY);
                    pathLines.lineTo(0, 0);
                    mPaint.setColor(mLinesColor);
                    canvas.drawPath(pathLines, mPaint);
                }

            }
            //
            path.close();
            //
            canvas.drawPath(path, mPaint);
        }
    }

    //
    public int dp2px(int dpValue) {
        int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, getResources().getDisplayMetrics());
        return px;
    }
    //获取屏幕的宽度
    public static int getScreenWidth(Context context) {
        Resources resources = context.getResources();
        DisplayMetrics displayMetrics = resources.getDisplayMetrics();
        float density = displayMetrics.density;
        int width = displayMetrics.widthPixels;
        int height = displayMetrics.heightPixels;
        return width;
    }

    //获取屏幕的高度
    public static int getScreenHeight(Context context) {
        Resources resources = context.getResources();
        DisplayMetrics displayMetrics = resources.getDisplayMetrics();
        float density = displayMetrics.density;
        int width = displayMetrics.widthPixels;
        int height = displayMetrics.heightPixels;
        return height;
    }
}
作者:RichieZhu 发表于2016/10/27 17:11:33 原文链接
阅读:46 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>