安卓 android Android camer2 相机预览变形解决方案

本人经过小米、华为、OPPO、VIVO 等十几款真机测试满足业务需求,横竖屏切换无变形失真问题,产品已上线!
写这篇文章的就是为了感谢编程前辈的们在我编程初期无私分享!

1、相机尺寸筛选

相机尺寸筛选决定你的相机适配要求
例如:UI要求全屏展示、要16:9、4:3等尺寸要求等。
由于现在抖音、微信都是全屏拍摄,我下面以全屏适配来做介绍。
现在CSDN上面介绍的都是各种残缺品、摘抄google源码、git开源翻译过来就是说解决
如果你对camer2 已无所知,看起来确实有点难度,一篇文章你也学不会,先自己梳理一下知识点 camer2相机知识点

 /**
     * @param sizeMap       相机尺寸集合
     * @param viewWidth  相机宽度
     * @param viewHeight 相机高度
     * @return
     */
    public static Size getMinPreSizeNew(Size[] sizeMap, int viewWidth, final int viewHeight) {
        List<Size> sizeWidthEqual = new ArrayList<>();
        //先查找preview中是否存在与surfaceview相同宽高的尺寸
        for (Size size : sizeMap) {
            LogAppUtil.ShowE(size.getWidth() + "__" + size.getHeight());
            //选择更高倍率相机尺寸
            if (size.getWidth() > viewHeight && size.getHeight() > viewWidth) {
                float beishuW = size.getWidth() * 1.0f / viewHeight * 1.0f;
                float beishuH = size.getHeight() * 1.0f / viewWidth * 1.0f;
                LogAppUtil.ShowE("beishuW:" + beishuW + "__" + "beishuH:" + beishuH + "---" + size.getWidth() + ":" + size.getHeight());
                if (beishuH == beishuW) {
                    return size;
                }
            }
            //优先选择大小相等的尺寸
            if ((size.getWidth() == viewHeight) && (size.getHeight() == viewWidth)) {
                needChangeTextSize = false;
                return size;
            }
            //再次选择能够满足我们遮罩层的的容差的
            if (size.getHeight() == viewWidth) {
                sizeWidthEqual.add(size);
            }
        }
        if (sizeWidthEqual.size() > 0) {
            //找一个分辨率最大的尺寸
            Collections.sort(sizeWidthEqual, new Comparator<Size>() {
                @Override
                public int compare(Size o1, Size o2) {
                    return Math.abs(o1.getWidth()-viewHeight) -Math.abs(o2.getWidth()-viewHeight);//相机宽度由小到大排序
                }
            });
            LogAppUtil.ShowE("最优尺寸列表");
            for (Size size : sizeWidthEqual) {
                LogAppUtil.ShowE(size.getWidth() + "__" + size.getHeight());
                //优先选择大小相等的尺寸
            }
            needChangeTextSize = true;
            //图片宽度和屏幕高度越接近 像素越好
            return sizeWidthEqual.get(0);
        } else {
            //以上都不满足自己设置一个条件选择一个相机尺寸展示就可以了。理论上都是被淘汰四五年前的低端机
            return getThreeDatas(sizeMap, viewWidth, viewHeight);
        }
    }

动态适配

拿到合适的相机尺寸后我们根据我们自身业务(全屏)做动态适配
1、通过监听器获取TextureView 的尺寸做动态比适配

 /**
     * 监听打开相机的回调
     */
    private CameraDevice.StateCallback deviceCallback = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice camera) {
            cameraDevice = camera;
            startPreview();
            if (null != mMainTextureView) {
                configureTransform(mMainTextureView.getWidth(), mMainTextureView.getHeight());
            }
        }

        @Override
        public void onDisconnected(@NonNull CameraDevice camera) {
            LogAppUtil.ShowE("CameraDevice.onDisconnected");
            camera.close();
            cameraDevice = null;
        }

        @Override
        public void onError(@NonNull CameraDevice camera, int error) {
            LogAppUtil.ShowE("CameraDevice.onError:" + error);
            camera.close();
            cameraDevice = null;

        }
    };

下面这块代码就是解决你预览界面变形问题

   /**
     * 设置输出画面缩放适配
     *
     * @param viewWidth  mTextureView 的宽度
     * @param viewHeight mTextureView 的高度
     */
    private void configureTransform(int viewWidth, int viewHeight) {
        if (null == mMainTextureView || null == mPreviewSize) {
            return;
        }
        //屏幕方向
        //int rotation = windowManager.getDefaultDisplay().getRotation();
        final Matrix matrix = new Matrix();
        RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
        RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
        float centerX = viewRect.centerX();
        float centerY = viewRect.centerY();
        //相机宽度小于界面高度时,使用矩阵缩放适配
        if (mPreviewSize.getWidth() < viewHeight) {
            LogAppUtil.ShowE(TAG + "矩阵缩放");
            bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
            matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
            float scale = Math.max((float) viewHeight / mPreviewSize.getWidth(), (float) viewWidth / mPreviewSize.getHeight());
            //设置缩放
            matrix.postScale(scale, scale, centerX, centerY);
            //设置旋转角度
            //matrix.postRotate(90 * (rotation - 2), centerX, centerY);
        } else {
            LogAppUtil.ShowE(TAG + "条件满足");
        }
        mMainTextureView.post(new Runnable() {
            @Override
            public void run() {
                mMainTextureView.setTransform(matrix);
            }
        });
    }

看到上面如果还解决不了你的问题请留言 我会一一解答

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
Android相机开发是指在Android系统中使用相机功能进行应用开发的过程。Android系统提供了丰富的相机API,使开发者可以轻松地实现与相机相关的功能。 首先,要在Android应用中使用相机,需要先获取相机实例。可以通过Camera类来获取相机实例,其提供了与相机硬件进行交互的方法和属性。可以通过调用open()方法来打开相机,并通过设置参数来配置相机的各种属性,如照片分辨率、闪光灯模式等。 接下来,可以使用SurfaceView来预览相机所拍摄的画面。SurfaceView是Android中用于显示实时画面的控件,可以通过SurfaceHolder来获取并控制SurfaceView的显示。 在进行拍照操作时,可以通过设置Camera.PictureCallback接口的实现来获取相机所拍摄的照片数据,并将其保存到指定的文件中。可以通过调用takePicture()方法来触发拍照动作,并在PictureCallback的回调方法中处理照片数据。 除了拍照功能,Android相机开发还可以实现其他功能,如录制视频、切换摄像头等。可以通过设置MediaRecorder来实现视频录制功能,通过调用Camera类中的方法来切换前后摄像头。 Android相机开发需要注意相机资源的管理和释放。在使用相机之前,需要先获取相机的访问权限,并在不使用相机时及时释放相机资源,避免资源泄漏。 总之,Android相机开发提供了丰富的API和功能,使开发者可以灵活地利用相机进行应用开发,实现各种有趣的相机功能和交互体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

邻居出行

码农不易,相互鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值