下载地址 :https://download.csdn.net/download/sinat_28238111/10659125
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
public class MainActivity extends AppCompatActivity {
CircleView circleView;
String[] title = {"资金", "出差", "公章", "加班", "用品", "评价", "会议", "值班", "请假"};
List<Map<String, String>> dataList = new ArrayList<>();
@BindView(R.id.a)
TextView a;
@BindView(R.id.b)
TextView b;
@BindView(R.id.c)
TextView c;
@BindView(R.id.d)
TextView d;
@BindView(R.id.e)
TextView e;
@BindView(R.id.f)
TextView f;
@BindView(R.id.g)
TextView g;
@BindView(R.id.h)
TextView h;
@BindView(R.id.i)
TextView i;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
a.setBackgroundColor(0xFFF06292);
b.setBackgroundColor(0xFF81C784);
c.setBackgroundColor(0xFFE57373);
d.setBackgroundColor(0xff9575cd);
e.setBackgroundColor(0xffffb74d);
f.setBackgroundColor(0xffba68c8);
g.setBackgroundColor(0xffaed581);
h.setBackgroundColor(0xffd4e157);
i.setBackgroundColor(0xff7986cb);
for (int a = 0; a < title.length; a++) {
Map<String, String> map = new HashMap<String, String>();
map.put("title", title[a]);
map.put("count", a * 10 + " 人");
dataList.add(map);
}
circleView = findViewById(R.id.pv);
circleView.setList(dataList);
circleView.setOnItemSelectListener(new CircleView.OnItemSelectListener() {
@Override
public void onItemSelect(int index) {
if (index == 20) {
Toast.makeText(MainActivity.this, "我是LoGo", Toast.LENGTH_SHORT).show();
} else if (index == 18) {
Toast.makeText(MainActivity.this, "指标", Toast.LENGTH_SHORT).show();
} else if (index == 19) {
Toast.makeText(MainActivity.this, "计划", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, dataList.get(index).get("title"), Toast.LENGTH_SHORT).show();
}
}
});
}
}
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.text.Layout;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Created by Administrator on 2018/9/20
* 不能旋转 点击定位精确
*/
public class CircleView extends View {
// private float RADIUS = 60f;
private float RADIUS;
private static final int[] COLORS = new int[]{0xFFF06292, 0xFF81C784, 0xFFE57373, 0xff9575cd, 0xffffb74d, 0xffba68c8, 0xffaed581, 0xffd4e157, 0xff7986cb};
private TextPaint textPaint;
private TextPaint textPaint1;
private TextPaint textPaint2;
private TextPaint textPaint3;
private TextPaint textPaint4;
private Paint mPaint;
private Paint mPaint1;
private Paint mPaint2;
private Paint mPaint3,mPaint4;
private Context mContext;
private RectF rectF; //矩形
private int mWidth;
private int mHeight;
List<Map<String, String>> list = new ArrayList<>();
/**
* 大园半径
*/
private float bigR;
public CircleView(Context context) {
super(context);
mContext = context;
}
public CircleView(Context context, AttributeSet attr) {
super(context, attr);
mContext = context;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widhtSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
mWidth = widhtSize;
mHeight = heightSize;
System.out.println("w==" + mWidth + ",h==" + mHeight);
final int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
final int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
final int heightSpecSize = MeasureSpec.getMode(heightMeasureSpec);
if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(mWidth, mHeight);
} else if (widthSpecMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(mWidth, heightSpecSize);
} else if (heightSpecMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(widthSpecSize, mHeight);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
RADIUS = 360f / COLORS.length;//平分360度
initPaint();
drawUI(canvas);
}
private void initPaint() {
mPaint = new Paint();
initPaintConfig(mPaint, Color.TRANSPARENT,0, Paint.Style.FILL);
mPaint1 = new Paint();
initPaintConfig(mPaint1, Color.WHITE,0, Paint.Style.FILL);
mPaint2 = new Paint();
initPaintConfig(mPaint2, Color.WHITE,0, Paint.Style.STROKE);
mPaint3 = new Paint();
initPaintConfig(mPaint3, Color.BLACK,0, Paint.Style.STROKE);
mPaint4 = new Paint();
initPaintConfig(mPaint4, 0xffffb74d,2, Paint.Style.STROKE);
textPaint = new TextPaint();//标题
initTextPaint(textPaint, Color.WHITE, 40);
textPaint1 = new TextPaint();//内容
initTextPaint(textPaint1, Color.WHITE, 30);
textPaint2 = new TextPaint();//LoGo
initTextPaint(textPaint2, Color.BLACK, 40);
textPaint3 = new TextPaint();//指标、计划
initTextPaint(textPaint3, 0xffaed581, 25);
textPaint4 = new TextPaint();//资金笔数
initTextPaint(textPaint4, Color.WHITE, 20);
//初始化区域
rectF = new RectF();
}
/**
* 配置Paint
*
* @param mPaint
* @param black
* @param stroke
*/
private void initPaintConfig(Paint mPaint, int black, int mWidth, Paint.Style stroke) {
mPaint.setColor(black);
mPaint.setAntiAlias(true);
mPaint.setStyle(stroke);
if (mWidth > 0)
mPaint.setStrokeWidth(mWidth);
}
/**
* 初始化TextPaint
*
* @param size
*/
private void initTextPaint(TextPaint textPaint, int color, int size) {
textPaint.setColor(color);
textPaint.setAntiAlias(true);
textPaint.setTextSize(size);
textPaint.setTextAlign(Paint.Align.CENTER);
}
private void drawUI(Canvas canvas) {
canvas.translate(mWidth / 2, mHeight / 2); //将画布坐标原点移到中心位置
float currentStartAngle = 270f; //起始角度
float r = (float) (Math.min(mWidth, mHeight) / 3); //饼状图半径(取宽高里最小的值)
bigR = r;
System.out.println("大圆半径==" + r);
rectF.set(-r, -r, r, r);
for (int i = 0; i < list.size(); i++) {
Map<String, String> map = list.get(i);
mPaint.setColor(COLORS[i]);
canvas.drawArc(rectF, currentStartAngle, RADIUS, true, mPaint);//6条圆弧 凑成一个大圆
Path path = new Path();
path.addArc(rectF, currentStartAngle, RADIUS);
if (i == 0) {
textPaint.setTextSize(30);
canvas.drawTextOnPath(map.get("title"), path, 0, 30, textPaint);//圆弧文字 主要根据path路径
} else {
textPaint.setTextSize(40);
canvas.drawTextOnPath(map.get("title"), path, 0, 50, textPaint);//圆弧文字 主要根据path路径
}
Path path1 = new Path();
path1.addArc(rectF, currentStartAngle, RADIUS);
if (i == 0) {
canvas.drawCircle(0, 0, bigR - 35, mPaint4);// 小圆弧
canvas.drawTextOnPath("指标", path1, -50, 60, textPaint3);
canvas.drawTextOnPath("计划", path1, 45, 60, textPaint3);
canvas.drawTextOnPath("13 笔", path1, -50, 90, textPaint4);
canvas.drawTextOnPath("26 笔", path1, 45, 90, textPaint4);
} else {
canvas.drawTextOnPath(map.get("count"), path1, 0, 90, textPaint1);
}
currentStartAngle += RADIUS;
}
/**
* 资金白色角度先
*/
double angle = 70;//角度
float radian = (float) Math.toRadians(angle);//角度换算弧度 根据弧度计算x y 坐标
float x = (float) (Math.cos(radian) * (bigR - 50));//35间距 +15"资金"文字的一半
float y = (float) (Math.sin(radian) * (bigR - 50));
System.out.println("x==" + x + ",y==" + y);
Path path2 = new Path();
path2.lineTo(x, -(bigR - 50));//首次使用lineTo 先从中心坐标 然后再lineTo
canvas.drawPath(path2, mPaint4);
canvas.drawCircle(0, 0, bigR / 2, mPaint1);// 内圆
//getWidth()表示绘制多宽后换行
StaticLayout sl = new StaticLayout(generateCenterSpannableText(), textPaint2, getWidth(), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true);
canvas.save();
canvas.translate(0, -55);
sl.draw(canvas);
canvas.restore();
// canvas.drawText("2018年"+"\n"+"10月20日", 0, 20, textPaint2);//内圆中添加Logo文字 也可以内圆中加Bitmap
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//中心坐标点
int ww = getWidth() / 2;
int hh = getHeight() / 2;
// 获取点击屏幕时的点的坐标
float x = event.getX();
float y = event.getY();
System.out.println("w==" + ww + ",h==" + hh + ",rx==" + x + ",ry==" + y);
whichCircle(x, y);
return super.onTouchEvent(event);
}
/**
* 确定点击的点在哪个圆内
*
* @param x
* @param y
*/
private void whichCircle(float x, float y) {
// 将屏幕中的点转换成以屏幕中心为原点的坐标点
int ax = getWidth() / 2 - (int) x;
int ay = getHeight() / 2 - (int) y;
double ju = Math.sqrt((ax * ax + (ay * ay)));//根据x,y 坐标获取三角形的第三条斜边(开平方根)
int m = (int) ju;
System.out.println("半径范围==" + m);
if (m <= bigR / 2) {//内圆的半径是bigR/2 如果点击的范围在140之间 是内圆
listener.onItemSelect(20);//随便传的一个数据,区分大圆的触摸事件
System.out.println("我是内圆");
} else {
//大圆范围
if (m <= bigR) {//如果点击的范围不超过大圆的半径
int aa = getRotationBetweenLines(mWidth / 2, mHeight / 2, x, y);//中心点与触摸点的夹角 角度数
System.out.println("触摸角度==" + aa);
if (aa <= 20) {
listener.onItemSelect(18);//指标
return;
} else if (aa > 20 && aa <= 40) {
listener.onItemSelect(19);//计划
return;
}
int c = aa / (int) RADIUS;
listener.onItemSelect(c);
System.out.println("触摸角度==" + aa + "cc==" + c + "数据==" + list.get(c));
}
}
}
/**
* 获取两条线的夹角 角度
*
* @param centerX
* @param centerY
* @param xInView
* @param yInView
* @return
*/
private int getRotationBetweenLines(float centerX, float centerY, float xInView, float yInView) {
double rotation = 0;
double k1 = (double) (centerY - centerY) / (centerX * 2 - centerX);
double k2 = (double) (yInView - centerY) / (xInView - centerX);
double tmpDegree = Math.atan((Math.abs(k1 - k2)) / (1 + k1 * k2)) / Math.PI * 180;
if (xInView > centerX && yInView < centerY) { //第一象限
rotation = 90 - tmpDegree;
} else if (xInView > centerX && yInView > centerY) //第二象限
{
rotation = 90 + tmpDegree;
} else if (xInView < centerX && yInView > centerY) { //第三象限
rotation = 270 - tmpDegree;
} else if (xInView < centerX && yInView < centerY) { //第四象限
rotation = 270 + tmpDegree;
} else if (xInView == centerX && yInView < centerY) {
rotation = 0;
} else if (xInView == centerX && yInView > centerY) {
rotation = 180;
}
return (int) rotation;
}
/**
* 传递数据并重新刷新View
*
* @param list
*/
public void setList(List<Map<String, String>> list) {
if (null == list) {
list = new ArrayList<>();
}
this.list = list;
postInvalidate();
}
//定义一个接口对象listerner
private OnItemSelectListener listener;
//获得接口对象的方法。
public void setOnItemSelectListener(OnItemSelectListener listener) {
this.listener = listener;
}
//定义一个接口
public interface OnItemSelectListener {
void onItemSelect(int index);
}
private SpannableString generateCenterSpannableText() {
String days = "2018年\n09月22日";
SpannableString spannableString = new SpannableString(days);
int indext = days.indexOf("年");
String name = days.substring(0, indext + 1);
String date = days.substring(indext + 1);
// System.out.println("s==" + spannableString.length() + "indext==" + indext + ",name==" + name + ",date==" + date);
spannableString.setSpan(new RelativeSizeSpan(1.5f), 0, name.length(), 0);
ForegroundColorSpan colorSpan = new ForegroundColorSpan(Color.parseColor("#0099EE"));
spannableString.setSpan(colorSpan, name.length(), spannableString.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
return spannableString;
}
}