Android 自定義View練習:雷達圖(比重)繪製
阿新 • • 發佈:2019-01-30
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;
}
}