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