在这里说明一点就是我上面的1,2,3,4是我自己定义的块。因为画扇形的时候api的是按照顺时针画的,而且起点是从第一块开始就是,先画黑色的
最终达到的效果就是点击不同颜色的扇形,产生不同的事件。我给上面加边框的意思是这个边框和圆还有边框与圆之间的空白是同一个view,给新入门Android开发的同志来说一个知识点:view其实就是一个矩形。有时候我们用imageview显示不规则图片的时候觉得这个图片的形状是这个view的形状,其实不是的。
下面来讲实现:
这个view一看就是用了自定义View 实现代码
<pre name="code" class="java">public class FanshapedView extends View implements OnTouchListener {
//矩形,画扇形的时候需要传入的参数
private RectF rectf;
//此view的高度
private int higth;
//此view的宽度
private int wide;
private int absy;
private int absx;
//按下时的x,y的值
private int downy;
private int downx;
//抬起时的x,y的值
private int upx;
private int upy;
//用于计算点击处的角度
private int tanx;
private int tany;
//中心点
private int centerx;
private int centery;
//按下时x,y相对于中心点的坐标
private int coordinatex;
private int coordinatey;
//扇形的半径
private int radius;
//监听器
private FanshapedClicke fanshapedclicke;
//扇形的弧度
private ArrayList<Integer> arraydegrees;
//扇形的颜色
private ArrayList<Integer> arraycolor;
public FanshapedView(Context context) {
super(context);
rectf = new RectF(0, 0, 500, 500);
}
@SuppressLint("ClickableViewAccessibility")
public FanshapedView(Context context, AttributeSet attrs) {
super(context, attrs);
this.setOnTouchListener(this);
arraydegrees=new ArrayList<Integer>();
arraycolor=new ArrayList<Integer>();
arraydegrees.add(45);
arraycolor.add(Color.BLACK);
arraydegrees.add(45);
arraycolor.add(Color.BLUE);
arraydegrees.add(90);
arraycolor.add(Color.CYAN);
arraydegrees.add(90);
arraycolor.add(Color.DKGRAY);
arraydegrees.add(60);
arraycolor.add(Color.GREEN);
arraydegrees.add(30);
arraycolor.add(Color.LTGRAY);
}
/*这里多说一点,得到view的宽高,不能在构造函数中得到, 因为在构造函数中还不知道view的大小,所以得不到,在onMeasure与onLayout中都可以得到
* getMeasuredHeight和getHeight两个都可以得到高度,至于有什么区别 百度一下吧。
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@SuppressLint("DrawAllocation")
@Override
protected void onLayout(boolean changed, int left, int top, int right,int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (changed) {
//得到这个view的宽高;
higth = this.getMeasuredHeight();
wide = this.getMeasuredWidth();
//算出中心点与半径
centerx=radius=wide/2;
centery=higth/2;
//创建矩形
rectf = new RectF(0, 0, higth, wide);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 创建画笔
Paint p = new Paint();
int degree=0;
for (int i = 0; i < arraydegrees.size(); i++){
// 设置红色
p.setColor(arraycolor.get(i));
// 画弧,第一个参数是RectF:该类是第二个参数是角度的开始,第三个参数是多少度,第四个参数是真的时候画扇形,是假的时候画弧线,第五个是画笔
canvas.drawArc(rectf, degree, arraydegrees.get(i), true, p);
degree=arraydegrees.get(i)+degree;
}
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
switch (arg1.getAction()) {
case MotionEvent.ACTION_DOWN:
//按下时候的x,y
downx=(int) arg1.getX();
downy=(int) arg1.getY();
//计算按下的x,y与坐标中点的距离
absx=Math.abs(downx-centerx);
absy=Math.abs(downy-centery);
//用于计算正切值
tanx=Math.abs(downx-centerx);
tany=Math.abs(downy-centery);
//按下时x,y相对于中心点的坐标
coordinatex=downx-centerx;
coordinatey=centery-downy;
break;
case MotionEvent.ACTION_UP:
//抬起来时候的x,y
upx=(int) arg1.getX();
upy=(int) arg1.getY();
//
boolean t=((upx-downx)*(upx-downx)+(upy-downy)*(upy-downy))<25;
int a=absx*absx +absy*absy;
if(a<radius*radius&&t){
double jiaodu=getangle(tanx, tany, coordinatex, coordinatey);
itemClicke(jiaodu);
}
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_CANCEL:
break;
default:
break;
}
return true;
}
/**
*
* @param 用于计算正切值的x
* @param 用于计算正切值的y
* @param downx downy 用于判断按下时候 在第几块
* @return 得到按下时候的角度
*/
protected double getangle(int x,int y,int downx,int downy) {
double angle=(float) 0.0;
if(downx>0&&downy<0){
double c=(double)y/(double)x;
double d=Math.toDegrees(Math.atan(c));
angle=d;
}else if(downx<=0&&downy<=0){
double c=(double)x/(double)y;
double d=Math.toDegrees(Math.atan(c));
angle=d+90;
}else if(downx<0&&downy>=0){
double c=(double)y/(double)x;
double d=Math.toDegrees(Math.atan(c));
angle=180+d;
}else{
double c=(double)x/(double)y;
double d=Math.toDegrees(Math.atan(c));
angle=d+270;
}
return angle;
}
//添加监听事件
protected void itemClicke(double jiaodu) {
int jianji=(int)jiaodu;
int b=0;
int c=arraydegrees.get(0);
System.out.println(jianji);
for (int i = 0; i < arraydegrees.size(); i++) {
if(jianji>b&&jianji<c){
fanshapedclicke.itemClicke(i+1) ;
return;
}
b=b+arraydegrees.get(i);
c=b+arraydegrees.get(i+1);
}
}
//添加监听器
public void setFanshapedClicke(FanshapedClicke fanshapedClicke){
this.fanshapedclicke=fanshapedClicke;
}
//定义监听接口
public interface FanshapedClicke{
public void itemClicke(int a) ;
}
}
整个工程的下载地址 点击这个