自定义view实战笔记--CircleMenu

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

    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值