1:根据startAngle来摆放子view(特别注意坐标的问题)
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
//获取孩子视图的测量宽度
int childWidth = child.getMeasuredWidth();
//temp:相当于自定义控件所在圆的圆心到子视图所在矩形的几何中心的距离
float temp = d / 3.0f;
int left = (int) (d / 2 + Math.round(temp * Math.cos(Math.toRadians(startAngle))) - childWidth / 2);
int right = left + childWidth;
int top = (int) (d / 2 + Math.round(temp * Math.sin(Math.toRadians(startAngle))) - childWidth / 2);
int bottom = top + childWidth;
child.layout(left, top, right, bottom);
startAngle += 360 / getChildCount();
}
}
2:实现旋转的思路是计算出down到move之间的角度(注意坐标和角度的象限问题),在累加给startAngle,重新布局requestLayout();
private float lastX;
private float lastY;
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("test", "ACTION_DOWN");
lastX = x;
lastY = y;
break;
case MotionEvent.ACTION_MOVE:
Log.i("test", "ACTION_MOVE");
float start = CircleUtil.getAngle(lastX, lastY, d);
float end = CircleUtil.getAngle(x, y, d);
float angle;
//判断点击的点所处的象限,如果是1,4象限,角度值是正数,否则是负数
if (CircleUtil.getQuadrant(x, y, d) == 1 || CircleUtil.getQuadrant(x, y, d) == 4) {
angle = end - start;
} else {
angle = start - end;
}
startAngle += angle;
//让界面重新布局和绘制
requestLayout();
lastX = x;
lastY = y;
break;
case MotionEvent.ACTION_UP:
Log.i("test", "ACTION_UP");
break;
}
//return true 表示当前控件想要处理事件,如果没有其他控件想要处理,则所有的MotionEvent事件都会交给自己处理
return true;
}
3:两个工具类
public class CircleUtil {
/**
* 根据触摸的位置,计算角度
*
* @param xTouch
* @param yTouch
* @param d 直径
* @return
*/
public static float getAngle(float xTouch, float yTouch,int d) {
double x = xTouch - (d / 2f);
double y = yTouch - (d / 2f);
//hypot:通过两条直角边,求斜边
return (float) (Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI);
}
/**
* 根据当前位置计算象限
*
* @param x
* @param y
* @param d 直径
* @return
*/
public static int getQuadrant(float x, float y,int d) {
int tmpX = (int) (x - d / 2);
int tmpY = (int) (y - d / 2);
if (tmpX >= 0) {
return tmpY >= 0 ? 4 : 1;
} else {
return tmpY >= 0 ? 3 : 2;
}
}
}