react-native可以做web与原生的交互,这是使用react-native开发项目的主要目的之一,也是主要优势,用rn而不用原生交互则毫无价值,这篇文章用来记录在项目中rn的原生交互使用过程。

之前说过要做的是一个pda项目,所以今天以input获取焦点的时候禁止软键盘弹出为例,大体说一下rn的原生交互过程。

android的原生交互分为以下几步

  1. 编写原生代码
  2. 向js暴露原生接口
  3. 注册原生模块
  4. 导出并再rn导入原生,模块

1、编写原生模块

作为web工程师出身的我,对原生android代码是不太了解的,充其量也只是稍微了解点java语言,但是通过自己的努力,还是过来了(笑哭);根据需求,就是再刚一进入页面的时候,让第一个input获取焦点,并同时隐藏软键盘,前端代码很好写,就是在获取焦点之后调用隐藏软键盘的原生功能;搞清楚了需求之后就开始编写原生代码了。

如上图,在newpda目录下面新建BoardModule类文件,用来编写原生功能代码;这个类继承自 ReactContextBaseJavaModule,代码如下

package com.newpda;
import android.util.Log;
import android.widget.Toast;
import android.widget.EditText;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import java.lang.reflect.Method; import java.util.HashMap;
import java.util.Map;
import android.content.Context;
import android.app.Activity;
import android.app.ActivityManager;
import android.view.inputmethod.InputMethodManager;
import com.facebook.infer.annotation.Assertions;
import javax.annotation.Nullable; /**
* Description: Created by song on 2018/7/3. email:gaosongai@foxmail.com
*/
public class BoardModule extends ReactContextBaseJavaModule {
private final ReactApplicationContext reactContext;
public BoardModule(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext; // 获取上下文
} @Override
public String getName() {
return "BoardModule";
} /**
*    关闭Edittext软件盘,光标依然正常显示。 
*/
@ReactMethod
public void hideboard() {
Activity currentActivity = getCurrentActivity();
InputMethodManager mInputMethodManager = (InputMethodManager)
Assertions.assertNotNull(this.reactContext.getSystemService(Context.INPUT_METHOD_SERVICE));
mInputMethodManager.hideSoftInputFromWindow(currentActivity.getCurrentFocus().getWindowToken(), 0);
}
}

hideboard为隐藏软键盘的方法,并向js暴露hideboard方法,要导出一个方法给JavaScript使用,Java方法需要使用注解@ReactMethod

2、注册模块

然后注册原生模块,同级目录下新建CustomBoardPackage类,代码如下

package com.newpda;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; /**
* Description:
* Created by song on 2018/9/6.
* email:gaosongai@foxmail.com
*/
public class CustomBoardPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules=new ArrayList<>();
modules.add(new BoardModule(reactContext));
return modules;
} @Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}

我们需要在应用的Package类的createNativeModules方法中添加这个模块。如果模块没有被注册,它也无法在JavaScript中被访问到。

然后这个package需要在MainApplication.java文件的getPackages方法中提供,文件在同级目录下,代码如下

package com.newpda;

import android.app.Application;

import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader; import java.util.Arrays;
import java.util.List; public class MainApplication extends Application implements ReactApplication { private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
} @Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new CustomBoardPackage() // 刚刚添加的方法
);
} @Override
protected String getJSMainModuleName() {
return "index";
}
}; @Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
} @Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
}
}

3、在rn中引入模块

为了让你的功能从JavaScript端访问起来更为方便,通常我们都会把原生模块封装成一个JavaScript模块。这不是必须的,但省下了每次都从NativeModules中获取对应模块的步骤。这个JS文件也可以用于添加一些其他JavaScript端实现的功能,App.js同级目录下新建androidtoast.js,内容如下

import {NativeModules} from 'react-native';
module.exports = NativeModules.BoardModule;

然后在组件内部使用

import BoardModule from "../../../androidtoast";
BoardModule.hideboard(); // 使用原生模块方法

最新文章

  1. information_schema系列八(事物,锁)
  2. re模块使用
  3. javascript中call和apply方法
  4. Linux - CentOS6.5服务器搭建与初始化配置详解(上)
  5. Linux下CURL常用命令
  6. Nginx日志配置及日志切割
  7. 2017 UESTC Training for Graph Theory
  8. 201521123016 《Java程序设计》第8周学习总结
  9. 五、Hadoop学习笔记————调优之硬件选择
  10. [C#]使用Gembox.SpreadSheet向Excel写入数据及图表
  11. arm-linux-androideabi-4.8/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-g++: Command not found 解决方法
  12. LAMP第三部分php,mysql配置
  13. Linux定时任务深入学习
  14. 使用kbmmw 生成客户端delphi函数原型
  15. [POI2010]GRA-The Minima Game
  16. 精彩看点 | GIAC大会PPT+视频合集全量放送!
  17. Xpath做数据解析
  18. python颜色及背景
  19. equals与hashcode区别
  20. MFC CHotKeyCtrl控件

热门文章

  1. Learning Context Graph for Person Search
  2. ip地址掩码和位数对应关系表、子网掩码、网络地址、主机地址-yellowcong
  3. 使用ItextSharop合并pdf文件,体积变大的解决
  4. leetcode 266.Palindrome Permutation 、267.Palindrome Permutation II
  5. pm2 工具来管理 node 服务端
  6. 持久化机器学习模型(joblib方式)
  7. Java 解析XML数据
  8. [简短问答]SET_PRINT_STYLEA相关简短问答
  9. SecureCRT字体、界面优化
  10. SpringBoot整合AbstractRoutingDataSource实现读写分离