react-native手势及与java端交互应用
demo: https://github.com/wangzuxing/myrncommu
命令行创建项目工程、安装、关联组件
react-native init myrncommu
cd myrncommu
配置android工程
首先在android目录下加入local.properties(命令行创建工程,默认不包含该文件,指定android工程sdk目录sdk.dir)
android/app/src/main/java/[…]/MainApplication.java 中添加:
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
// 添加自定义ReactPackage至React Packager
);
}
MainApplication.java同级目录下创建MyReactPackage.java:
public class MyReactPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new MyNativeModule(reactContext));
//由ReactPackage统一添加本地模块至入本地模块列表
return modules;
}
@Override
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
MainApplication.java同级目录下创建MyNativeModule.java:
public class MyNativeModule extends ReactContextBaseJavaModule {
public static final String REACTCLASSNAME = "MyNativeModule";
private Context mContext;
public MyNativeModule(ReactApplicationContext reactContext) {
super(reactContext);
mContext = reactContext;
}
@Override
public String getName() {
return REACTCLASSNAME;
}
/**
* 必须添加反射注解不然会报错
* 这个方法就是ReactNative将要调用的方法,会通过此类名字调用
* @param msg
*/
@ReactMethod
public void callNativeMethod(String msg) {
Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();
}
@ReactMethod
public void tryCallBack(String name, String psw, Callback errorCallback, Callback successCallback){
try{
if(TextUtils.isEmpty(name) && TextUtils.isEmpty(psw)){
// 失败时回调
errorCallback.invoke("user or psw is empty");
}
// 成功时回调
successCallback.invoke("add user success");
sendEvent((ReactContext)mContext, "Native Module", "ok");
}catch(IllegalViewOperationException e){
// 失败时回调
errorCallback.invoke(e.getMessage());
}
}
@ReactMethod
public void tryPromise(String name, String psw, Promise promise){
try{
if(TextUtils.isEmpty(name) && TextUtils.isEmpty(psw)){
promise.reject("0","user name or psw is empty");
}
WritableMap map = Arguments.createMap();
map.putString("user_id", "JS invoke JAVA success!");
promise.resolve(map);
}catch(IllegalViewOperationException e){
promise.reject("2",e.getMessage());
}
}
public static void sendEvent(ReactContext reactContext, String eventName, String status)
{
System.out.println("reactContext="+reactContext);
reactContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName,status);
}
}
index.android.js 添加功能实现(导入相关功能组件):
//<Text style={styles.instructionson} onPress={() => this.onClick()}>
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Image,
PanResponder,
TouchableOpacity,
DeviceEventEmitter,
NativeModules
} from 'react-native';
class Mixture extends Component {
render() {
return (
<View style={styles.container} >
<Text style={styles.instructionson} onPress={() => this.onClick()}>
native method
</Text>
<TouchableOpacity
activeOpacity={0.5}
onPress={()=> this.onClick0()}>
<Image
source={require('./fruit0.png')}
style={{width: 70, height: 70}}
/>
</TouchableOpacity>
<TouchableOpacity
activeOpacity={0.5}
onPress={()=> this.onClick1()}>
<Image
source={require('./fruit1.png')}
style={{width: 70, height: 70}}
/>
</TouchableOpacity>
</View>
);
}
constructor(props) {
super(props);
this.state = {
eventName:'',
pos: '',
};
this.myPanResponder={}
}
componentWillMount() {
this.myPanResponder = PanResponder.create({
//Responder
onStartShouldSetPanResponder: (evt, gestureState) => true,
onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
onPanResponderTerminationRequest: (evt, gestureState) => true,
//Responder handle:
onPanResponderGrant: (evt, gestureState) => {
this.state.eventName='start';
this.forceUpdate();
alert(this.state.eventName);
},
onPanResponderMove: (evt, gestureState) => {
var _pos = 'x:' + gestureState.moveX + ',y:' + gestureState.moveY;
this.setState( {eventName:'move',pos : _pos} );
},
onPanResponderRelease: (evt, gestureState) => {
this.setState( {eventName:'up'} );
alert(this.state.eventName);
},
onPanResponderTerminate: (evt, gestureState) => {
this.setState( {eventName:'other new responser'} )
},
});
}
componentDidMount() {
//add listener
DeviceEventEmitter.addListener('Native Module',(message) => {
alert('JS receive Native Module data ' + message);
});
}
onClick0() {
NativeModules.MyNativeModule.tryCallBack("wangzuxing","35",(errorCallback)=>{
alert(errorCallback)},(successCallback)=>{
alert(successCallback);
});
}
onClick1() {
NativeModules.MyNativeModule.tryPromise('wang zux ing', '35').then((map)=> {
alert(map['user_id']);}, (code, message)=> {
alert(message);
});
}
//call Native Method
onClick() {
NativeModules.MyNativeModule.callNativeMethod('success invoke!');
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
padding: 10,
margin: 20,
fontSize: 25
},
});
AppRegistry.registerComponent('myrncommu', () => Mixture);
命令行执行(即开启packager, Running packager on port 8081):
react-native start
//浏览器地址栏输入:http://localhost:8081/index.android.bundle?platform=android,检测看packager是否启动完成
6、命令行执行(连接android真机/模拟器,新开命令窗口,进入到项目myrncommu目录下,输入如下指令):
react-native run-android