1

我已经在这个问题上搜索和编码 3 天了,没有结果:(

我做了一个相机叠加层,代码在这里+加速度计

public class CameraActivity extends Activity implements SurfaceHolder.Callback, SensorEventListener {
    Camera camera;
    SurfaceView surfaceView;
    SurfaceHolder surfaceHolder;
    boolean previewing = false;
    LayoutInflater controlInflater = null;

    static String TAG = CameraActivity.class.getSimpleName();

    // Accelerometer
    private SensorManager mSensorManager;
    private Sensor mAccelerometer;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.surface_view);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        surfaceView = (SurfaceView) findViewById(R.id.camerapreview);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        controlInflater = LayoutInflater.from(getBaseContext());
        View viewControl = controlInflater.inflate(R.layout.camera_control,
                null);

        LayoutParams layoutParamsControl = new LayoutParams(
                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);

        this.addContentView(viewControl, layoutParamsControl);


        // Accelerometer
        mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        mAccelerometer = mSensorManager
                .getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mSensorManager.registerListener(this, mAccelerometer,
                SensorManager.SENSOR_DELAY_NORMAL);

    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

    @Override
    public void onSensorChanged(SensorEvent event) {

    }


    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        // TODO Auto-generated method stub
        if (previewing) {
            camera.stopPreview();
            previewing = false;
        }

        if (camera != null) {
            try {
                camera.setPreviewDisplay(surfaceHolder);
                camera.startPreview();
                previewing = true;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        camera = Camera.open();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        camera.stopPreview();
        camera.release();
        camera = null;
        previewing = false;
    }
}

然后在 camera_control.xml 我有这个:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout_holder"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@android:color/transparent"
    android:gravity="bottom" >

    <ImageView
        android:id="@+id/imageView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/camera_red_button"
        android:layout_alignLeft="@+id/camera_back_button"
        android:layout_marginBottom="27dp"
        android:src="@drawable/camera_accelerometer_red" />

</RelativeLayout>

camera_accelerometer_red

球

并在 surface_view.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/camerapreview_holder"
    >

<SurfaceView
    android:id="@+id/camerapreview"  
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    />
</LinearLayout>

图像视图是水平仪的图像。

这个想法是用户需要在拍照之前调平相机。我已经清除了所有不必要的代码。上面的代码是工作代码。

问题: 我需要为水平仪制作一个球。它不需要是最平滑的水平仪。如果我能找到将球限制在水平仪内并根据加速度计结果移动它的方法,我会和拉里一样高兴:)/

如果有人请让我在这三件事上朝着正确的方向前进:

  1. 将动画限制在一个区域内
  2. 禁区要圈,怎么做

提前致谢。H。

4

1 回答 1

1

好的,我得到了答案。希望它可以帮助某人。您需要使用计算从中间到拐角的距离(半径)偏移拐角。

此外,我将加速度计更改为方向传感器,然后我可以获得手机在 X 和 Y 轴上的 3d 旋转。

以下代码是工作代码,我对它们进行了测试。我使用的是 Android 2.3.3+ 球的运动不是很流畅,因为这不是应用程序的目的。

我认为为了平滑运动,您可能还需要为其添加计时器和碰撞检测。请检查 android 示例。

我还没有重构代码。所以这不是生产级代码:)

代码:

public class CameraActivity extends Activity implements SurfaceHolder.Callback,
        SensorEventListener {

    // Accelerometer
    private SensorManager mSensorManager;
    private Sensor mAccelerometer;

    /** Called when the activity is first created. */
    public static float x;
    public static float y;

    FrameLayout layout_holder;
    FrameLayout ball_holder;

    // private float hOriginSize;
    float halfOfWidth;
    int centerYOnImage;
    private Sensor mOrientation;

        // float viewInset = 14.0f; // I remove this simply to make the code cleaner. I used this to calculate the radius and the offset later on

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.surface_view);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        surfaceView = (SurfaceView) findViewById(R.id.camerapreview);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        controlInflater = LayoutInflater.from(getBaseContext());
        View viewControl = controlInflater.inflate(R.layout.camera_control,
                null);

        LayoutParams layoutParamsControl = new LayoutParams(
                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);

        this.addContentView(viewControl, layoutParamsControl);

        // Accelerometer
        mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        mOrientation = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
        mSensorManager.registerListener(this, mAccelerometer,
                SensorManager.SENSOR_DELAY_NORMAL);

        Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
                R.drawable.ball);
        CustomDrawableView mCustomDrawableView = new CustomDrawableView(this,
                bitmap);

        ball_holder = (FrameLayout) findViewById(R.id.ball_holder);
        ball_holder.addView(mCustomDrawableView);

        halfOfWidth = 40; // You can calculate this, I just put this so I can test it. This is the half of the width of target image - attached in the question

        centerYOnImage = 40; // Not important :)

    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

    // This method will update the UI on new sensor events
    public void onSensorChanged(SensorEvent event) {

        // float azimuth_angle = event.values[0];
        x = event.values[1];
        y = event.values[2];

        // FIXME: Fine tune this for the image taking part
        float ratio = 70.0f / 25.0f;
        x = x * ratio;
        y = y * ratio;

        Log.d(TAG, "x and y: " + x + " " + y);

        float maxDistance = 35; // To calculate this halfOfWidth - viewInset;

                // to calculate between 2 distances 
        float distance = (float) Math.sqrt(((x) * (x)) + ((y) * (y)));

        if (distance > maxDistance) {

            float angle = (float) Math.atan2(x, y);

            / Get new point on the edge of the circle
            y = (float) (Math.cos(angle) * maxDistance);
            x = (float) (Math.sin(angle) * maxDistance);
        }

        x = x + 40; // 40 is the half od the distance of the full width
        y = (y * -1.0f) + 40; // -1.0f is so orientation works like the actual spirit level

        canUserTakePhoto(distance);

    }

    // Change the background
    public void canUserTakePhoto(float treshold) {
        if (treshold > 10) {
            // Not Yet
        } else {
            // take it
        }
    }


    @Override
    protected void onResume() {
        super.onResume();
        mSensorManager.registerListener(this, mOrientation,
                SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    protected void onPause() {
        super.onPause();
        mSensorManager.unregisterListener(this);
    }

    public class CustomDrawableView extends ImageView {

        Bitmap b;

        public CustomDrawableView(Context context, Bitmap bitmap) {
            super(context);

            this.b = bitmap;
        }

        @Override
        protected void onDraw(Canvas canvas) {

            canvas.drawBitmap(this.b, x, y, null);

            invalidate();
        }
    }

    @Override
    public void onDestroy() // main thread stopped
    {
        super.onDestroy();
        // wait for threads to exit before clearing app
        System.runFinalizersOnExit(true);
        // remove app from memory
        android.os.Process.killProcess(android.os.Process.myPid());
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        // TODO Auto-generated method stub
        if (previewing) {
            camera.stopPreview();
            previewing = false;
        }

        if (camera != null) {
            try {

                camera.setPreviewDisplay(surfaceHolder);
                camera.startPreview();
                previewing = true;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        camera = Camera.open();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        camera.stopPreview();
        camera.release();
        camera = null;
        previewing = false;
    }

}

干杯。

于 2013-05-08T06:51:16.770 回答