From d9703b784f40decde0dadb568820f376bf10ab51 Mon Sep 17 00:00:00 2001 From: Rickard Zrinski Date: Sun, 10 Apr 2022 15:55:12 +0200 Subject: [PATCH 1/7] Update non-snippet references to Java --- docs/native-components-android.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/native-components-android.md b/docs/native-components-android.md index 8f02ea08ced..90ab50a6cc7 100644 --- a/docs/native-components-android.md +++ b/docs/native-components-android.md @@ -88,7 +88,7 @@ Setter declaration requirements for methods annotated with `@ReactPropGroup` are ### 4. Register the `ViewManager` -The final Java step is to register the ViewManager to the application, this happens in a similar way to [Native Modules](native-modules-android.md), via the applications package member function `createViewManagers.` +The final Java/Kotlin step is to register the ViewManager to the application, this happens in a similar way to [Native Modules](native-modules-android.md), via the applications package member function `createViewManagers.` ```java @Override @@ -102,7 +102,7 @@ The final Java step is to register the ViewManager to the application, this happ ### 5. Implement the JavaScript module -The very final step is to create the JavaScript module that defines the interface layer between Java and JavaScript for the users of your new view. It is recommended for you to document the component interface in this module (e.g. using Flow, TypeScript, or plain old comments). +The very final step is to create the JavaScript module that defines the interface layer between Java/Kotlin and JavaScript for the users of your new view. It is recommended for you to document the component interface in this module (e.g. using Flow, TypeScript, or plain old comments). ```jsx title="ImageView.js" import { requireNativeComponent } from 'react-native'; From 45debd25862f46d2f11f9844ba7fba1fd0f987c4 Mon Sep 17 00:00:00 2001 From: Rickard Zrinski Date: Sun, 10 Apr 2022 17:14:27 +0200 Subject: [PATCH 2/7] Add corresponding Kotlin types in non-snippets --- docs/native-components-android.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/native-components-android.md b/docs/native-components-android.md index 90ab50a6cc7..a088dcb4a73 100644 --- a/docs/native-components-android.md +++ b/docs/native-components-android.md @@ -57,13 +57,13 @@ Views are created in the `createViewInstance` method, the view should initialize ### 3. Expose view property setters using `@ReactProp` (or `@ReactPropGroup`) annotation -Properties that are to be reflected in JavaScript needs to be exposed as setter method annotated with `@ReactProp` (or `@ReactPropGroup`). Setter method should take view to be updated (of the current view type) as a first argument and property value as a second argument. Setter should be declared as a `void` method and should be `public`. Property type sent to JS is determined automatically based on the type of value argument of the setter. The following type of values are currently supported: `boolean`, `int`, `float`, `double`, `String`, `Boolean`, `Integer`, `ReadableArray`, `ReadableMap`. +Properties that are to be reflected in JavaScript needs to be exposed as setter method annotated with `@ReactProp` (or `@ReactPropGroup`). Setter method should take view to be updated (of the current view type) as a first argument and property value as a second argument. Setter should be declared as a `void` method in Java or with return type `Unit` (or omitted) in Kotlin and should be `public`. Property type sent to JS is determined automatically based on the type of value argument of the setter. The following type of values are currently supported (in Java): `boolean`, `int`, `float`, `double`, `String`, `Boolean`, `Integer`, `ReadableArray`, `ReadableMap`. The corresponding types in Kotlin are `Boolean`, `Int`, `Float`, `Double`, `String`, `ReadableArray`, `ReadableMap`. Annotation `@ReactProp` has one obligatory argument `name` of type `String`. Name assigned to the `@ReactProp` annotation linked to the setter method is used to reference the property on JS side. -Except from `name`, `@ReactProp` annotation may take following optional arguments: `defaultBoolean`, `defaultInt`, `defaultFloat`. Those arguments should be of the corresponding type (accordingly `boolean`, `int`, `float`) and the value provided will be passed to the setter method in case when the property that the setter is referencing has been removed from the component. Note that "default" values are only provided for primitive types, in case when setter is of some complex type, `null` will be provided as a default value in case when corresponding property gets removed. +Except from `name`, `@ReactProp` annotation may take following optional arguments: `defaultBoolean`, `defaultInt`, `defaultFloat`. Those arguments should be of the corresponding type (accordingly `boolean`, `int`, `float` in Java and `Boolean`, `Int`, `Float` in Kotlin) and the value provided will be passed to the setter method in case when the property that the setter is referencing has been removed from the component. Note that "default" values are only provided for primitive types, in case when setter is of some complex type, `null` will be provided as a default value in case when corresponding property gets removed. Setter declaration requirements for methods annotated with `@ReactPropGroup` are different than for `@ReactProp`, please refer to the `@ReactPropGroup` annotation class docs for more information about it. **IMPORTANT!** in ReactJS updating the property value will result in setter method call. Note that one of the ways we can update component is by removing properties that have been set before. In that case setter method will be called as well to notify view manager that property has changed. In that case "default" value will be provided (for primitive types "default" can value can be specified using `defaultBoolean`, `defaultFloat`, etc. arguments of `@ReactProp` annotation, for complex types setter will be called with value set to `null`). From 58546be6dffda09b70c1d38a73ad4dcc37d71d6b Mon Sep 17 00:00:00 2001 From: Rickard Zrinski Date: Sun, 10 Apr 2022 17:20:13 +0200 Subject: [PATCH 3/7] Add ReactImageManager examples in Kotlin --- docs/native-components-android.md | 81 +++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/docs/native-components-android.md b/docs/native-components-android.md index a088dcb4a73..96c458c924f 100644 --- a/docs/native-components-android.md +++ b/docs/native-components-android.md @@ -3,6 +3,8 @@ id: native-components-android title: Android Native UI Components --- +import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants'; + There are tons of native UI widgets out there ready to be used in the latest apps - some of them are part of the platform, others are available as third-party libraries, and still more might be in use in your very own portfolio. React Native has several of the most critical platform components already wrapped, like `ScrollView` and `TextInput`, but not all of them, and certainly not ones you might have written yourself for a previous app. Fortunately, we can wrap up these existing components for seamless integration with your React Native application. Like the native module guide, this too is a more advanced guide that assumes you are somewhat familiar with Android SDK programming. This guide will show you how to build a native UI component, walking you through the implementation of a subset of the existing `ImageView` component available in the core React Native library. @@ -27,6 +29,25 @@ To send a view: In this example we create view manager class `ReactImageManager` that extends `SimpleViewManager` of type `ReactImageView`. `ReactImageView` is the type of object managed by the manager, this will be the custom native view. Name returned by `getName` is used to reference the native view type from JavaScript. + + + +```kotlin +class ReactImageManager( + private val mCallerContext: ReactApplicationContext +) : SimpleViewManager() { + + override fun getName() = REACT_CLASS + + companion object { + const val REACT_CLASS = "RCTImageView" + } +} +``` + + + + ```java public class ReactImageManager extends SimpleViewManager { @@ -44,10 +65,24 @@ public class ReactImageManager extends SimpleViewManager { } ``` + + + ### 2. Implement method `createViewInstance` Views are created in the `createViewInstance` method, the view should initialize itself in its default state, any properties will be set via a follow up call to `updateView.` + + + +```kotlin + override fun createViewInstance(context: ThemedReactContext) = + ReactImageView(context, Fresco.newDraweeControllerBuilder(), null, mCallerContext) +``` + + + + ```java @Override public ReactImageView createViewInstance(ThemedReactContext context) { @@ -55,6 +90,9 @@ Views are created in the `createViewInstance` method, the view should initialize } ``` + + + ### 3. Expose view property setters using `@ReactProp` (or `@ReactPropGroup`) annotation Properties that are to be reflected in JavaScript needs to be exposed as setter method annotated with `@ReactProp` (or `@ReactPropGroup`). Setter method should take view to be updated (of the current view type) as a first argument and property value as a second argument. Setter should be declared as a `void` method in Java or with return type `Unit` (or omitted) in Kotlin and should be `public`. Property type sent to JS is determined automatically based on the type of value argument of the setter. The following type of values are currently supported (in Java): `boolean`, `int`, `float`, `double`, `String`, `Boolean`, `Integer`, `ReadableArray`, `ReadableMap`. The corresponding types in Kotlin are `Boolean`, `Int`, `Float`, `Double`, `String`, `ReadableArray`, `ReadableMap`. @@ -69,6 +107,29 @@ Setter declaration requirements for methods annotated with `@ReactPropGroup` are + + + +```kotlin + @ReactProp(name = "src") + fun setSrc(view: ReactImageView, sources: ReadableArray?) { + view.setSource(sources) + } + + @ReactProp(name = "borderRadius", defaultFloat = 0f) + override fun setBorderRadius(view: ReactImageView, borderRadius: Float) { + view.setBorderRadius(borderRadius) + } + + @ReactProp(name = ViewProps.RESIZE_MODE) + fun setResizeMode(view: ReactImageView, resizeMode: String?) { + view.setScaleType(ImageResizeMode.toScaleType(resizeMode)) + } +``` + + + + ```java @ReactProp(name = "src") public void setSrc(ReactImageView view, @Nullable ReadableArray sources) { @@ -86,10 +147,27 @@ Setter declaration requirements for methods annotated with `@ReactPropGroup` are } ``` + + + ### 4. Register the `ViewManager` The final Java/Kotlin step is to register the ViewManager to the application, this happens in a similar way to [Native Modules](native-modules-android.md), via the applications package member function `createViewManagers.` + + + +```kotlin + override fun createViewManagers( + reactContext: ReactApplicationContext + ): List> { + return listOf(ReactImageManager(reactContext)) + } +``` + + + + ```java @Override public List createViewManagers( @@ -100,6 +178,9 @@ The final Java/Kotlin step is to register the ViewManager to the application, th } ``` + + + ### 5. Implement the JavaScript module The very final step is to create the JavaScript module that defines the interface layer between Java/Kotlin and JavaScript for the users of your new view. It is recommended for you to document the component interface in this module (e.g. using Flow, TypeScript, or plain old comments). From 23270a9e6a40c30456c801321e135438f8c16356 Mon Sep 17 00:00:00 2001 From: Rickard Zrinski Date: Sun, 10 Apr 2022 17:26:03 +0200 Subject: [PATCH 4/7] Add Events examples in Kotlin --- docs/native-components-android.md | 48 +++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/docs/native-components-android.md b/docs/native-components-android.md index 96c458c924f..76e40509a45 100644 --- a/docs/native-components-android.md +++ b/docs/native-components-android.md @@ -204,6 +204,27 @@ The `requireNativeComponent` function takes the name of the native view. Note th So now we know how to expose native view components that we can control freely from JS, but how do we deal with events from the user, like pinch-zooms or panning? When a native event occurs the native code should issue an event to the JavaScript representation of the View, and the two views are linked with the value returned from the `getId()` method. + + + +```kotlin +class MyCustomView(context: Context) : View(context) { + ... + fun onReceiveNativeEvent() { + val event = Arguments.createMap().apply { + putString("message", "MyMessage") + } + val reactContext = context as ReactContext + reactContext + .getJSModule(RCTEventEmitter::class.java) + .receiveEvent(id, "topChange", event) + } +} +``` + + + + ```java class MyCustomView extends View { ... @@ -218,8 +239,32 @@ class MyCustomView extends View { } ``` + + + To map the `topChange` event name to the `onChange` callback prop in JavaScript, register it by overriding the `getExportedCustomBubblingEventTypeConstants` method in your `ViewManager`: + + + +```kotlin +class ReactImageManager : SimpleViewManager() { + ... + override fun getExportedCustomBubblingEventTypeConstants(): Map { + return mapOf( + "topChange" to mapOf( + "phasedRegistrationNames" to mapOf( + "bubbled" to "onChange" + ) + ) + ) + } +} +``` + + + + ```java public class ReactImageManager extends SimpleViewManager { ... @@ -235,6 +280,9 @@ public class ReactImageManager extends SimpleViewManager { } ``` + + + This callback is invoked with the raw event, which we typically process in the wrapper component to make a simpler API: ```jsx title="MyCustomView.js" From 9fc8167505ae58bf0fb534c545b9ee16d0aad12a Mon Sep 17 00:00:00 2001 From: Rickard Zrinski Date: Sun, 10 Apr 2022 17:28:09 +0200 Subject: [PATCH 5/7] Add Android Fragment examples in Kotlin --- docs/native-components-android.md | 243 ++++++++++++++++++++++++++++++ 1 file changed, 243 insertions(+) diff --git a/docs/native-components-android.md b/docs/native-components-android.md index 76e40509a45..a13da346734 100644 --- a/docs/native-components-android.md +++ b/docs/native-components-android.md @@ -320,6 +320,34 @@ In order to integrate existing Native UI elements to your React Native app, you First, let's create a `CustomView` class which extends `FrameLayout` (the content of this view can be any view that you'd like to render) + + + +```kotlin title="CustomView.kt" +package com.mypackage + +import android.content.Context +import android.graphics.Color +import android.widget.FrameLayout +import android.widget.TextView + +class CustomView(context: Context) : FrameLayout(context) { + init { + // set padding and background color + setPadding(16,16,16,16) + setBackgroundColor(Color.parseColor("#5FD3F3")) + + // add default text view + addView(TextView(context).apply { + text = "Welcome to Android Fragments with React Native." + }) + } +} +``` + + + + ```java title="CustomView.java" // replace with your package package com.mypackage; @@ -347,8 +375,65 @@ public class CustomView extends FrameLayout { } ``` + + + ### 2. Create a `Fragment` + + + +```kotlin title="MyFragment.kt" +// replace with your package +package com.mypackage + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment + +// replace with your view's import +import com.mypackage.CustomView + +class MyFragment : Fragment() { + private lateinit var customView: CustomView + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + super.onCreateView(inflater, container, savedInstanceState) + customView = CustomView(requireNotNull(context)) + return customView // 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: + // customView.onCreate(savedInstanceState); + } + + override fun onPause() { + super.onPause() + // do any logic that should happen in an `onPause` method + // e.g.: customView.onPause(); + } + + override fun onResume() { + super.onResume() + // do any logic that should happen in an `onResume` method + // e.g.: customView.onResume(); + } + + override fun onDestroy() { + super.onDestroy() + // do any logic that should happen in an `onDestroy` method + // e.g.: customView.onDestroy(); + } +} +``` + + + + ```java title="MyFragment.java" // replace with your package package com.mypackage; @@ -402,8 +487,121 @@ public class MyFragment extends Fragment { } ``` + + + ### 3. Create the `ViewManager` subclass + + + +```kotlin title="MyViewManager.kt" +// replace with your package +package com.mypackage + +import android.view.Choreographer +import android.view.View +import android.view.ViewGroup +import android.widget.FrameLayout +import androidx.fragment.app.FragmentActivity +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.ReadableArray +import com.facebook.react.uimanager.ThemedReactContext +import com.facebook.react.uimanager.ViewGroupManager +import com.facebook.react.uimanager.annotations.ReactPropGroup +import kotlin.properties.Delegates + +class MyViewManager( + private val reactContext: ReactApplicationContext +) : ViewGroupManager() { + private var propWidth by Delegates.notNull() + private var propHeight by Delegates.notNull() + + override fun getName() = REACT_CLASS + + /** + * Return a FrameLayout which will later hold the Fragment + */ + override fun createViewInstance(reactContext: ThemedReactContext) = + FrameLayout(reactContext) + + /** + * Map the "create" command to an integer + */ + override fun getCommandsMap() = mapOf("create" to COMMAND_CREATE) + + /** + * Handle "create" command (called from JS) and call createFragment method + */ + 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) + } + } + + @ReactPropGroup(names = ["width", "height"], customType = "Style") + fun setStyle(view: FrameLayout, index: Int, value: Int) { + if (index == 0) propWidth = value + if (index == 1) propHeight = value + } + + /** + * Replace your React Native view with a custom fragment + */ + fun createFragment(root: FrameLayout, reactNativeViewId: Int) { + val parentView = root.findViewById(reactNativeViewId) + setupLayout(parentView) + + val myFragment = MyFragment() + val activity = reactContext.currentActivity as FragmentActivity + activity.supportFragmentManager + .beginTransaction() + .replace(reactNativeViewId, myFragment, reactNativeViewId.toString()) + .commit() + } + + fun setupLayout(view: View) { + Choreographer.getInstance().postFrameCallback(object: Choreographer.FrameCallback { + override fun doFrame(frameTimeNanos: Long) { + manuallyLayoutChildren(view) + view.viewTreeObserver.dispatchOnGlobalLayout() + Choreographer.getInstance().postFrameCallback(this) + } + }) + } + + /** + * Layout all children properly + */ + private fun manuallyLayoutChildren(view: View) { + // propWidth and propHeight coming from react-native props + val width = propWidth + val height = propHeight + + view.measure( + View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)) + + view.layout(0, 0, width, height) + } + + companion object { + private const val REACT_CLASS = "MyViewManager" + private const val COMMAND_CREATE = 1 + } +} +``` + + + + ```java title="MyViewManager.java" // replace with your package package com.mypackage; @@ -536,8 +734,35 @@ public class MyViewManager extends ViewGroupManager { } ``` + + + ### 4. Register the `ViewManager` + + + +```kotlin title="MyPackage.kt" +// replace with your package +package com.mypackage + +import com.facebook.react.ReactPackage +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.uimanager.ViewManager + +class MyPackage : ReactPackage { + ... + override fun createViewManagers( + reactContext: ReactApplicationContext + ): List> { + return listOf(MyViewManager(reactContext)) + } +} +``` + + + + ```java title="MyPackage.java" // replace with your package package com.mypackage; @@ -561,8 +786,23 @@ public class MyPackage implements ReactPackage { } ``` + + + ### 5. Register the `Package` + + + +```kotlin title="MainApplication.kt" + override fun getPackages() = PackageList(this).packages.apply { + add(MyPackage()) + } +``` + + + + ```java title="MainApplication.java" @Override protected List getPackages() { @@ -573,6 +813,9 @@ public class MyPackage implements ReactPackage { } ``` + + + ### 6. Implement the JavaScript module I. Start with custom View manager: From 5c12bc3414031b35e477ea4b53dfe70f5e8fd89d Mon Sep 17 00:00:00 2001 From: Rickard Zrinski Date: Sun, 10 Apr 2022 18:38:40 +0200 Subject: [PATCH 6/7] Add missing comment to CustomView.kt --- docs/native-components-android.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/native-components-android.md b/docs/native-components-android.md index a13da346734..3d8ac6bc1c3 100644 --- a/docs/native-components-android.md +++ b/docs/native-components-android.md @@ -324,6 +324,7 @@ First, let's create a `CustomView` class which extends `FrameLayout` (the conten ```kotlin title="CustomView.kt" +// replace with your package package com.mypackage import android.content.Context From e688f94d6a331aa7bb386157d7fc2e4f8200a129 Mon Sep 17 00:00:00 2001 From: Rickard Zrinski Date: Sun, 17 Apr 2022 22:56:12 +0200 Subject: [PATCH 7/7] Make improvements based on feedback --- docs/native-components-android.md | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/docs/native-components-android.md b/docs/native-components-android.md index 3d8ac6bc1c3..4e360f964f4 100644 --- a/docs/native-components-android.md +++ b/docs/native-components-android.md @@ -34,7 +34,7 @@ In this example we create view manager class `ReactImageManager` that extends `S ```kotlin class ReactImageManager( - private val mCallerContext: ReactApplicationContext + private val callerContext: ReactApplicationContext ) : SimpleViewManager() { override fun getName() = REACT_CLASS @@ -77,7 +77,7 @@ Views are created in the `createViewInstance` method, the view should initialize ```kotlin override fun createViewInstance(context: ThemedReactContext) = - ReactImageView(context, Fresco.newDraweeControllerBuilder(), null, mCallerContext) + ReactImageView(context, Fresco.newDraweeControllerBuilder(), null, callerContext) ``` @@ -95,7 +95,7 @@ Views are created in the `createViewInstance` method, the view should initialize ### 3. Expose view property setters using `@ReactProp` (or `@ReactPropGroup`) annotation -Properties that are to be reflected in JavaScript needs to be exposed as setter method annotated with `@ReactProp` (or `@ReactPropGroup`). Setter method should take view to be updated (of the current view type) as a first argument and property value as a second argument. Setter should be declared as a `void` method in Java or with return type `Unit` (or omitted) in Kotlin and should be `public`. Property type sent to JS is determined automatically based on the type of value argument of the setter. The following type of values are currently supported (in Java): `boolean`, `int`, `float`, `double`, `String`, `Boolean`, `Integer`, `ReadableArray`, `ReadableMap`. The corresponding types in Kotlin are `Boolean`, `Int`, `Float`, `Double`, `String`, `ReadableArray`, `ReadableMap`. +Properties that are to be reflected in JavaScript needs to be exposed as setter method annotated with `@ReactProp` (or `@ReactPropGroup`). Setter method should take view to be updated (of the current view type) as a first argument and property value as a second argument. Setter should be public and not return a value (i.e. return type should be `void` in Java or `Unit` in Kotlin). Property type sent to JS is determined automatically based on the type of value argument of the setter. The following type of values are currently supported (in Java): `boolean`, `int`, `float`, `double`, `String`, `Boolean`, `Integer`, `ReadableArray`, `ReadableMap`. The corresponding types in Kotlin are `Boolean`, `Int`, `Float`, `Double`, `String`, `ReadableArray`, `ReadableMap`. Annotation `@ReactProp` has one obligatory argument `name` of type `String`. Name assigned to the `@ReactProp` annotation linked to the setter method is used to reference the property on JS side. @@ -152,7 +152,7 @@ Setter declaration requirements for methods annotated with `@ReactPropGroup` are ### 4. Register the `ViewManager` -The final Java/Kotlin step is to register the ViewManager to the application, this happens in a similar way to [Native Modules](native-modules-android.md), via the applications package member function `createViewManagers.` +The final step is to register the ViewManager to the application, this happens in a similar way to [Native Modules](native-modules-android.md), via the applications package member function `createViewManagers`. @@ -160,9 +160,7 @@ The final Java/Kotlin step is to register the ViewManager to the application, th ```kotlin override fun createViewManagers( reactContext: ReactApplicationContext - ): List> { - return listOf(ReactImageManager(reactContext)) - } + ) = listOf(ReactImageManager(reactContext)) ``` @@ -510,13 +508,12 @@ import com.facebook.react.bridge.ReadableArray import com.facebook.react.uimanager.ThemedReactContext import com.facebook.react.uimanager.ViewGroupManager import com.facebook.react.uimanager.annotations.ReactPropGroup -import kotlin.properties.Delegates class MyViewManager( private val reactContext: ReactApplicationContext ) : ViewGroupManager() { - private var propWidth by Delegates.notNull() - private var propHeight by Delegates.notNull() + private var propWidth: Int? = null + private var propHeight: Int? = null override fun getName() = REACT_CLASS @@ -583,8 +580,8 @@ class MyViewManager( */ private fun manuallyLayoutChildren(view: View) { // propWidth and propHeight coming from react-native props - val width = propWidth - val height = propHeight + val width = requireNotNull(propWidth) + val height = requireNotNull(propHeight) view.measure( View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY), @@ -755,9 +752,7 @@ class MyPackage : ReactPackage { ... override fun createViewManagers( reactContext: ReactApplicationContext - ): List> { - return listOf(MyViewManager(reactContext)) - } + ) = listOf(MyViewManager(reactContext)) } ```