1. 程式人生 > >Android 自定義View練習:雷達圖(比重)繪製

Android 自定義View練習:雷達圖(比重)繪製

這裡寫圖片描述

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; } }