android-fragments 原生子系检视未占据FrameLayout的完整高度和长度

wtlkbnrh  于 2022-11-13  发布在  Android
关注(0)|答案(2)|浏览(127)

我正在尝试将camera-x集成到react-native中的android fragment
这是我的本地代码

class CealScanQrView(context: Context): FrameLayout(context) {

 init {
        val frameLayoutParams = ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT
        )
        layoutParams = frameLayoutParams
       setLayoutParams(layoutParams)
        setBackgroundColor(Color.parseColor("#5FD3F3"))

        preview = PreviewView(context)
        preview.id = View.generateViewId()
        preview.layoutParams = ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT
        )
        addView(preview)
}
//other non related code
......
}

我尝试使用LinearlayoutConstraintLayout而不是Framelayout,但同样的问题仍然存在
react-native端,我将按如下方式使用它

const App = () => {
//non-related code here
.....

 return (
    <SafeAreaView>
      <StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />

      {isCameraPermissionGranted ? (
        <CealScanQrViewManager
          style={{
            // converts dpi to px, provide desired height
            height: PixelRatio.getPixelSizeForLayoutSize(200),
            // converts dpi to px, provide desired width
            width: PixelRatio.getPixelSizeForLayoutSize(200),
          }}
          ref={ref}
          onChange={readQr}
        />
      ) : (
        <View style={{backgroundColor: 'red'}} />
      )}
      <Text style={{color: 'red', fontSize: 25}}>{firstText}</Text>
      <Text style={{color: 'red', fontSize: 25}}>{secondText}</Text>
    </SafeAreaView>
  );
}

这是我的UI外观

你可以看到相机和第一个红色文本之间有一个空间,这个空间是Framelayout,但是相机没有占据Framelayout的整个空间,我不明白为什么
完整的源代码here

hujrc8aj

hujrc8aj1#

您的代码的第一个问题是,您在此处使用200 x200像素对其进行样式设置:

<CealScanQrViewManager
          style={{
            // You intentionally scale it to be small
            height: PixelRatio.getPixelSizeForLayoutSize(200),
            width: PixelRatio.getPixelSizeForLayoutSize(200),
          }}

第二件事是你使用的是androidx相机包中的PreviewView,它不是一个简单的SurfaceViewTextureView,而是一个 Package 器。它是什么意思-文档中说
它在内部使用TextureView或SurfaceView来显示摄像机馈送,并对它们应用所需的变换以正确显示预览,这涉及到校正它们的纵横比、缩放和旋转。
这意味着,如果将只使用正确的视图,而不考虑与预览容器大小相关的任何扭曲,因为它以前是与表面纹理视图。因此,如果预览大小或纵横比不同于您的屏幕(或您的预览的父组件),它将不匹配父尺寸,但将被缩放到看起来“正确”和预览大小范围内。
在普通的“曲面”或“纹理”视图内通道化摄影机预览将没有此限制,但如果容器与预览的尺寸或纵横比不匹配,则会发生扭曲。
这不是解决方案,但在您的情况下没有简单的解决方案-您必须考虑上面的信息来调整您的代码。

编辑

还有一个方法,但它很复杂,我不会给予你一个实现-只是一个通用的方法。你可以做的是,你可以得到你的预览的长宽比和大小,并通过负填充或自定义视图容器剪切它,其中有一些相关的逻辑。这不是一个简单的方法,也不是很难-它只是很复杂,似乎非常多余。
例如,如果您的预览长宽比(h/w)= 1.20和屏幕宽高比(高/宽)= 1.40,你的预览会在顶部和底部有间隙,如果居中的话。现在你的目标是使预览的纵横比为1.40,而不扭曲渲染在上面的图像-你将不得不从左和右剪切预览,这样它就不会在顶部和底部有间隙。2反之亦然,如果你的预览长宽比比大于屏幕的长宽比
差不多吧。

a11xaf1n

a11xaf1n2#

帕夫洛的回答帮了我的忙,但如果有人对确切的答案感兴趣,我会告诉你
我从本机端删除了style prop并更改了manuallyLayoutChildren方法,如下所示

private fun manuallyLayoutChildren(view: ViewGroup) {
        for (i in 0 until view.childCount) {
            val child = view.getChildAt(i)
            child.measure(
                View.MeasureSpec.makeMeasureSpec(view.measuredWidth, View.MeasureSpec.EXACTLY),
                View.MeasureSpec.makeMeasureSpec(view.measuredHeight, View.MeasureSpec.EXACTLY))
            child.layout(0, 0, child.measuredWidth, child.measuredHeight)
        }

    }

相关问题