簡體   English   中英

在 UIManager 中找不到 requireNativeComponent

[英]requireNativeComponent was not found in UIManager

我知道這個問題已經被問過很多次了,但是所有的問題都是指在react-native應用程序中集成第三方依賴項,但就我而言,這是因為我自己的本機代碼,我在如何修復它時遇到了問題。 我正在使用react-native 0.69

這是我的代碼片段

CealScanQrView.kt

class CealScanQrView(context: Context): FrameLayout(context) {
...
//Contains all the logic of integrating camerax, check below code repo to see the full source code 
...
}

CealScanQrFragment.kt

class CealScanQrFragment: Fragment() {
    private lateinit var cealScanQrView: CealScanQrView

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

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // do any logic that should happen in an `onCreate` method, e.g:
        cealScanQrView.setUpCamera(requireActivity())
    }

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


CealScanQrViewManager.kt

class CealScanQrViewManager(
    private val reactContext: ReactApplicationContext
) : ViewGroupManager<FrameLayout>() {

    private val cealScanQrView = "CealScanQrView"
    private val topChange = "topChange"
    private val phasedRegistrationNames = "phasedRegistrationNames"
    private val bubbled = "bubbled"
    private val onChange = "onChange"
    private val create = "create"

    companion object {
        private const val COMMAND_CREATE = 1
    }

    private var propWidth: Int? = null
    private var propHeight: Int? = null

    override fun getName() = cealScanQrView

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

    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)

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

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

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

    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)
            }
        })
    }

    @ReactPropGroup(names = ["width", "height"], customType = "Style")
    fun setStyle(view: FrameLayout, index: Int, value: Int) {
        if (index == 0) propWidth = value
        if (index == 1) propHeight = value
    }

    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)
    }


    override fun getExportedCustomBubblingEventTypeConstants(): Map<String, Any> {
        return mapOf(
            topChange to mapOf(
                phasedRegistrationNames to mapOf(
                    bubbled to onChange
                )
            )
        )
    }
}

JS方面

我創建了一個CealScanQrViewManager.tsx文件

import {requireNativeComponent} from 'react-native';

export const CealScanQrViewManager = requireNativeComponent(
  'CealScanQrViewManager',
);

在 App.tsx 中

const createFragment = (viewId: number | null) =>
  UIManager.dispatchViewManagerCommand(
    viewId,
    // we are calling the 'create' command
    UIManager.CealScanQrViewManager.Commands.create.toString(),
    [viewId],
  );

const App = () => {
  const isDarkMode = useColorScheme() === 'dark';
  const [isCameraPermissionGranted, setIsCameraPermissionGranted] =
    useState(false);

  const backgroundStyle = {
    backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
  };

  const ref = useRef(null);

  useEffect(() => {
    requestCameraPermission();
  }, []);

  useEffect(() => {
    if (isCameraPermissionGranted) {
      const viewId = findNodeHandle(ref.current);
      createFragment(viewId);
    }
  }, [isCameraPermissionGranted]);

  const requestCameraPermission = async () => {
    try {
      const granted = await PermissionsAndroid.request(
        PermissionsAndroid.PERMISSIONS.CAMERA,
        {
          title: 'Cool Photo App Camera Permission',
          message:
            'Cool Photo App needs access to your camera ' +
            'so you can take awesome pictures.',
          buttonNeutral: 'Ask Me Later',
          buttonNegative: 'Cancel',
          buttonPositive: 'OK',
        },
      );
      if (granted === PermissionsAndroid.RESULTS.GRANTED) {
        setIsCameraPermissionGranted(true);
      } else {
        console.log('Camera permission denied');
      }
    } catch (err) {
      console.warn(err);
    }
  };

  const readQr = async (data: any) => {
    console.log(data.nativeEvent.qrCode);
  };

  return (
    <SafeAreaView style={backgroundStyle}>
      <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={{flex: 1, backgroundColor: 'red'}} />
      )}
    </SafeAreaView>
  );
};

一旦我授予相機權限,我就會收到錯誤消息

requireNativeComponent CealScanQrViewManager was not found in UIManager

在此處輸入圖像描述

有點刺眼的答案,但我認為一個正確的答案:本機組件的官方指南讓您注冊一個視圖管理器,這是一個 class 覆蓋getName以返回固定字符串,然后傳遞相同的字符串到requireNativeComponent

在您鏈接的存儲庫中,這些名稱不匹配。 requireNativeComponent('CealScanQrViewManager') ,但將其注冊為"CealScanQrView" 正如官方指南解釋的那樣,

getName返回的名稱用於引用來自 JavaScript 的原生視圖類型。

如果名稱不匹配,難怪查找類型失敗。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM