Android layout 在android的摄像头预览中,在视图内使用加速计移动球

Android layout 在android的摄像头预览中,在视图内使用加速计移动球,android-layout,android-animation,accelerometer,Android Layout,Android Animation,Accelerometer,我已经就这个问题搜索和编码了3天,没有结果:( 我制作了一个摄像头覆盖图,代码在这里+加速计 public class CameraActivity extends Activity implements SurfaceHolder.Callback, SensorEventListener { Camera camera; SurfaceView surfaceView; SurfaceHolder surfaceHolder; boolean previewi

我已经就这个问题搜索和编码了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>

在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>

“图像”视图是“精神级别”的图像

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

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

如果有人告诉我这三件事的正确方向:

  • 将动画限制在一个区域内
  • 禁闭区要圆,怎么做
  • 提前谢谢。
    好的,我已经得到了答案。希望它能帮助别人。您需要使用计算从中间到角点的距离(半径)以及角点的偏移量

    此外,我已经改变了方向传感器的加速度计,然后我可以得到手机在X轴和Y轴的三维旋转

    下面的代码是工作代码,我对它们进行了测试。我使用的是安卓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;
        }
    
    }
    

    干杯。

    好的,我知道答案了。希望它能帮助别人。您需要使用计算从中间到角点的距离(半径)以及角点的偏移量

    此外,我已经改变了方向传感器的加速度计,然后我可以得到手机在X轴和Y轴的三维旋转

    下面的代码是工作代码,我对它们进行了测试。我使用的是安卓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;
        }
    
    }
    
    干杯