设置TextureView(Camera2)全屏预览不拉伸
关于拉伸问题,要使预览不变形,需要使用Matrix:
首先把视频区移动到View区,使两者中心点重合。
matrix.preTranslate((textureViewWidth - viewWidth) / 2, (textureViewHeight - viewHeight) / 2);
其次,因为默认视频是fitXY的形式显示的,所以首先要缩放还原回来。
matrix.preScale(viewWidth/ textureViewWidth, viewHeight/ textureViewHeight);
最后等比例放大或缩小,直到视频区的一边和View一边相等,不相等则留白。
int rotation = getWindowManager().getDefaultDisplay().getRotation(); 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 (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) { bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY()); matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL); float scale = Math.max( (float) viewHeight / mPreviewSize.getHeight(), (float) viewWidth / mPreviewSize.getWidth()); matrix.postScale(scale, scale, centerX, centerY); matrix.postRotate(90 * (rotation - 2), centerX, centerY); } else if (Surface.ROTATION_180 == rotation) { matrix.postRotate(180, centerX, centerY); } mTextureView.setTransform(matrix);
不考虑全屏的情况下设置TextureView大小为可支持的最大size即可:
Size largest = Collections.max( Arrays.asList(mMap.getOutputSizes(ImageFormat.JPEG)), new CompareSizesByArea());
要使TextureView全屏,重写TextureView的onMeasure方法:
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); if (0 == mRatioWidth || 0 == mRatioHeight) { setMeasuredDimension(width, height); } else { //设置为大于判断时,textureView全屏预览,小于号时,按比例留白预览 if (width > height * mRatioWidth / mRatioHeight) { setMeasuredDimension(width, width * mRatioHeight / mRatioWidth); } else { setMeasuredDimension(height * mRatioWidth / mRatioHeight, height); } } }
这段代码使得TextureView在宽高都不超过手机屏幕的情况下最大化显示。
解决方案是,让TextureView总是达到最大边界,超出部分不进行预览,但实际上还是能拍到的