Anonymous
Внедрение нативной камеры Android в React Native всегда показывает черный экран
Сообщение
Anonymous » 16 июн 2025, 08:53
Я пытаюсь внедрить собственное представление Android в свое приложение React, я использую новую архитектуру < /p>
Итак, вот мой пример кода < /p>
Код: Выделить всё
class ReactMyCamera: ConstraintLayout {
private var viewFinder: PreviewView = PreviewView(context)
private var mCameraProvider: ProcessCameraProvider? = null
private lateinit var cameraExecutor: ExecutorService
private var imageCapture: ImageCapture? = null
private var button: Button = Button(context)
companion object {
private const val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS"
}
constructor(context: Context) : super(context) {
configureComponent(context)
}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
configureComponent(context)
}
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
configureComponent(context)
}
private fun configureComponent(context: Context) {
val constraintLayoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
layoutParams = constraintLayoutParams
val constraintSet = ConstraintSet()
constraintSet.clone(this)
viewFinder.id = View.generateViewId()
viewFinder.layoutParams = ConstraintLayout.LayoutParams(
ConstraintLayout.LayoutParams.MATCH_CONSTRAINT,
ConstraintLayout.LayoutParams.MATCH_CONSTRAINT
)
addView(viewFinder)
constraintSet.constrainWidth(viewFinder.id,ConstraintSet.MATCH_CONSTRAINT)
constraintSet.constrainHeight(viewFinder.id,ConstraintSet.MATCH_CONSTRAINT)
constraintSet.connect(viewFinder.id,ConstraintSet.LEFT,ConstraintSet.PARENT_ID,ConstraintSet.LEFT)
constraintSet.connect(viewFinder.id,ConstraintSet.RIGHT,ConstraintSet.PARENT_ID,ConstraintSet.RIGHT)
constraintSet.connect(viewFinder.id,ConstraintSet.TOP,ConstraintSet.PARENT_ID,ConstraintSet.TOP)
constraintSet.connect(viewFinder.id,ConstraintSet.BOTTOM,ConstraintSet.PARENT_ID,ConstraintSet.BOTTOM,200)
button.id = View.generateViewId()
button.text = "Take Photo"
button.layoutParams = ConstraintLayout.LayoutParams(
ConstraintLayout.LayoutParams.MATCH_CONSTRAINT,
ConstraintLayout.LayoutParams.WRAP_CONTENT
)
button.setBackgroundColor(Color.YELLOW)
button.setTextColor(Color.RED)
addView(button)
constraintSet.constrainWidth(button.id,ConstraintSet.MATCH_CONSTRAINT)
constraintSet.constrainHeight(button.id,ConstraintSet.WRAP_CONTENT)
constraintSet.connect(button.id,ConstraintSet.LEFT,ConstraintSet.PARENT_ID,ConstraintSet.LEFT)
constraintSet.connect(button.id,ConstraintSet.RIGHT,ConstraintSet.PARENT_ID,ConstraintSet.RIGHT)
constraintSet.connect(button.id,ConstraintSet.BOTTOM,ConstraintSet.PARENT_ID,ConstraintSet.BOTTOM,20)
setupLayoutHack()
manuallyLayoutChildren()
constraintSet.applyTo(this)
button.setOnClickListener {
takePhoto()
}
setUpCamera(context)
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
manuallyLayoutChildren()
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
measureChildren(widthMeasureSpec, heightMeasureSpec)
}
private fun setupLayoutHack() {
Choreographer.getInstance().postFrameCallback(object : Choreographer.FrameCallback {
override fun doFrame(frameTimeNanos: Long) {
manuallyLayoutChildren()
viewTreeObserver.dispatchOnGlobalLayout()
Choreographer.getInstance().postFrameCallback(this)
}
})
}
private fun manuallyLayoutChildren() {
for (i in 0 until childCount) {
val child = getChildAt(i)
child.measure(
MeasureSpec.makeMeasureSpec(measuredWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(measuredHeight, MeasureSpec.EXACTLY)
)
child.layout(0, 0, child.measuredWidth, child.measuredHeight)
}
}
....
}
< /code>
Теперь проблема в том, что я не вижу камеру, кнопка занимает всю ширину и высоту, если экран, теперь, когда я использую тот же код в нативном Android, она работает абсолютно нормально < /p>
Клон этого репо < /p>
npm install
cd android
./gradlew generateCodegenArtifactsFromSchema
yarn react-native run-android --active-arch-only
Теперь я решил рефактор кода, чтобы удалить Constraintlayout
Код: Выделить всё
class ReactMyCamera: FrameLayout {
private var viewFinder: PreviewView = PreviewView(context)
private lateinit var button: Button
private var mCameraProvider: ProcessCameraProvider? = null
private lateinit var cameraExecutor: ExecutorService
private var imageCapture: ImageCapture? = null
companion object {
private const val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS"
}
constructor(context: Context) : super(context) {
configureComponent(context)
}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
configureComponent(context)
}
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
configureComponent(context)
}
private fun configureComponent(context: Context) {
viewFinder.layoutParams = FrameLayout.LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT
)
installHierarchyFitter(viewFinder)
addView(viewFinder)
// Create Button
button = Button(context).apply {
id = View.generateViewId()
text = "Start"
elevation = 2f
layoutParams = FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT
).apply {
gravity = Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL
bottomMargin = 10
}
}
addView(button)
}
private val REQUIRED_PERMISSIONS = mutableListOf(Manifest.permission.CAMERA).apply {
if (Build.VERSION.SDK_INT
Я также пытался сделать следующие вещи < /p>
1.
override fun requestLayout() {
super.requestLayout()
post(measureAndLayout)
}
private val measureAndLayout = Runnable {
measure(
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
)
layout(left, top, right, bottom)
}
< /code>
[list]
[*] private val measureAndlayout = runnable {
ream (
mameaspec.makemeasperspec(width, mearspec.exactly),
measurespec.makemeaspec-(height.xactly), exactly), exactly), exactly), exactly), exactly) < /br /measerspec.makemeaspec- ceace.xactly). /> Layout (слева, вверху, справа, внизу)
} < /p>
переопределить веселье намеров (WidthMeasurespec: int, heightmeaspec: int) {
var maxwidth = 0
var maxheight = 0
for (i in 0 in gildcount) {br /> gath = 0
for (i in 0 in gildcount) {
gate) {br /> gate) (child.visibility! = Gone) {
child.measure(widthmeasurespec, termespec.unspecifififified)
maxwidth = maxwidth.coerceatleast (child.measuredwidth)
maxheight = maxheight.coerceatles /> val finalwidth = maxwidth.coerceatleasteast (prevededminimumwidth)
val finalheight = maxheight.coerceatleast (prevededminimumheight)
setmeaseRedDimension (finalwidth, finalHeight)
(контекст как TheMedReActContext). /> (контекст как TheMedReactContext) .getNativeModule (uimanagermodule :: class.java)
? Int, справа: int, внизу: int) {
super.onlayout(Changed, слева, вверху, справа, внизу)
вручные /> super.onmeasure(widthmeasurespec, heightmeaspecpec)
measurechildren (widthmeasurespec, heightmeaspec)
} < /p>
< /li>
override fun requestlayout () {br />super.RequestlAyout. /> post (measureAndlayout)
} < /p>
private val measureAndLayout = Runnable {
measure(
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
)
layout(left, top, right, bottom)
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
var maxWidth = 0
var maxHeight = 0
for (i in 0 until childCount) {
val child = getChildAt(i)
if (child.visibility != GONE) {
child.measure(widthMeasureSpec, MeasureSpec.UNSPECIFIED)
maxWidth = maxWidth.coerceAtLeast(child.measuredWidth)
maxHeight = maxHeight.coerceAtLeast(child.measuredHeight)
}
}
val finalWidth = maxWidth.coerceAtLeast(suggestedMinimumWidth)
val finalHeight = maxHeight.coerceAtLeast(suggestedMinimumHeight)
setMeasuredDimension(finalWidth, finalHeight)
(context as ThemedReactContext).runOnNativeModulesQueueThread {
(context as ThemedReactContext).getNativeModule(UIManagerModule::class.java)
?.updateNodeSize(id, finalWidth, finalHeight)
}
}
[/list]
Пробое использовал RELATIVELAYOU>
Подробнее здесь:
https://stackoverflow.com/questions/796 ... ack-screen
1750053199
Anonymous
Я пытаюсь внедрить собственное представление Android в свое приложение React, я использую новую архитектуру < /p> Итак, вот мой пример кода < /p> [code]class ReactMyCamera: ConstraintLayout { private var viewFinder: PreviewView = PreviewView(context) private var mCameraProvider: ProcessCameraProvider? = null private lateinit var cameraExecutor: ExecutorService private var imageCapture: ImageCapture? = null private var button: Button = Button(context) companion object { private const val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS" } constructor(context: Context) : super(context) { configureComponent(context) } constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { configureComponent(context) } constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { configureComponent(context) } private fun configureComponent(context: Context) { val constraintLayoutParams = ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT ) layoutParams = constraintLayoutParams val constraintSet = ConstraintSet() constraintSet.clone(this) viewFinder.id = View.generateViewId() viewFinder.layoutParams = ConstraintLayout.LayoutParams( ConstraintLayout.LayoutParams.MATCH_CONSTRAINT, ConstraintLayout.LayoutParams.MATCH_CONSTRAINT ) addView(viewFinder) constraintSet.constrainWidth(viewFinder.id,ConstraintSet.MATCH_CONSTRAINT) constraintSet.constrainHeight(viewFinder.id,ConstraintSet.MATCH_CONSTRAINT) constraintSet.connect(viewFinder.id,ConstraintSet.LEFT,ConstraintSet.PARENT_ID,ConstraintSet.LEFT) constraintSet.connect(viewFinder.id,ConstraintSet.RIGHT,ConstraintSet.PARENT_ID,ConstraintSet.RIGHT) constraintSet.connect(viewFinder.id,ConstraintSet.TOP,ConstraintSet.PARENT_ID,ConstraintSet.TOP) constraintSet.connect(viewFinder.id,ConstraintSet.BOTTOM,ConstraintSet.PARENT_ID,ConstraintSet.BOTTOM,200) button.id = View.generateViewId() button.text = "Take Photo" button.layoutParams = ConstraintLayout.LayoutParams( ConstraintLayout.LayoutParams.MATCH_CONSTRAINT, ConstraintLayout.LayoutParams.WRAP_CONTENT ) button.setBackgroundColor(Color.YELLOW) button.setTextColor(Color.RED) addView(button) constraintSet.constrainWidth(button.id,ConstraintSet.MATCH_CONSTRAINT) constraintSet.constrainHeight(button.id,ConstraintSet.WRAP_CONTENT) constraintSet.connect(button.id,ConstraintSet.LEFT,ConstraintSet.PARENT_ID,ConstraintSet.LEFT) constraintSet.connect(button.id,ConstraintSet.RIGHT,ConstraintSet.PARENT_ID,ConstraintSet.RIGHT) constraintSet.connect(button.id,ConstraintSet.BOTTOM,ConstraintSet.PARENT_ID,ConstraintSet.BOTTOM,20) setupLayoutHack() manuallyLayoutChildren() constraintSet.applyTo(this) button.setOnClickListener { takePhoto() } setUpCamera(context) } override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { super.onLayout(changed, left, top, right, bottom) manuallyLayoutChildren() } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) measureChildren(widthMeasureSpec, heightMeasureSpec) } private fun setupLayoutHack() { Choreographer.getInstance().postFrameCallback(object : Choreographer.FrameCallback { override fun doFrame(frameTimeNanos: Long) { manuallyLayoutChildren() viewTreeObserver.dispatchOnGlobalLayout() Choreographer.getInstance().postFrameCallback(this) } }) } private fun manuallyLayoutChildren() { for (i in 0 until childCount) { val child = getChildAt(i) child.measure( MeasureSpec.makeMeasureSpec(measuredWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(measuredHeight, MeasureSpec.EXACTLY) ) child.layout(0, 0, child.measuredWidth, child.measuredHeight) } } .... } < /code> Теперь проблема в том, что я не вижу камеру, кнопка занимает всю ширину и высоту, если экран, теперь, когда я использую тот же код в нативном Android, она работает абсолютно нормально < /p> Клон этого репо < /p> npm install cd android ./gradlew generateCodegenArtifactsFromSchema yarn react-native run-android --active-arch-only [/code] Теперь я решил рефактор кода, чтобы удалить Constraintlayout [code]class ReactMyCamera: FrameLayout { private var viewFinder: PreviewView = PreviewView(context) private lateinit var button: Button private var mCameraProvider: ProcessCameraProvider? = null private lateinit var cameraExecutor: ExecutorService private var imageCapture: ImageCapture? = null companion object { private const val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS" } constructor(context: Context) : super(context) { configureComponent(context) } constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { configureComponent(context) } constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { configureComponent(context) } private fun configureComponent(context: Context) { viewFinder.layoutParams = FrameLayout.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT ) installHierarchyFitter(viewFinder) addView(viewFinder) // Create Button button = Button(context).apply { id = View.generateViewId() text = "Start" elevation = 2f layoutParams = FrameLayout.LayoutParams( FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT ).apply { gravity = Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL bottomMargin = 10 } } addView(button) } private val REQUIRED_PERMISSIONS = mutableListOf(Manifest.permission.CAMERA).apply { if (Build.VERSION.SDK_INT Я также пытался сделать следующие вещи < /p> 1. override fun requestLayout() { super.requestLayout() post(measureAndLayout) } private val measureAndLayout = Runnable { measure( MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY) ) layout(left, top, right, bottom) } < /code> [list] [*] private val measureAndlayout = runnable { ream ( mameaspec.makemeasperspec(width, mearspec.exactly), measurespec.makemeaspec-(height.xactly), exactly), exactly), exactly), exactly), exactly) < /br /measerspec.makemeaspec- ceace.xactly). /> Layout (слева, вверху, справа, внизу) } < /p> переопределить веселье намеров (WidthMeasurespec: int, heightmeaspec: int) { var maxwidth = 0 var maxheight = 0 for (i in 0 in gildcount) {br /> gath = 0 for (i in 0 in gildcount) { gate) {br /> gate) (child.visibility! = Gone) { child.measure(widthmeasurespec, termespec.unspecifififified) maxwidth = maxwidth.coerceatleast (child.measuredwidth) maxheight = maxheight.coerceatles /> val finalwidth = maxwidth.coerceatleasteast (prevededminimumwidth) val finalheight = maxheight.coerceatleast (prevededminimumheight) setmeaseRedDimension (finalwidth, finalHeight) (контекст как TheMedReActContext). /> (контекст как TheMedReactContext) .getNativeModule (uimanagermodule :: class.java) ? Int, справа: int, внизу: int) { super.onlayout(Changed, слева, вверху, справа, внизу) вручные /> super.onmeasure(widthmeasurespec, heightmeaspecpec) measurechildren (widthmeasurespec, heightmeaspec) } < /p> < /li> override fun requestlayout () {br />super.RequestlAyout. /> post (measureAndlayout) } < /p> private val measureAndLayout = Runnable { measure( MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY) ) layout(left, top, right, bottom) } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { var maxWidth = 0 var maxHeight = 0 for (i in 0 until childCount) { val child = getChildAt(i) if (child.visibility != GONE) { child.measure(widthMeasureSpec, MeasureSpec.UNSPECIFIED) maxWidth = maxWidth.coerceAtLeast(child.measuredWidth) maxHeight = maxHeight.coerceAtLeast(child.measuredHeight) } } val finalWidth = maxWidth.coerceAtLeast(suggestedMinimumWidth) val finalHeight = maxHeight.coerceAtLeast(suggestedMinimumHeight) setMeasuredDimension(finalWidth, finalHeight) (context as ThemedReactContext).runOnNativeModulesQueueThread { (context as ThemedReactContext).getNativeModule(UIManagerModule::class.java) ?.updateNodeSize(id, finalWidth, finalHeight) } } [/code] [/list] Пробое использовал RELATIVELAYOU> Подробнее здесь: [url]https://stackoverflow.com/questions/79664703/embedding-native-android-camerax-in-react-native-always-shows-black-screen[/url]