Margin Android:RelativeLayout边距有效,但被覆盖 问题

Margin Android:RelativeLayout边距有效,但被覆盖 问题,margin,layoutparams,android-relativelayout,Margin,Layoutparams,Android Relativelayout,在setLayoutParams参数之前使用RelativeLayout.LayoutParams和marginTop。 在所有设备上都能工作半秒钟,但在某些情况下会反弹到顶部。 该视图保持在我的Moto X 2014跑步棒棒糖的保留视图的中心,但不在我的Nexus 4跑步棒棒糖上 开幕活动 打开活动 边缘清晰,表面视图居中 约200毫秒延迟 边距重置,并返回到表面顶部在支架顶部查看 结束活动 背压 约200毫秒延迟 边距设置到位,使我的观点处于正确的位置 活动结束 代码编辑 实例 每次在每台设

在setLayoutParams参数之前使用RelativeLayout.LayoutParams和marginTop。 在所有设备上都能工作半秒钟,但在某些情况下会反弹到顶部。 该视图保持在我的Moto X 2014跑步棒棒糖的保留视图的中心,但不在我的Nexus 4跑步棒棒糖上

开幕活动 打开活动 边缘清晰,表面视图居中 约200毫秒延迟 边距重置,并返回到表面顶部在支架顶部查看 结束活动 背压 约200毫秒延迟 边距设置到位,使我的观点处于正确的位置 活动结束 代码编辑 实例 每次在每台设备上我都需要这样的余量。 在某些设备上,红色表面视图与屏幕顶部对齐,忽略了边距和重力


为了让你的生活更轻松,这里是我的简单相机实现,可以帮助你。请注意,此实现依赖于旧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;
    }
}
屏幕截图:

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" />
我希望这个答案能帮助你把相机开动起来

干杯,
Mike

为什么要将支架的布局参数设置为SurfaceView。另外,为什么不直接在xml中添加CustomCamera视图并在那里添加边距?我需要父布局参数来使用边距?如果我错了,请纠正我。至于在XML中使用边距,我正在以编程方式更改视图的宽度和高度,因此在XML中设置它将不起作用。这个问题已经更新了代码,包括来自XML的自定义视图。请给我一些您想要实现的简要细节。没有代码…我可以帮您解决这个问题。支架的纵横比是4:3,而相机是16:9:16,因为它是旋转的,我只想显示中间的4:3。SurfaceView的高度高于或低于支架中显示的高度-我想使用边距重力将SurfaceView向上移动到支架的中间。记住:这在我测试过的三台设备中有一台是有效的。好吧,但如果你的相机初始化错误,不必担心边缘呢?是否有SurfaceHolder.Callback?与实现SurfaceHolder.Callback而不是像您那样设置它有什么区别吗?mSurfaceHolder.addCallback this;而不是mSurfaceHolder.addCallback surfaceHolderCallback错误使用FFC;不,这不应该有很大的区别。您可以根据自己的需要修改类的结构。我尝试更改了许多与活动相关的内容,以使布局保持不变,但即使在实现代码的情况下也无法工作:我可以向您确认,上述代码是100%的功能。如果你只是简单地复制和粘贴它,它肯定会在很多设备和操作系统版本上进行测试。试着一步一步地从这个代码中走出来。我都知道这一点。但是就像你昨天说的。。。。如果它为您提供了一个功能齐全的摄像头实现,并且对您有所帮助,那么您为什么要为这些保证金问题而烦恼呢?
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" />