Java android textureview具有正确纵横比的全屏预览

Java android textureview具有正确纵横比的全屏预览,java,android,android-camera,android-camera2,android-textureview,Java,Android,Android Camera,Android Camera2,Android Textureview,我一直在使用,不幸的是,示例应用程序被构建为以大约70%的屏幕高度显示textureview预览,环顾四周后,我能够确定这是由AutoFitTextureView覆盖onMeasure()方法造成的,如下所示: @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec);

我一直在使用,不幸的是,示例应用程序被构建为以大约70%的屏幕高度显示textureview预览,环顾四周后,我能够确定这是由AutoFitTextureView覆盖
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 {
        if (width < height * mRatioWidth / mRatioHeight) {
            setMeasuredDimension(width, width * mRatioHeight / mRatioWidth);
        } else {
            setMeasuredDimension(height * mRatioWidth / mRatioHeight, height);
        }
    }
}
@覆盖
测量时的保护空隙(内部宽度测量等级、内部高度测量等级){
超级测量(宽度测量、高度测量);
int width=MeasureSpec.getSize(widthmasurespec);
int height=MeasureSpec.getSize(heightMeasureSpec);
如果(0==mRatioWidth | | 0==mRatioHeight){
设置测量尺寸(宽度、高度);
}否则{
if(宽度<高度*mRatioWidth/mRatioHeight){
设置测量尺寸(宽度、宽度*mRatioHeight/mRatioWidth);
}否则{
设置测量尺寸(高度*mRatioWidth/mRatioHeight,高度);
}
}
}

我试图通过在
setMeasuredDimension(width,height)中设置正确的高度和宽度来纠正这个问题,这修复了高度问题,并从textureview中为我提供了一个全屏预览,但是每个设备上的纵横比都被完全破坏和扭曲,解决这个问题的标准方法是什么?我看到play store上的许多应用程序都找到了解决此问题的方法,但尚未找到解决方案,任何帮助都会大有帮助,谢谢。

如果您想要全屏、无失真预览,那么您必须为相机选择与屏幕纵横比匹配的预览分辨率

但是,如果您的屏幕大小不是标准大小(基本上是16:9或4:3),特别是减去软按钮和通知栏后(假设您不是全屏),那么让预览填充屏幕的唯一选项就是将其部分删除


通过查看视图的宽度和高度以及选定的预览宽度和高度,您应该能够修改TextureView的变换矩阵以消除失真,但这必然会切断部分失真。

我可以通过切换setMeasuredDimension()来解决此问题

int width=MeasureSpec.getSize(widthmasurespec);
int height=MeasureSpec.getSize(heightMeasureSpec);
如果(0==mRatioWidth | | 0==mRatioHeight){
设置测量尺寸(宽度、高度);
}否则{
if(宽度<高度*mRatioWidth/mRatioHeight){
设置测量尺寸(高度*mRatioWidth/mRatioHeight,高度);
}否则{
设置测量尺寸(宽度、宽度*mRatioHeight/mRatioWidth);
}
}

下面是我们用来测量预览的代码,它支持4:3、16:9和1:1的预览大小。高度是缩放的,因为应用程序是纵向块,它不会旋转到横向

希望它能帮助你或其他人解决同样的问题

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int width = MeasureSpec.getSize(widthMeasureSpec);
    int height = MeasureSpec.getSize(heightMeasureSpec);

    Log.d(TAG, "[onMeasure] Before transforming: " + width + "x" + height);

    int rotation = ((Activity) getContext()).getWindowManager().getDefaultDisplay().getRotation();
    boolean isInHorizontal = Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation;

    int newWidth;
    int newHeight;

    Log.d(TAG, "[onMeasure] Get measured dimensions: " + getMeasuredWidth() + "x" + getMeasuredHeight());

    if (isInHorizontal) {
        newHeight = getMeasuredHeight();
        if (mAspectRatioOneOne) newWidth = getMeasuredHeight();
        else newWidth = (int) (newHeight * mAspectRatio);
    } else {
        newWidth = getMeasuredWidth();
        if (mAspectRatioOneOne) newHeight = getMeasuredWidth();
        else newHeight = (int) (newWidth * mAspectRatio);
    }

    setMeasuredDimension(newWidth, newHeight);
    Log.d(TAG, "[onMeasure] After transforming: " + getMeasuredWidth() + "x" + getMeasuredHeight());

}

