zoukankan      html  css  js  c++  java
  • (五)react-native开发系列之Android原生交互

    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();  // 使用原生模块方法
  • 相关阅读:
    MySQL数据库备份
    执行SDK的aapt报错./aapt: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ./aapt)
    ftp删除目录和文件,目录下有文件删除提示【550 Remove directory operation failed.】
    Spring mvc接收中文参数值乱码(tomcat配置问题)
    python3获得命令行输入的参数
    Java反射、动态加载(将java类名、方法、方法参数当做参数传递,执行方法)
    java定义object数组(可以存储String或int等多种类型)
    java方法中增加不固定参数
    ibatis和myBatis打印sql语句的log4j配置文件
    spring依赖注入之手工装配
  • 原文地址:https://www.cnblogs.com/gaosong-shuhong/p/9814981.html
Copyright © 2011-2022 走看看