集成Android Fragment在react native的结构架构中导致空白视图

hrirmatl  于 2023-03-16  发布在  Android
关注(0)|答案(1)|浏览(143)

bounty将在4天后过期。回答此问题可获得+500声望奖励。BraveEvidence希望引起更多人关注此问题。

我正在尝试将Android Fragment与react native的新架构结构集成。我正在遵循here上的指南,不幸的是,他们没有指定任何用于集成fragment的文档,因此我正在here上从旧架构中获取帮助
我创建了以下Kotlin文件,添加typescript接口的其余代码保持不变

class CenteredText(context: Context): LinearLayout(context){

    private var textView: TextView
    private var secondtextView: TextView

    init {
        val layoutParams: ViewGroup.LayoutParams =
            LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
        setLayoutParams(layoutParams)
        orientation = VERTICAL

        textView = TextView(context)
        addView(textView)

        secondtextView = TextView(context)
        addView(secondtextView)
        secondtextView.text = "Hello I am second"
        secondtextView.textSize = 25F
        secondtextView.setTextColor(Color.RED)
    }

    fun configureText(text: String){
        textView.text = text
    }

}

class CenteredTextManager(private val context: ReactApplicationContext) :
    ViewGroupManager<FrameLayout>() {

    private val create = "create"
    private var propWidth: Int? = null
    private var propHeight: Int? = null

    override fun getName(): String {
        return NAME
    }

    override fun createViewInstance(reactContext: ThemedReactContext) = FrameLayout(reactContext)

    companion object {
        const val NAME = "RTNCenteredText"
        private const val COMMAND_CREATE = 1
    }

    override fun getCommandsMap() = mapOf(create to COMMAND_CREATE)

    override fun receiveCommand(root: FrameLayout, commandId: String?, args: ReadableArray?) {
        super.receiveCommand(root, commandId, args)
        val reactNativeViewId = requireNotNull(args).getInt(0)
        Log.i("argumentsare", args.toString())

        when (commandId?.toInt()) {
            COMMAND_CREATE -> createFragment(root, reactNativeViewId)
        }
    }

    private fun setupLayout(view: View) {
        Choreographer.getInstance().postFrameCallback(object : Choreographer.FrameCallback {
            override fun doFrame(frameTimeNanos: Long) {
                manuallyLayoutChildren(view)
                view.viewTreeObserver.dispatchOnGlobalLayout()
                Choreographer.getInstance().postFrameCallback(this)
            }
        })
    }

    private fun manuallyLayoutChildren(view: View) {
        // propWidth and propHeight coming from react-native props
        val width = requireNotNull(propWidth)
        val height = requireNotNull(propHeight)

        view.measure(
            View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
            View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)
        )

        view.layout(0, 0, width, height)
    }

    private fun createFragment(root: FrameLayout, reactNativeViewId: Int) {
        val parentView = root.findViewById<ViewGroup>(reactNativeViewId)
        setupLayout(parentView)

        val myFragment = CenteredTextFragment()
        val activity = context.currentActivity as FragmentActivity
        activity.supportFragmentManager
            .beginTransaction()
            .replace(reactNativeViewId, myFragment, reactNativeViewId.toString())
            .commit()
    }
}

class CenteredTextFragment: Fragment() {
    private lateinit var centeredText: CenteredText

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        super.onCreateView(inflater, container, savedInstanceState)
        centeredText = CenteredText(requireNotNull(context))
        return centeredText // this CustomView could be any view that you want to render
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

    }



    override fun onDestroy() {
        super.onDestroy()
    }
}

class CenteredTextPackage : ReactPackage {
    override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
        return Collections.singletonList(CenteredTextManager(reactContext))
    }

    override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
        return emptyList()
    }
}

完整的源代码在here

kadbb459

kadbb4591#

尝试设置
com.facebook.react.bridge.UiThreadUtil#assertOnUiThread
在做之前
添加到后栈()。

import com.facebook.react.bridge.UiThreadUtil;

if (UiThreadUtil.isOnUiThread()) {
    // do what you need to do here
}

另一个可能的解决方案是覆盖片段中的onResumeonPause函数,并强制它们分别调用getReactInstanceManager().onHostResume(getActivity(), this);getReactInstanceManager().onHostPause(getActivity());

@Override 
public void onResume() {
   super.onResume();
   if (mReactInstanceManager != null) 
       mReactInstanceManager.onHostResume(getActivity(), this);
   }

@Override 
public void onPause() {
   super.onPause();
   if (mReactInstanceManager != null)
       mReactInstanceManager.onHostPause(getActivity());
   }

或者,如果您不想使用Fabric,请更改应用程序onCreate方法ReactNativeHost.getUseFabric()以返回false

@Override
protected boolean getUseFabric() {
   return false;
}

相关问题