Android:RelativeLayout保证金有效但被覆盖

时间:2015-02-03 16:48:17

标签: margin layoutparams android-relativelayout

问题

RelativeLayout.LayoutParams之前使用marginTopsetLayoutParams( params )
可以在所有设备上使用半秒钟,但有些情况下它可以恢复到顶部。 视图在我的 Moto X 2014运行棒棒糖的保持视图中居中,但不在我的运行Lollipop的 Nexus 4 上。


开幕活动

  1. 打开活动
  2. 边距很好,SurfaceView居中
  3. 〜200ms延迟
  4. 边距重置并返回顶部(持有者顶部的SurfaceView顶部)
  5. 结束活动

    1. 后退
    2. 〜200ms延迟
    3. 保证金设定,将我的观点置于正确的位置
    4. 活动已关闭

    5. 代码(编辑)

      RelativeLayout holder = ( RelativeLayout ) findViewById( R.id.holder );
      RelativeLayout.LayoutParams params = ( RelativeLayout.LayoutParams ) holder.getLayoutParams();
      CustomCamera view = ( CustomCamera ) findViewById( R.id.surface ); // Extends SurfaceView
      params.topMargin = margin;
      view.setLayoutParams( params );
      

      实施例

      我需要保证金在每台设备上按照每次工作。 在某些设备上,红色(SurfaceView)与屏幕顶部对齐,忽略了边距和重力。

      What I need

1 个答案:

答案 0 :(得分:0)

为了让您的生活更轻松,这是我的简单相机实现,可以帮助您。请注意,此实现会在旧android.hardware.Camera API上进行中继。从API级别21开始,有一种使用相机的新方法。

无论如何,这是您活动的基本xml文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent">

    <FrameLayout
        android:id="@+id/root_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <SurfaceView
            android:id="@+id/camera_surfaceview"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </FrameLayout>

    <Button
        android:id="@+id/take_picture_button"
        android:layout_width="wrap_content"
        android:layout_height="48dp"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="16dp"
        android:text="Take picture" />
</RelativeLayout>

您的相机活动:

package com.your.package;

import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.hardware.Camera.Size;
import android.media.AudioManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.FrameLayout;

import java.io.IOException;

/**
 * @author Mike Reman
 *
 */
public class MainActivity extends Activity {

    // Constants
    private static final float PREVIEW_SIZE_FACTOR = 1.3f;
    private static final String STATE_SELECTED_CHECKBOX = "CameraType";

    private Camera mCamera;
    private SurfaceHolder mSurfaceHolder = null;

    // Data
//private boolean mHasTwoCameras = (Camera.getNumberOfCameras() > 1);
    private boolean mIsInPreview;
    private boolean mIsUsingFFC = false;
    private boolean mIsLandscape;
    protected AutoFocusCallback autoFocusCallback = new AutoFocusCallback() {

        @Override
        public void onAutoFocus(boolean success, Camera camera) {
            try {
                camera.takePicture(shutterCallback, null, jpegCallback);
            } catch (RuntimeException e) {
                e.printStackTrace();
            }
        }
    };

    private ShutterCallback shutterCallback = new ShutterCallback() {

        @Override
        public void onShutter() {
            AudioManager mgr = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
            mgr.playSoundEffect(AudioManager.FLAG_PLAY_SOUND);
        }
    };

    private PictureCallback jpegCallback = new PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            //Tadaaa, you got your picture taken
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().setFormat(PixelFormat.TRANSLUCENT);
        mIsLandscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;