我在使用Camera2实现时遇到了类似的问题。我使用了TextureView的AutoFitTextureView实现作为相机预览,并希望调整到正确的比率。我的问题来自方法的不同实现,并传播到onSurfaceTextureSizeChanged。 [1] com.google.android.cameraview.cameraview#onMeasure(..)->[2]com.google.android.cameraview.AutoFitTextureView#onMeasure(..)->[3]onSurfaceTextureSizeChanged(..)

与[2]中的if[1]不同的if[1]中的问题。 我在[1]中替换了:

if (height < width * ratio.getY() / ratio.getX()) {
if(高度

if(!(高度
因为[2]的if基于宽度而不是高度

 if (width < height * mRatioWidth / mRatioHeight) {
if(宽度<高度*mratiowith/mratiowith){
验证测量方法(..)是否正确实施


或者您也可以像Edmund Rojas一样-上面的

AutoFitTextureView在布局中应该使用wrap\u内容

    <AutoFitTextureView
        android:id="@+id/texture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>


/**
*可调整为指定纵横比的[TextureView]。
*/
类AutoFitTextureView:TextureView{
构造函数(context:context):这个(context,null)
构造函数(context:context,attrs:AttributeSet?):这个(context,attrs,0)
构造函数(上下文:context,attrs:AttributeSet?=null,defStyle:Int=0):super(上下文,attrs,defStyle)
专用变量比率宽度=0
私人var比率为0
/**
*设置此视图的纵横比。将根据纵横比测量视图的大小
*根据参数计算。请注意,参数的实际大小并不重要
*是,调用setAspectRatio(2,3)和setAspectRatio(4,6)会得到相同的结果。
*
*@param宽度相对水平尺寸
*@param高度相对垂直尺寸
*/
fun setAspectRatio(宽度:Int,高度:Int){
要求(!(宽度<0 | |高度<0)){“大小不能为负。”
比率宽度=宽度
比率高度=高度
requestLayout()
}
覆盖测量时的乐趣(widthMeasureSpec:Int,heightMeasureSpec:Int){
超级测量(宽度测量、高度测量)
val width=MeasureSpec.getSize(widthMeasureSpec)
val height=MeasureSpec.getSize(heightMeasureSpec)
如果(比率宽度==0 | |比率高度==0){
设置测量尺寸(宽度、高度)
}否则{
if(宽度<高度*比率宽度/比率高度){
设置测量尺寸(宽度、宽度*比率高度/比率宽度)
}否则{
设置测量尺寸(高度*比率宽度/比率高度,高度)
}
}
}
}

Hello Edmund,“切换setMeasuredDimension()”是什么意思?我对camera2的全屏显示也有同样的问题。请提供在onMeasure方法中使用的代码,使全屏显示不失真。谢谢更新的答案,但此解决方案会延长预览时间。Tha
 if (width < height * mRatioWidth / mRatioHeight) {
    <AutoFitTextureView
        android:id="@+id/texture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

/**
 * A [TextureView] that can be adjusted to a specified aspect ratio.
 */
class AutoFitTextureView : TextureView {

    constructor(context: Context) : this(context, null)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) : super(context, attrs, defStyle)

    private var ratioWidth = 0
    private var ratioHeight = 0

    /**
     * Sets the aspect ratio for this view. The size of the view will be measured based on the ratio
     * calculated from the parameters. Note that the actual sizes of parameters don't matter, that
     * is, calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result.
     *
     * @param width  Relative horizontal size
     * @param height Relative vertical size
     */
    fun setAspectRatio(width: Int, height: Int) {
        require(!(width < 0 || height < 0)) { "Size cannot be negative." }
        ratioWidth = width
        ratioHeight = height
        requestLayout()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        val width = MeasureSpec.getSize(widthMeasureSpec)
        val height = MeasureSpec.getSize(heightMeasureSpec)
        if (ratioWidth == 0 || ratioHeight == 0) {
            setMeasuredDimension(width, height)
        } else {
            if (width < height * ratioWidth / ratioHeight) {
                setMeasuredDimension(width, width * ratioHeight / ratioWidth)
            } else {
                setMeasuredDimension(height * ratioWidth / ratioHeight, height)
            }
        }
    }

}