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

Android加速度计开发水平仪:靶心原点与气泡边界限制问题

Solution for Your Bullseye Level Accelerometer Issues

Let’s break down your two challenges and fix them step by step to get your level working exactly how you want it!


1. Setting the Bullseye Center as Accelerometer X:0 Y:0 Origin

Your bullseye is already centered via ConstraintLayout, but we need to map its physical center to the accelerometer’s (0,0) point. Here’s how to do it properly:

Key Steps:

  • First, get the bullseye’s actual center coordinates (we can’t do this in onCreate because views haven’t finished rendering yet).
  • Use those center coordinates as the base for all bubble position calculations.

Code Modifications:

First, add global variables to track critical positions:

private ImageView bullseye;
private ImageView bubble;
private float bullseyeCenterX;
private float bullseyeCenterY;
private float maxOffset; // Max distance bubble can move from center

Then, initialize these values once the view is fully drawn (using ViewTreeObserver):

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.your_layout);

    bullseye = findViewById(R.id.bullseye);
    bubble = findViewById(R.id.bubble);
    xview = findViewById(R.id.xview);
    yview = findViewById(R.id.yview);

    // Wait for views to render before calculating positions
    bullseye.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            // Remove listener to avoid repeated calls
            bullseye.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            
            // Calculate bullseye's center point
            bullseyeCenterX = bullseye.getX() + bullseye.getWidth() / 2f;
            bullseyeCenterY = bullseye.getY() + bullseye.getHeight() / 2f;

            // Calculate maximum allowed bubble offset (bullseye radius minus bubble radius)
            float bullseyeRadius = bullseye.getWidth() / 2f;
            float bubbleRadius = bubble.getWidth() / 2f;
            maxOffset = bullseyeRadius - bubbleRadius;

            // Initialize bubble to center
            resetBubbleToCenter();
        }
    });
}

2. Initialize Bubble to Center & Restrict It to Bullseye Radius

Your current code uses raw accelerometer values to set absolute positions, which causes the bubble to drift endlessly and go outside the bullseye. We’ll fix this by:

  1. Starting the bubble exactly at the bullseye center
  2. Scaling accelerometer values to fit within the bullseye’s bounds
  3. Clamping the bubble’s position so it never leaves the green area

Code for Initialization & Position Clamping:

Add this helper method to reset the bubble to center:

private void resetBubbleToCenter() {
    // Set bubble's top-left corner so its center matches the bullseye's center
    float bubbleX = bullseyeCenterX - bubble.getWidth() / 2f;
    float bubbleY = bullseyeCenterY - bubble.getHeight() / 2f;
    bubble.setX(bubbleX);
    bubble.setY(bubbleY);
}

Update your onSensorChanged method to use relative offsets instead of absolute values:

@Override
public void onSensorChanged(SensorEvent event) {
    if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
        // Map accelerometer values (-9.8 to 9.8) to our max allowed offset
        float scaleFactor = maxOffset / 9.8f;
        // Adjust sign for Y-axis to match screen orientation (tweak if needed for your device)
        float offsetX = event.values[0] * scaleFactor;
        float offsetY = -event.values[1] * scaleFactor;

        // Clamp offsets to keep bubble inside bullseye
        offsetX = Math.max(-maxOffset, Math.min(maxOffset, offsetX));
        offsetY = Math.max(-maxOffset, Math.min(maxOffset, offsetY));

        // Calculate bubble's final position (account for bubble's own size)
        float bubbleX = bullseyeCenterX - bubble.getWidth()/2f + offsetX;
        float bubbleY = bullseyeCenterY - bubble.getHeight()/2f + offsetY;

        // Update bubble position
        bubble.setX(bubbleX);
        bubble.setY(bubbleY);

        // Update display values (show offset from center)
        xview.setText(String.format("X: %.2f", offsetX));
        yview.setText(String.format("Y: %.2f", offsetY));
    }
}

Layout Fix for Bubble:

Your current bubble layout has constraints that might interfere with manual positioning. Update it to be centered in the parent (so initial layout matches our code’s center position):

<ImageView
    android:id="@+id/bubble"
    android:layout_width="31dp"
    android:layout_height="31dp"
    android:contentDescription="Bubble"
    android:src="@drawable/ic_bubble"
    android:scaleType="centerInside"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:55:50