        if (savedInstanceState != null) {
            mIsUsingFFC = savedInstanceState.getBoolean(STATE_SELECTED_CHECKBOX, false);
        }
        setContentView(R.layout.activity_main);
        initializeCameraAndViews();
    }


    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        outState.putBoolean(STATE_SELECTED_CHECKBOX, mIsUsingFFC);
    }

    /**
     * Initialize the views used by the activity, including the SurfaceView
     * displaying the 'camera'. There is a SurfaceHolder object which is
     * initialized by the SurfaceView's SurfaceHolder
     */
    private void initializeCameraAndViews() {
        FrameLayout frame = (FrameLayout) findViewById(R.id.root_container);
        SurfaceView surfaceView = (SurfaceView) frame.findViewById(R.id.camera_surfaceview);

        if (mSurfaceHolder == null) {
            mSurfaceHolder = surfaceView.getHolder();
        }

        mSurfaceHolder.addCallback(surfaceHolderCallback(mIsUsingFFC));
        findViewById(R.id.take_picture_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    mCamera.autoFocus(autoFocusCallback);
                } catch (RuntimeException e) {
                    try {
                        mCamera.takePicture(shutterCallback, null, jpegCallback);
                    } catch (RuntimeException ex) {
                        // Failed to take the picture
                        ex.printStackTrace();
                    }
                }
            }
        });
    }


    private SurfaceHolder.Callback surfaceHolderCallback(final boolean isUsingFFC) {
        return new SurfaceHolder.Callback() {
            private AsyncTask<Void, Void, Void> initCameraAsyncTask;
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                if (isUsingFFC) {
                    try {
                        mCamera = Camera.open(CameraInfo.CAMERA_FACING_FRONT);
                        CameraUtils.setCameraDisplayOrientation(MainActivity.this, CameraInfo.CAMERA_FACING_FRONT, mCamera);
                    } catch (RuntimeException e) {
                        // Open camera failed
                    }
                } else {
                    try {
                        mCamera = Camera.open(CameraInfo.CAMERA_FACING_BACK);
                        CameraUtils.setCameraDisplayOrientation(MainActivity.this, CameraInfo.CAMERA_FACING_BACK, mCamera);
                    } catch (RuntimeException e) {
                        // Open camera failed
                    }
                }

                try {
                    if (mCamera != null) {
                        mCamera.setPreviewDisplay(holder);
                    } else {
                        // Most probably the device has no camera...yeah it is possible :)
                    }
                } catch (IOException exception) {
                    mCamera.release();
                }
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, final int width, final int height) {
                initCameraAsyncTask = new AsyncTask<Void, Void, Void>() {

                    @Override
                    protected Void doInBackground(Void... params) {
                        if (mCamera != null) {
                            try {
                                Camera.Parameters parameters = mCamera.getParameters();
                                Size size = getOptimalSize(mCamera);
                                parameters.setPreviewSize(size.width, size.height);
                                mCamera.setParameters(parameters);
                            } catch (RuntimeException e) {
                                e.printStackTrace();
                            }

                            mCamera.startPreview();
                        }
                        return null;
                    }

                    @Override
                    protected void onPostExecute(Void result) {
                        super.onPostExecute(result);
                        mIsInPreview = true;

                        // Set the initial FlashMode to OFF
                        if (mCamera != null) {
                            Camera.Parameters parameters = mCamera.getParameters();
                            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                            mCamera.setParameters(parameters);
                        }
                    }
                };
                initCameraAsyncTask.execute();
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                if (mCamera != null) {
                    mCamera.stopPreview();
                    mIsInPreview = false;
                    initCameraAsyncTask.cancel(true);
                    mCamera.release();
                }
            }
        };
    }


    /**
     * Open the camera by creating a new instance of the Camera object depending
     * on the given parameter. Use this method if you want to switch between Front facing camera(FFC) and back facing cameras
     * <p>
     * If the parameter value is true, a new Camera object will be created using
     * the Front Facing Camera. Otherwise the newly created Camera object will
     * use the Back Facing Camera
     * </p>
     *
     * @param isWithFFC
     *            - the parameter to be the deciding factor on which camera is
     *            used
     */
    private void openCamera(boolean isWithFFC) {
        if (mIsInPreview) {
            mCamera.stopPreview();
            mIsInPreview = false;
        }
        mCamera.release();

        int currentCameraId;
        if (isWithFFC) {
            currentCameraId = CameraInfo.CAMERA_FACING_FRONT;
        } else {
            currentCameraId = CameraInfo.CAMERA_FACING_BACK;
        }
        mCamera = Camera.open(currentCameraId);

        CameraUtils.setCameraDisplayOrientation(MainActivity.this, currentCameraId, mCamera);

        try {
            mCamera.setPreviewDisplay(mSurfaceHolder);
        } catch (IOException e) {
            e.printStackTrace();
        }

        new AsyncTask<Void, Void, Void>() {

            @Override
            protected Void doInBackground(Void... params) {
                try {
                    Camera.Parameters parameters = mCamera.getParameters();
                    Size size = getOptimalSize(mCamera);
                    parameters.setPreviewSize(size.width, size.height);
                    mCamera.setParameters(parameters);
                } catch (RuntimeException e) {
                    e.printStackTrace();
                }
                mCamera.startPreview();
                return null;
            }

            @Override
            protected void onPostExecute(Void result) {
                super.onPostExecute(result);
                mIsInPreview = true;
            }

        }.execute();
    }

    /**
     * Gets an optimal size for the created Camera.
     *
     * @param camera
     *            - the built Camera object
     * @return the optimal Size for the Camera object
     */
    private Size getOptimalSize(Camera camera) {
        Size result = null;
        final Camera.Parameters parameters = camera.getParameters();

        int width = ScreenUtils.getScreenWidth(this);
        int height = ScreenUtils.getScreenHeight(this);

        for (final Size size : parameters.getSupportedPreviewSizes()) {
            if (size.width <= width * PREVIEW_SIZE_FACTOR && size.height <= height * PREVIEW_SIZE_FACTOR) {

                if (mIsLandscape) {
                    size.width = width;
                    size.height = height;
                } else {
                    size.height = width; // switching the values because the default camera is basically always in landscape mode and our camera isn't.
                    size.width = height;
                }
                if (result == null) {
                    result = size;
                } else {
                    final int resultArea = result.width * result.height;
                    final int newArea = size.width * size.height;

                    if (newArea > resultArea) {
                        result = size;
                    }
                }
            }
        }
        if (result == null) {
            result = parameters.getSupportedPreviewSizes().get(0);
        }
        return result;
    }
}

