You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android自定义View设置线条高度极值及两线夹角计算问询

为自定义View的线条高度设置范围 + 计算直线夹角思路

一、限制线条高度的最大值与最小值

看你的代码,是通过触摸滑动改变lineOneEnd的Y值来调整左侧竖线的高度(线条高度为lineOneEnd - lineOneStart,也就是lineOneEnd - 50f)。要给这个高度设置上下限,只需要在更新lineOneEnd的时候,用Math.max()和Math.min()把数值限制在你想要的区间内就好。

比如我假设你希望线条的最小高度是50(对应lineOneEnd最小为100f),最大高度是250(对应lineOneEnd最大为300f),你可以这样修改onTouchEvent方法里的逻辑:

@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            if (touchArea.contains(event.getX(), event.getY())) {
                currentTouch = TOUCH_TOP_LEFT;
                Toast.makeText(getContext(), "tf" + currentTouch, Toast.LENGTH_SHORT).show();
            } else {
                return false;
            }
            return true;
        case MotionEvent.ACTION_MOVE:
            switch (currentTouch) {
                case TOUCH_TOP_LEFT:
                    // 获取触摸的Y值,然后限制在100f到300f之间
                    float newY = event.getY();
                    lineOneEnd = Math.max(100f, Math.min(newY, 300f));
                    invalidate();
                    return true;
            }
            return false;
        case MotionEvent.ACTION_UP:
            switch (currentTouch) {
                case TOUCH_TOP_LEFT:
                    float newY = event.getY();
                    lineOneEnd = Math.max(100f, Math.min(newY, 300f));
                    currentTouch = NONE;
                    invalidate();
                    return true;
            }
            return false;
    }
    return false;
}

原理说明:

  • Math.min(newY, 300f)确保lineOneEnd不会超过最大值300f,避免线条过高;
  • Math.max(100f, ...)确保lineOneEnd不会低于最小值100f,避免线条过短;
  • 你可以根据自己的需求,把100f和300f改成任意符合业务逻辑的数值。

二、计算两条直线夹角的思路

计算两条直线的夹角,最常用的是向量点积公式,步骤如下:

  1. 获取两条直线的方向向量:每条直线取两个端点,用终点坐标减去起点坐标得到方向向量;
  2. 计算向量点积:两个向量的x分量相乘加上y分量相乘;
  3. 计算向量的模长:每个向量的x、y分量平方和开根号;
  4. 通过点积公式求余弦值:余弦值 = 点积 / (两个向量模长的乘积);
  5. 转成角度:用反余弦函数得到弧度,再转成角度,最后取0-90度的锐角(因为直线夹角通常指最小的那个角)。

示例代码:

你可以在你的Line类里添加这个方法来计算夹角:

private float calculateLineAngle(PointF line1Start, PointF line1End, PointF line2Start, PointF line2End) {
    // 计算两条直线的方向向量
    float vec1X = line1End.x - line1Start.x;
    float vec1Y = line1End.y - line1Start.y;
    float vec2X = line2End.x - line2Start.x;
    float vec2Y = line2End.y - line2Start.y;

    // 计算点积
    float dotProduct = vec1X * vec2X + vec1Y * vec2Y;

    // 计算两个向量的模长
    float vec1Length = (float) Math.sqrt(vec1X * vec1X + vec1Y * vec1Y);
    float vec2Length = (float) Math.sqrt(vec2X * vec2X + vec2Y * vec2Y);

    // 处理向量长度为0的异常情况(比如直线是一个点)
    if (vec1Length == 0 || vec2Length == 0) {
        return 0f;
    }

    // 计算余弦值,限制在[-1,1]范围内,避免浮点计算误差导致超出范围
    float cosTheta = Math.max(-1f, Math.min(dotProduct / (vec1Length * vec2Length), 1f));
    // 转成弧度再转成角度
    float angleRadians = (float) Math.acos(cosTheta);
    float angleDegrees = (float) Math.toDegrees(angleRadians);

    // 返回最小的夹角(0-90度)
    return Math.min(angleDegrees, 180 - angleDegrees);
}

使用示例:

比如你想计算左侧竖线(lineOne)和底部横线的夹角,可以这样调用:

// lineOne的两个点:(lineOneStartx, lineOneStart) 和 (lineOneEndx, lineOneEnd)
// 底部横线的两个点:(lineOneEndx, lineOneEnd) 和 (lineTwoEndx, lineTwoEnd)
float angle = calculateLineAngle(
        new PointF(lineOneStartx, lineOneStart),
        new PointF(lineOneEndx, lineOneEnd),
        new PointF(lineOneEndx, lineOneEnd),
        new PointF(lineTwoEndx, lineTwoEnd)
);

内容的提问来源于stack exchange,提问作者Rnld

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:43:38