Java android-如何动态调整SurfaceView的大小?

Java android-如何动态调整SurfaceView的大小?,java,android,android-camera,Java,Android,Android Camera,我正在构建一个简单的录音应用程序。我想在开始录制时动态调整SurfaceView的大小。例如,当用户在“设置”活动中提前将视频分辨率设置为4:3,并单击“开始录制”按钮时,我希望SurfaceView将其宽度和高度更改为4:3。因此,按下录制按钮时,SurfaceView会更改其大小 当应用程序未录制任何内容时,我可以调整SurfaceView的大小,但当我在视频录制开始前尝试更改它时,它会调整视图大小,但录制未正确完成(当我完成录制时,它会抛出stopFailed错误) 我想让我的应用程序调整

我正在构建一个简单的录音应用程序。我想在开始录制时动态调整SurfaceView的大小。例如,当用户在“设置”活动中提前将视频分辨率设置为4:3,并单击“开始录制”按钮时,我希望SurfaceView将其宽度和高度更改为4:3。因此,按下录制按钮时,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<Camera.Size> 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;
    }
 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<Camera.Size> 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;
}
private boolean预序器(){
mRecorder=新的MediaRecorder();
摄像机配置文件=getCurrentProfile();
Camera.Parameters=mCamera.getParameters();
参数=setContinuesFocusMode(参数);
Camera.Size desiredSize=null,optimalPreviewSize=null;
如果(mVideoSizeIndex!=-1){
列出SupportedVidesizes=参数。getSupportedVideoSizes();
if(mVideoSizeIndex
VideoSurfaceView.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<Camera.Size> 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;
    }
 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<Camera.Size> 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;
}
public void resizePreview(int desiredWidth、int desiredHeight、int screenWidth、int screenHeight){
浮动视频比例=(浮动)所需宽度/(浮动)所需高度;
浮动屏幕比例=(浮动)屏幕宽度/屏幕高度;
ViewGroup.LayoutParams lp=this.getLayoutParams();
如果(视频比例>屏幕比例){
lp.width=屏幕宽度;
lp.height=(int)((浮动)屏幕宽度/视频比例);
}否则{
lp.width=(int)(视频比例*(浮动)屏幕高度);
lp.高度=屏幕高度;
}
此.setLayoutParams(lp);
}
公共摄像头。大小GetOptimizePreviewSize(列表大小,整数w,整数h){
最终双纵横比公差=0.2;
双目标率=(双)w/h;
如果(大小==null)
返回null;
照相机。大小优化大小=空;
double minDiff=double.MAX_值;
int targetHeight=h;
用于(相机尺寸:尺寸){
如果(size.width==w&&size.height==h){
尺寸=尺寸;
返回最佳大小;
}
双倍比率=(双倍)size.width/size.height;
if(数学绝对值(比率-目标比率)>纵横比公差)
继续;
if(数学绝对值(尺寸高度-目标光)
当我在应用程序未录制时运行
resizePreview()
方法时,它会完美地改变视图;但是当我在按下录制按钮时运行它时,它会冻结UI一段时间,并且视频输出没有正确保存。主线程是否可能过载


提前谢谢

我解决了。这是因为在调整视图大小时调用了
onSurfaceChanged()
方法。我删除了mCamera.stopPreview()、mCamera.setPreviewDisplay()和mCamera.startPreview(),现在可以正常工作了

我解决了。这是因为在调整视图大小时调用了
onSurfaceChanged()
方法。我删除了mCamera.stopPreview()、mCamera.setPreviewDisplay()和mCamera.startPreview(),现在可以正常工作了

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