动态设置尺寸android,android-如何动态调整SurfaceView的大小?

我正在构建一个简单的记录器应用程序。我想在开始记录时动态调整SurfaceView的大小。例如,当用户在设置活动中预先将视频分辨率设置为4:3的比例并点击'开始录制'按钮时,我希望SurfaceView将它的宽度和高度更改为4:3的比例。所以当按下录制按钮时,SurfaceView会改变它的大小。android-如何动态调整SurfaceView的大小?

当应用程序没有录制任何东西时,我可以调整SurfaceView的大小,但是当我在录制开始之前尝试更改它时,它调整了视图的大小,但录制没有正确完成(录制完成时它会引发stopFailed错误。)

我希望我的应用能够调整SurfaceView的大小,然后开始记录。在用户按下录制按钮之前!

这是我的代码。

MainActivity.java

private boolean prepRecorder() {

mRecorder = new MediaRecorder();

CamcorderProfile profile = getCurrentProfile();

Camera.Parameters parameters = mCamera.getParameters();

parameters = setContinuesFocusMode(parameters);

Camera.Size desiredSize = null, optimalPreviewSize = null;

if (mVideoSizeIndex != -1) {

List supportedVidSizes = parameters.getSupportedVideoSizes();

if (mVideoSizeIndex < supportedVidSizes.size()) {

desiredSize = supportedVidSizes.get(mVideoSizeIndex);

optimalPreviewSize = mSurface.getOptimalPreviewSize(

parameters.getSupportedPreviewSizes(), desiredSize.width, desiredSize.height);

Point screenSize = getScreenSize();

mSurface.resizePreview(optimalPreviewSize.width, optimalPreviewSize.height, screenSize.x, screenSize.y);

parameters.setPreviewSize(optimalPreviewSize.width, optimalPreviewSize.height);

}

} else {

parameters.setPreviewSize(profile.videoFrameWidth, profile.videoFrameHeight);

}

mCamera.setParameters(parameters);

mCamera.unlock();

mRecorder.setCamera(mCamera);

mRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);

mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

mRecorder.setProfile(profile);

mRecorder.setPreviewDisplay(mSurface.getHolder().getSurface());

mVideoPath = getMediaPath();

if (mVideoPath != null) {

mRecorder.setOutputFile(mVideoPath);

} else {

return false;

}

if (desiredSize != null) {

mRecorder.setVideoSize(desiredSize.width, desiredSize.height);

} else {

mRecorder.setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);

}

// Orientation adjustment stuff.....

mTrackerThread = new VideoFileTrackerThread(new Handler(), this, mVideoPath);

mTrackerThread.start();

mTrackerThread.prepareHandler();

mTrackerThread.triggerHandler();

try {

mRecorder.prepare();

} catch (Exception e) {

e.printStackTrace();

return false;

}

return true;

}

VideoSurfaceView.java

public void resizePreview(int desiredWidth, int desiredHeight, int screenWidth, int screenHeight) {

float videoProportion = (float) desiredWidth/(float) desiredHeight;

float screenProportion = (float) screenWidth/screenHeight;

ViewGroup.LayoutParams lp = this.getLayoutParams();

if (videoProportion > screenProportion) {

lp.width = screenWidth;

lp.height = (int) ((float) screenWidth/videoProportion);

} else {

lp.width = (int) (videoProportion * (float) screenHeight);

lp.height = screenHeight;

}

this.setLayoutParams(lp);

}

public Camera.Size getOptimalPreviewSize(List sizes, int w, int h) {

final double ASPECT_TOLERANCE = 0.2;

double targetRatio = (double) w/h;

if (sizes == null)

return null;

Camera.Size optimalSize = null;

double minDiff = Double.MAX_VALUE;

int targetHeight = h;

for (Camera.Size size : sizes) {

if (size.width == w && size.height == h) {

optimalSize = size;

return optimalSize;

}

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;

}

当运行resizePreview()方法时,应用程序不记录,它完美地改变视图;但是当我按下录制按钮时运行它时,它会冻结UI一段时间,并且视频输出未正确保存。主线程是否可能超载?

在此先感谢。

+0

这应该有帮助! http://stackoverflow.com/questions/20491499/resizing-surface-view-for-aspect-ratio-change-in-video-display-in-android –

+0

@ acac97我已经看到并实现了这个问题..它在应用程序不记录任何内容时工作正常,但我想在用户按下StartRecording按钮时调整SurfaceView的大小。 –

+0

还要确保你已经通过了这些步骤 https://developer.android.com/reference/android/hardware/Camera.html –

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 相机预览界面中添加人像框,可以通过在 SurfaceView 或 TextureView 上叠加一个带有透明背景的 ImageView 来实现。以下是实现步骤: 1. 在布局文件中添加 SurfaceView 或 TextureView 和 ImageView。 ```xml <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <!-- SurfaceView 或 TextureView --> <SurfaceView android:id="@+id/surface_view" android:layout_width="match_parent" android:layout_height="match_parent" /> <!-- 带有透明背景的 ImageView --> <ImageView android:id="@+id/face_frame" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/transparent" android:src="@drawable/face_frame" /> </RelativeLayout> ``` 其中,@drawable/face_frame 是一个带有人像框的图片资源。 2. 调整 ImageView 的位置和大小,使其与预览画面重合。 ```java SurfaceView surfaceView = findViewById(R.id.surface_view); ImageView faceFrame = findViewById(R.id.face_frame); surfaceView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { // 获取 SurfaceView 的宽高 int width = surfaceView.getWidth(); int height = surfaceView.getHeight(); // 调整 ImageView 的位置和大小 RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) faceFrame.getLayoutParams(); layoutParams.width = width / 2; layoutParams.height = height / 2; layoutParams.leftMargin = width / 4; layoutParams.topMargin = height / 4; faceFrame.setLayoutParams(layoutParams); // 只需要调整一次,移除监听器 surfaceView.getViewTreeObserver().removeOnGlobalLayoutListener(this); } }); ``` 其中,调整 ImageView 的位置和大小需要在 SurfaceView尺寸确定后进行,因此需要在 onGlobalLayout 回调中进行。 3. 调用相机 API 开始预览。 ```java private Camera camera; private Camera.PreviewCallback previewCallback = new Camera.PreviewCallback() { @Override public void onPreviewFrame(byte[] data, Camera camera) { // 获取预览数据的 byte 数组 } }; private void startCameraPreview() { camera = Camera.open(); try { camera.setPreviewDisplay(surfaceView.getHolder()); camera.setPreviewCallback(previewCallback); camera.startPreview(); } catch (IOException e) { e.printStackTrace(); } } ``` 在预览回调中,可以获取预览数据的 byte 数组,用于后续的人脸检测等操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值