ZXING之前都用的好好的,结果在一个Android11的设备上翻了车 (基于全屏预览的情况下)
扫码页面预览效果变形,
在网上找了一些代码,修改后发现无效,不适用我这边的设备,
最后想着,预览结果变形,就是预览Size用的不太对,最后找到了调整预览Size的方法,修改了一下,经测试,Android 11 Android 7都正常显示
先全局搜索一下代码, findBestPreviewSizeValue 该方法是获取最佳预览Size的方法
ZXING
private static Point findBestPreviewSizeValue(CharSequence previewSizeValueString, Point screenResolution) { Point res = Util.getPoint(previewSizeValueString); if (null != res) { return res; } return null; }
相关工具类方法
/** * 获取最佳分辨率 */ public static Point getPoint(CharSequence previewSizeValueString) { Pattern COMMA_PATTERN = Pattern.compile(","); String[] lists = COMMA_PATTERN.split(previewSizeValueString); Size[] querys = new Size[lists.length]; int i = 0; for (String data: lists ) { String[] datas = data.split("x"); int width = Integer.parseInt(datas[1]); int height = Integer.parseInt(datas[0]); Size size = new Size(width,height); querys[i] = size; i++; } int width = Util.getScreenSize(context, true)[0]; int height = Util.getScreenSize(context, true)[1]; Size size = Util.chooseSize(querys,querys, width,height); Point point = new Point(size.getHeight(), size.getWidth()); return point; } /** * 获取屏幕的宽高,(此方法来自于 autolayout) */ public static int[] getScreenSize(Context context, boolean useDeviceSize) { int[] size = new int[2]; WindowManager w = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display d = w.getDefaultDisplay(); DisplayMetrics metrics = new DisplayMetrics(); d.getMetrics(metrics); int widthPixels = metrics.widthPixels; int heightPixels = metrics.heightPixels; if (!useDeviceSize) { size[0] = widthPixels; size[1] = heightPixels - getStatusBarHeight(context); return size; } if (Build.VERSION.SDK_INT >= 14 && Build.VERSION.SDK_INT < 17) try { widthPixels = (Integer) Display.class.getMethod("getRawWidth").invoke(d); heightPixels = (Integer) Display.class.getMethod("getRawHeight").invoke(d); } catch (Exception ignored) { } if (Build.VERSION.SDK_INT >= 17) try { Point realSize = new Point(); Display.class.getMethod("getRealSize", Point.class).invoke(d, realSize); widthPixels = realSize.x; heightPixels = realSize.y; } catch (Exception ignored) { } size[0] = widthPixels; size[1] = heightPixels; return size; } /** * 获取状态栏高度,(此方法来自于 autolayout) */ public static int getStatusBarHeight(Context context) { int result = 0; try { int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { result = context.getResources().getDimensionPixelSize(resourceId); } } catch (Resources.NotFoundException e) { e.printStackTrace(); } return result; } /** * Camera 获取合适的尺寸(如果有相同尺寸,优先选择) */ public static Size chooseSize(Size[] preChoices, Size[] picChoices, int width, int height) { // Collect the supported resolutions that are at least as big as the preview Surface List<Size> choices = new ArrayList<>(); // 部分设备 预览与拍照的分辨率不一致,故先获取一致的分辨率 for (Size pre: preChoices) { for (Size pic: picChoices ) { if (pre.getHeight() == pic.getHeight() && pre.getWidth() == pic.getWidth()) { choices.add(pre); } } } if (choices.size() == 0) { return preChoices[0]; } int ReqTmpWidth = width; int ReqTmpHeight = height; //先查找preview中是否存在与surfaceview相同宽高的尺寸 for (Size size : choices) { if ((size.getWidth() == ReqTmpWidth) && (size.getHeight() == ReqTmpHeight)) { return size; } } // 获取与传入的宽高比最接近的size float reqRatio = ((float) ReqTmpWidth) / ReqTmpHeight; float curRatio, deltaRatio; float deltaRatioMin = Float.MAX_VALUE; Size retSize = null; for (Size size : choices) { curRatio = ((float) size.getWidth()) / size.getHeight(); deltaRatio = Math.abs(reqRatio - curRatio); if (deltaRatio < deltaRatioMin) { deltaRatioMin = deltaRatio; retSize = size; } } return retSize != null ? retSize : choices.get(0); }