本人经过小米、华为、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);
}
});
}
看到上面如果还解决不了你的问题请留言 我会一一解答