在RelativeLayout.LayoutParams
之前使用marginTop
和setLayoutParams( params )
。
可以在所有设备上使用半秒钟,但有些情况下它可以恢复到顶部。
视图在我的 Moto X 2014运行棒棒糖的保持视图中居中,但不在我的运行Lollipop的 Nexus 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)与屏幕顶部对齐,忽略了边距和重力。
答案 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" />
我希望这个答案可以帮助您随时随地使用相机!
干杯, 麦克