在使用rn开发时,笔者遇到过这样一个需求:已有的原生页面,需要进行改版,而这个改版比较小,只是加一个ImageView,因为部门有ios的同事,而且当时已经用了rn这门技术。因此,希望这个ImageView用rn来实现。那么,我们如何在一个纯原生的页面中调用rn控件呢?
前面几篇文章,我们都是在一个rn的页面中使用rn的控件。这次,笔者就带大家来实现这个功能——在原生页面中调用rn控件。
思路很简单:我们在原生新建一个ViewGroup,用这个ViewGroup在承载rn的控件就行了。
首先,我们新建一个纯原生的页面
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SecondActivity"
tools:ignore="MissingDefaultResource">
<FrameLayout
android:id="@+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
然后,我们新建一个类来封装相关的rn逻辑:
package com.example.demo;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactRootView;
/**
* Created by brett.li
* on 2022/10/26
*/
public class RNView {
private ReactRootView mReactRootView;
private ReactInstanceManager mReactInstanceManager;
private Activity activity;
private Bundle bundle;
public RNView(Activity activity){
this.activity = activity;
this.init();
}
public ReactRootView getContant() {
return mReactRootView;
}
private void init(){
try {
mReactRootView = new ReactRootView(this.activity);
mReactInstanceManager = ((ReactApplication)this.activity.getApplicationContext()).getReactNativeHost().getReactInstanceManager();
bundle = new Bundle();//作为rn控件的属性
bundle.putString("test","test");
mReactRootView.startReactApplication(mReactInstanceManager,"MyReactNativeApp",bundle);
}catch (Exception exception){
Log.e("RNView","error");
}
}
}
最后,在原生页面中调用即可
package com.example.demo;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
public class SecondActivity extends BaseActivity {
private FrameLayout frameLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
frameLayout = findViewById(R.id.frameLayout);
RNView rnView = new RNView(this);
frameLayout.addView(rnView.getContant());
}
}
rn端代码:
import React from "react";
import {
DeviceEventEmitter,
NativeEventEmitter,
NativeModules,
Platform,
requireNativeComponent,
StyleSheet,
Text, ToastAndroid,
TouchableOpacity,
View
} from "react-native";
const RCTTextView = (Platform.OS === 'android') ? requireNativeComponent('RCTTextView') : null;
const NWebview = (Platform.OS === 'android') ? requireNativeComponent('WebView') : null;
const styles = StyleSheet.create({
container: {
// flex: 1,
justifyContent: 'center',
alignItems:'center'
},
hello: {
fontSize: 20,
textAlign: 'center',
margin: 10
}
});
interface Props{
test:string
}
interface State{
test:string
}
export class HelloWorld extends React.Component<Props,State> {
constructor(props:Props) {
super(props);
this.state={
test:props.test
}
ToastAndroid.show("test is "+this.props.test,ToastAndroid.SHORT)
}
render() {
return (
<View style={styles.container}>
<Text style={styles.hello}>{this.state.test}</Text>
</View>
);
}
}
//index.js
AppRegistry.registerComponent(
'MyReactNativeApp',
() => HelloWorld
);