React Native is pretty strong with Native Modules. You aren't really limited to using JavaScript. However, documentation for native modules is not that great. You need to dig some functionalities yourself. ViewGroupManager is one of them.
I will assume that you are familiar with Native Modules and have developed at least one native module using SimpleViewManager<View>
https://facebook.github.io/react-native/docs/native-components-android
View's are great placeholders but they cannot contain other views. Let's say you have this simplest Native View.
public class NativeView extends SimpleViewManager<View> {
public static final String REACT_CLASS = "NativeView";
@Override
public String getName() {
return REACT_CLASS;
}
@Override
public View createViewInstance(ThemedReactContext context) {
View v = new View(context);
v.setBackgroundColor(Color.RED);
return v;
}
}
And call it using JS
const NativeView = requireNativeComponent('NativeView')
...
<NativeView style={{ height: 100, width: 100 }} />
You will see a square shape (100x100) view with red background. This is what we expect using the code. But if you change the JS code to below:
<NativeView style={{height: 100, width: 100}}>
<Text>I am a text view inside a native view</Text>
</NativeView>
you will get an error:
android.view.View cannot be cast to android.view.ViewGroup
This is because we are trying to add a textview inside a view. NativeView object is a simple Android View object. It cannot hold another view. Only ViewGroup can hold other views. You need to use layouts if you want to have parent-child relationship with views. Layout classes like LinearLayout or RelativeLayout etc. are sub classes of ViewGroup.
So instead of SimpleViewManager<View>
, we need to use ViewGroupManager<LinearLayout>
or ViewGroupManager<ViewGroup>
etc. Let's create a new class that extends LinearLayout:
public class NativeLinearLayout extends LinearLayout {
public NativeLinearLayout(Context context) {
super(context);
}
}
and call it from our main class that used to extend SimpleViewManager:
public class NativeView extends ViewGroupManager<NativeLinearLayout> {
public static final String REACT_CLASS = "NativeView";
@Override
public String getName() {
return REACT_CLASS;
}
@Override
public NativeLinearLayout createViewInstance(ThemedReactContext context) {
NativeLinearLayout nativeLinearLayout = new NativeLinearLayout(context);
return nativeLinearLayout;
}
}
This will work and insert the Text object created from JS into the NativeLinearLayout object.
We can also create another TextView from inside the native layout and combine them together:
But now since you're handling views a bit low level, React Native or CSS is not going to help with styling or the layouts. You need to handle it yourself using the native commands like setLayoutParams etc.
iOS equivalent of View is UIView and they can hold subviews. So, in iOS you don't need another solution. The default configuration of Native UI Components documentation will just work.