您需要的utils类。如果您不想在其他地方使用它们,可以将它们添加到您自己的CameraActivity中:

CameraUtils:

public final class CameraUtils {

            /**
             * Sets the orientation for the Camera object as the default orientation is
             * in landscape mode.
             * @param activity - the Activity where the orientation is applied to the Camera object
             * @param cameraId - the id of the used Camera(using the Front Facing Camera or the Back Facing Camera)
             * @param camera - the Camera object on which the orientation changes will be applied
             */
            public static void setCameraDisplayOrientation(Activity activity, int cameraId, Camera camera) {
                Camera.CameraInfo info = new Camera.CameraInfo();
                Camera.getCameraInfo(cameraId, info);
                int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();

                int degrees = 0;
                switch (rotation) {
                    case Surface.ROTATION_0:
                        degrees = 0;
                        break;
                    case Surface.ROTATION_90:
                        degrees = 90;
                        break;
                    case Surface.ROTATION_180:
                        degrees = 180;
                        break;
                    case Surface.ROTATION_270:
                        degrees = 270;
                        break;
                }

                int result;
                if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                    result = (info.orientation + degrees) % 360;
                    result = (360 - result) % 360; // compensate the mirror(basically turn the image upside down)
                } else { // back-facing
                    result = (info.orientation - degrees + 360) % 360;
                }
                camera.setDisplayOrientation(result);
            }
}

ScreenUtils:

public final class ScreenUtils {
            /**
             * Calculates the screen's width and returns this value.
             * @param activity - the activity where the method is called from
             * @return - the screen's width
             */
            public static int getScreenWidth(Activity activity) {
                Display display = activity.getWindowManager().getDefaultDisplay();
                Point size = new Point();
                display.getSize(size);
                return size.x;
            }

            /**
             * Calculates the screen's height and returns this value.
             * @param activity - the activity where the method is called from
             * @return - the screen's height
             */
            public static int getScreenHeight(Activity activity) {
                Display display = activity.getWindowManager().getDefaultDisplay();
                Point size = new Point();
                display.getSize(size);
                return size.y;
            }
} 

最后但并非最不重要的是,不要忘记清单文件中的权限:

<uses-permission android:name="android.permission.CAMERA" />

<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />

我希望这个答案可以帮助您随时随地使用相机!

干杯, 麦克