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

Android平台如何设置并读取鼠标光标位置?

Android 鼠标光标锁定中心+3D相机控制实现方案

核心逻辑

Android原生没有直接设置光标绝对位置的API,采用「隐藏系统光标+固定自定义视觉光标+捕获鼠标相对位移」的思路:

  • 隐藏系统默认光标,避免用户看到光标移动
  • 在屏幕中心绘制自定义光标(如十字线),给用户视觉锚点
  • 捕获鼠标的相对移动量,用这个偏移量控制3D相机视角,不需要真的移动光标

测试应用实现步骤

1. 隐藏系统光标

在Activity启动时执行以下代码隐藏系统光标:

getWindow().getDecorView().setCursorVisible(false);

2. 自定义带光标锁定的View

创建自定义View处理鼠标事件并绘制中心光标:

public class CursorLockView extends View {
    private Paint cursorPaint;
    private float centerX, centerY;
    // 相机视角参数
    private float cameraYaw = 0f;
    private float cameraPitch = 0f;
    // 鼠标灵敏度
    private static final float SENSITIVITY = 0.15f;

    public CursorLockView(Context context) {
        super(context);
        init();
    }

    public CursorLockView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        // 初始化自定义光标画笔
        cursorPaint = new Paint();
        cursorPaint.setColor(Color.WHITE);
        cursorPaint.setStrokeWidth(3f);
        cursorPaint.setAntiAlias(true);

        // 隐藏系统光标
        ((Activity) getContext()).getWindow().getDecorView().setCursorVisible(false);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        // 计算屏幕中心坐标
        centerX = w / 2f;
        centerY = h / 2f;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 绘制中心十字光标
        canvas.drawLine(centerX - 25, centerY, centerX + 25, centerY, cursorPaint);
        canvas.drawLine(centerX, centerY - 25, centerX, centerY + 25, cursorPaint);

        // 示例:用矩形模拟3D相机视角变化(实际项目替换为你的3D渲染逻辑)
        canvas.save();
        canvas.translate(centerX, centerY);
        canvas.rotate(cameraYaw);
        canvas.rotate(cameraPitch, 1f, 0f, 0f);
        canvas.drawRect(-60, -60, 60, 60, cursorPaint);
        canvas.restore();
    }

    @Override
    public boolean onGenericMotionEvent(MotionEvent event) {
        // 仅处理鼠标输入
        if (event.getSource() != InputDevice.SOURCE_MOUSE) {
            return super.onGenericMotionEvent(event);
        }

        if (event.getAction() == MotionEvent.ACTION_MOVE) {
            // 获取鼠标相对位移(API 23+支持)
            float deltaX = event.getAxisValue(MotionEvent.AXIS_RELATIVE_X);
            float deltaY = event.getAxisValue(MotionEvent.AXIS_RELATIVE_Y);

            // 更新相机视角(反转Y轴,符合鼠标控制相机的常规逻辑)
            cameraYaw += deltaX * SENSITIVITY;
            cameraPitch -= deltaY * SENSITIVITY;

            // 限制俯仰角度,避免过度翻转
            cameraPitch = Math.max(-89f, Math.min(89f, cameraPitch));

            // 刷新视图,更新相机画面和光标
            invalidate();
            return true;
        }
        return super.onGenericMotionEvent(event);
    }
}

3. 在Activity中使用自定义View

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 直接使用自定义View作为布局
        setContentView(new CursorLockView(this));
    }
}

兼容性处理(针对API 23以下)

如果需要兼容Android 6.0以下版本,无法直接获取相对位移,可以通过记录上一次鼠标绝对位置计算偏移:

private float lastMouseX, lastMouseY;

@Override
public boolean onGenericMotionEvent(MotionEvent event) {
    if (event.getSource() == InputDevice.SOURCE_MOUSE && event.getAction() == MotionEvent.ACTION_MOVE) {
        float currentX = event.getX();
        float currentY = event.getY();
        // 计算偏移量
        float deltaX = currentX - lastMouseX;
        float deltaY = currentY - lastMouseY;

        // 更新相机视角...

        // 更新上一次位置
        lastMouseX = currentX;
        lastMouseY = currentY;
        invalidate();
        return true;
    }
    return super.onGenericMotionEvent(event);
}

注意事项

  • 必须保持自定义光标在屏幕中心,用户的操作始终基于这个锚点
  • 灵敏度参数可以根据设备屏幕大小和用户习惯调整
  • 实际项目中,将示例里的矩形绘制替换为你的3D渲染逻辑(如OpenGL、Unity视图等)

内容的提问来源于stack exchange,提问作者izzy and simple

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 13:33:13