Android:RelativeLayout边距有效但被覆盖 [英] Android: RelativeLayout margin works but gets overridden

查看:95
本文介绍了Android:RelativeLayout边距有效但被覆盖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

setLayoutParams( params )之前使用RelativeLayout.LayoutParamsmarginTop.
可在所有设备上运行半秒钟,但在某些情况下会重新出现在顶部. 该视图始终保持在我的运行Moto X 2014的棒棒糖上的保持视图的中心,而不是在运行我的运行Lollipop的Nexus 4 上的视图.

Using RelativeLayout.LayoutParams and marginTop before setLayoutParams( params ).
Works on all devices for half a second but some cases it bumps back to top. The view stays centered in the holding view on my Moto X 2014 running Lollipop but not on my Nexus 4 running Lollipop.

  1. 开启活动
  2. 边距很好,SurfaceView居中
  3. 〜200ms延迟
  4. 重置页边距并将其重新设置为顶部(SurfaceView的顶部位于支架的顶部)

结算活动

  1. 后退
  2. 〜200ms延迟
  3. 插入边距,将我的视图放到正确的位置
  4. 活动关闭


代码(已编辑)

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)与屏幕顶部对齐,而忽略了边距和重力.


Example

I need the margin to work like this every time on every device. On some devices the red (SurfaceView) is aligned with top of screen ignoring the margin and gravity.

推荐答案

为了简化您的生活,这是我简单的相机实现,可以为您提供帮助.请注意,此实现基于旧的 android.hardware.Camera API.从API级别21开始,有一种使用相机的新方法.

To make your life easier, here is my simple camera implementation which can help you out. Note that this implementation relays on the old android.hardware.Camera API. Starting API level 21 there is a new way of working with the camera.

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

Anyway here is your basic xml file for your activity:

<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中:

Your needed utils classes. You can add these to your own CameraActivity if you won't use them elsewhere:

CameraUtils:

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:

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;
            }
} 

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

And last but not least, don't forget about you permissions in the manifest file:

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

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

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

I hope this answer helps you to get your camera on the go!

干杯, 迈克

这篇关于Android:RelativeLayout边距有效但被覆盖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