Android 全屏摄像头 - 同时保持摄像头的选定比例
Android full screen camera - while keeping the camera selected ratio
我们正在尝试构建类似于 Instagram
相机屏幕的东西。即允许用户拍摄 square
张照片。这样做时 U.i 必须能够让用户在 fullScreen
模式下看到相机。我们想强制用户以 portrait
模式
拍摄图像
获取相机可能的比率
我们正在通过
计算camera
的best
比率
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) h / w;
if (sizes == null) {
return null;
}
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) {
continue;
}
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
全屏显示。
public FrameLayout setCameraLayout(int width, int height) {
float newProportion = (float) width / (float) height;
// Get the width of the screen
int screenWidth = this.customCameraActivity.getWindowManager().getDefaultDisplay()
.getWidth();
int screenHeight = this.customCameraActivity.getWindowManager().getDefaultDisplay()
.getHeight();
float screenProportion = (float) screenWidth / (float) screenHeight;
// Get the SurfaceView layout parameters
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams)preview.getLayoutParams();
if (newProportion > screenProportion) {
lp.width = screenWidth;
lp.height = (int) ((float) screenWidth / newProportion);
} else {
lp.width = (int) (newProportion * (float) screenHeight);
lp.height = screenHeight;
}
//calculate the amount that takes to make it full screen (in the `height` parameter)
float propHeight = screenHeight / lp.height;
//make it full screen(
lp.width = (int)(lp.width * propHeight);
lp.height = (int)(lp.height * propHeight);
frameLayout.setLayoutParams(lp);
return frameLayout;
}
setCameraLayout 调用者
OnCreate
来自 Activity
和之后的 surfaceChanged
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
if (getHolder().getSurface() == null) {
return;
}
try {
cameraManager.getCamera().stopPreview();
} catch (Exception e) {
// tried to stop a non-existent preview
}
try {
Camera.Parameters cameraSettings = cameraManager.getCamera().getParameters();
cameraSettings.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
this.cameraView.setCameraLayout(mPreviewSize.width, mPreviewSize.height);
cameraManager.getCamera().setParameters(cameraSettings);
cameraManager.getCamera().setPreviewDisplay(holder);
cameraManager.getCamera().startPreview();
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
目标
phone 上的全屏相机预览。
问题
现在我们得到了没有失真的预览,好! 并且它具有与 phone
相同的 height
,这也是好!。 但是! preview
的宽度比 phone width
大(当然)所以结果相机的中心不在中心的 phone。我们考虑过的可能解决方案:
move
布局左负位置使预览中心在屏幕中央
crop
布局并仅绘制应该对 phone screens
可见的 new preview
的中心
有什么办法可以解决这个问题吗?
非常感谢! :)
我通过设置 SurfaceView 的重力成功地使预览居中:
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(wid, hei);
lp.gravity = Gravity.CENTER;
mSv.setLayoutParams(lp);
代码片段摘自here,有耐心破解的欢迎使用。我想我正在解决类似的问题(预览旋转、失真、fit-in/fill)
祝你好运。
如果我从代码片段中了解到,每次用户更改方向或旋转相机时,您都会重新实例化相机。有什么理由这样做吗?
为什么不将预览限制为仅纵向预览并使用可旋转的叠加视图?我很确定其他人(Instagram、Snapchat 等)也是这样做的。如果我能找到它,我将用这个例子进行编辑。
我们正在尝试构建类似于 Instagram
相机屏幕的东西。即允许用户拍摄 square
张照片。这样做时 U.i 必须能够让用户在 fullScreen
模式下看到相机。我们想强制用户以 portrait
模式
获取相机可能的比率
我们正在通过
计算camera
的best
比率
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) h / w;
if (sizes == null) {
return null;
}
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) {
continue;
}
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
全屏显示。
public FrameLayout setCameraLayout(int width, int height) {
float newProportion = (float) width / (float) height;
// Get the width of the screen
int screenWidth = this.customCameraActivity.getWindowManager().getDefaultDisplay()
.getWidth();
int screenHeight = this.customCameraActivity.getWindowManager().getDefaultDisplay()
.getHeight();
float screenProportion = (float) screenWidth / (float) screenHeight;
// Get the SurfaceView layout parameters
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams)preview.getLayoutParams();
if (newProportion > screenProportion) {
lp.width = screenWidth;
lp.height = (int) ((float) screenWidth / newProportion);
} else {
lp.width = (int) (newProportion * (float) screenHeight);
lp.height = screenHeight;
}
//calculate the amount that takes to make it full screen (in the `height` parameter)
float propHeight = screenHeight / lp.height;
//make it full screen(
lp.width = (int)(lp.width * propHeight);
lp.height = (int)(lp.height * propHeight);
frameLayout.setLayoutParams(lp);
return frameLayout;
}
setCameraLayout 调用者
OnCreate
来自 Activity
和之后的 surfaceChanged
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
if (getHolder().getSurface() == null) {
return;
}
try {
cameraManager.getCamera().stopPreview();
} catch (Exception e) {
// tried to stop a non-existent preview
}
try {
Camera.Parameters cameraSettings = cameraManager.getCamera().getParameters();
cameraSettings.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
this.cameraView.setCameraLayout(mPreviewSize.width, mPreviewSize.height);
cameraManager.getCamera().setParameters(cameraSettings);
cameraManager.getCamera().setPreviewDisplay(holder);
cameraManager.getCamera().startPreview();
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
目标
phone 上的全屏相机预览。
问题
现在我们得到了没有失真的预览,好! 并且它具有与 phone
相同的 height
,这也是好!。 但是! preview
的宽度比 phone width
大(当然)所以结果相机的中心不在中心的 phone。我们考虑过的可能解决方案:
move
布局左负位置使预览中心在屏幕中央crop
布局并仅绘制应该对phone screens
可见的
new preview
的中心
有什么办法可以解决这个问题吗?
非常感谢! :)
我通过设置 SurfaceView 的重力成功地使预览居中:
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(wid, hei);
lp.gravity = Gravity.CENTER;
mSv.setLayoutParams(lp);
代码片段摘自here,有耐心破解的欢迎使用。我想我正在解决类似的问题(预览旋转、失真、fit-in/fill)
祝你好运。
如果我从代码片段中了解到,每次用户更改方向或旋转相机时,您都会重新实例化相机。有什么理由这样做吗?
为什么不将预览限制为仅纵向预览并使用可旋转的叠加视图?我很确定其他人(Instagram、Snapchat 等)也是这样做的。如果我能找到它,我将用这个例子进行编辑。