React-native нативный модуль с вложенными view
Мне необходимо сделать ui нативный модуль react-native для ios и android, содержащий вложенные друг в друга view:
+-----------------------+
| Wrapper native view |
| +--------------------+|
| | Inner native view ||
| | +-----------------+||
| | | React childs |||
| | +-----------------+||
| +--------------------+|
+-----------------------+
Внешний view должен содержать внутренний view в котором, в свою очередь, должны рендерится react компоненты.
Примеров с такой компоновкой я не встречал. Попадалась только следующая структура: Точка входа Manager (android - ViewGroupManager, ios - RCTViewManager) из которого создается один единственный view (android - ReactViewGroup, ios - RCTView) внутри которого рендерятся react компоненты. Каким образом мне сделать желаемое, как создать дополнительный вложенный view?
Буду благодарен примерам на swift/kotlin, с objective-c/java тоже разберусь.
Ответы (1 шт):
Создайте свой собственный менеджер для каждого из нативных View.Для ios нужно создать RCTViewManager и RCTView, который использует вложенный UIView. Для android вам нужно создать ViewGroupManager и ReactViewGroup.
пример для ios:
class InnerNativeView: RCTView {
override init(frame: CGRect) {
super.init(frame: frame)
// Код для инициализации вложенного UIView
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
@objc(InnerNativeViewManager)
class InnerNativeViewManager: RCTViewManager {
override func view() -> UIView! {
return InnerNativeView()
}
}
Потом надо регистрировать InnerNativeViewManager в JavaScript коде:
import { requireNativeComponent } from 'react-native';
const InnerNativeView = requireNativeComponent('InnerNativeView', null);
// Использование InnerNativeView в вашем компоненте
<InnerNativeView>
{/* Ваши React-компоненты */}
</InnerNativeView>
Еще можно использ. библиотеку с помощью npm или yarn:
npm install react-native-reanimated
Затем возьмите Animated.View, чтобы создать нативный View и использовать его в качестве контейнера для ваших React-компонентов:
import { View, Text } from 'react-native';
import Animated from 'react-native-reanimated';
function WrapperNativeView() {
return (
<Animated.View>
<View>
<Text>Inner Native View</Text>
</View>
{/* Ваши React-компоненты */}
</Animated.View>
);
}
Еще решение -это Modal компонент:
import { View, Modal } from 'react-native';
function WrapperNativeView() {
const [modalVisible, setModalVisible] = useState(false);
return (
<View>
<TouchableOpacity onPress={() => setModalVisible(true)}>
<Text>Open Modal</Text>
</TouchableOpacity>
<Modal
animationType="slide"
transparent={false}
visible={modalVisible}
onRequestClose={() => {
setModalVisible(false);
}}>
<View>
<Text>Inner Native View</Text>
{/* Ваши React-компоненты */}
</View>
</Modal>
</View>
);
}
P.S. Дополняю ответ в соответствии с замечанием. я предлагаю вам использовать существующую структуру с Manager и единственным View, но добавить еще один слой вложенности внутри этого View.
Для этого, вам необходимо создать новый класс нативного кода, который будет расширять существующий класс View (iOS: RCTView, Android: ReactViewGroup) и добавлять в него дополнительный вложенный View. Затем, вам нужно будет обновить Manager для использования этого нового класса View вместо стандартного.
На iOS:
// Создание нового класса для нативного View
class InnerNativeView: RCTView {
// Добавление вложенного View
let innerView: UIView = UIView()
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(innerView)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
// Обновление Manager для использования нового View
@objc(InnerNativeViewManager)
class InnerNativeViewManager: RCTViewManager {
override func view() -> UIView! {
return InnerNativeView()
}
}
На Android:
// Создание нового класса для нативного View
public class InnerNativeView extends ReactViewGroup {
// Добавление вложенного View
private View innerView;
public InnerNativeView(Context context) {
super(context);
innerView = new View(context);
addView(innerView);
}
}
// Обновление Manager для использования нового View
public class InnerNativeViewManager extends ViewGroupManager<InnerNativeView> {
public static final String REACT_CLASS = "InnerNativeView";
@Override
public String getName() {
return REACT_CLASS;
}
@Override
protected InnerNativeView createViewInstance(ThemedReactContext reactContext) {
return new InnerNativeView(reactContext);
}
}
В данном примере мы создаем класс InnerNativeView на нативном уровне, который расширяет существующий класс View и добавляет в него дополнительный вложенный View. Затем мы обновляем Manager для использования этого нового класса View вместо стандартного.