美文网首页Android技术分享Android技术知识React Native实践
如何创建一个android的react-native组件(一)

如何创建一个android的react-native组件(一)

作者: alexis_zyp | 来源:发表于2015-12-18 10:44 被阅读1981次

    刚刚接触react-native不到一月,从一开始照着React Native上文档的例子熟悉每一个控件的使用,到页面跳转,跳转到android原生Activity,再到自己实现一些简单的原生的android react-native组件,这是我上传到npm的两个组件(react-native-gotoactivity-android 和react-native-segmented-android),可以使用下面的命令下载

    $ npm install react-native-segmented-android --save
    $ npm install react-native-gotoactivity-android --save
    

    先说一下实现原理,如果是实现类似与Android的Toast与Dialog等一般继承ReactContextBaseJavaModule来实现,如果是ViewGroup类型(有子View)的,例如ScrollView等则继承ViewGroupManager,如果是View类型(无子View)例如Text,Image等则继承BaseViewManager 或者SimpleViewManager等。

    我们以ToastAndroid为例子,来讲解如何创建原生android react-native组件,其实facebook官方团队已经实现了,这个比较简单,容易理解。其实我主要就是说明实现的步骤;如有错误,请大家多多反馈。希望与大家共同学习进步。

    开始

    Step 1 - 新建react-native工程 ReactNativeToastAndroid

    $ react-native init ReactNativeToastAndroid
    

    Step 2 - 将新建的工程导入android studio然后新建空library(以react-native-toast-android为library的名称)之所以要新建一个library而不在ReactNativeToastAndroid工程中写呢,主要是为了方便上传到npm及github上方便其他开发者使用,一般以react-native-xxx-android命名方便识别这是react-native组件。

    Step 3 - 新建空library(以react-native-toast-android为library的名称)
    在library目录下的build.gradle中添加react-native的依赖

    // file: android/react-native-toast-android/build.gradle
    ...
    
    dependencies {
        ...
        compile 'com.facebook.react:react-native:0.16.+' 
    }
    

    Step 4 - 继承ReactContextBaseJavaModule ,大家可以很明显的发现show()方法上多了一个‘@ReactMethod’,加上了‘@ReactMethod'的方法可以被js调用。

    public class AndroidToastModule extends ReactContextBaseJavaModule {
    
        private static final String DURATION_SHORT_KEY = "SHORT";
        private static final String DURATION_LONG_KEY = "LONG";
    
        public AndroidToastModule(ReactApplicationContext reactContext) {
            super(reactContext);
        }
    
        @Override
        public String getName() {
            return "ToastForAndroid";
        }
    
        @Override
        public Map<String, Object> getConstants() {
            final Map<String, Object> constants = MapBuilder.newHashMap();
            constants.put(DURATION_SHORT_KEY, Toast.LENGTH_SHORT);
            constants.put(DURATION_LONG_KEY, Toast.LENGTH_LONG);
            return constants;
        }
    
        @ReactMethod
        public void show(String message, int duration) {
            Toast.makeText(getReactApplicationContext(), message, duration).show();
        }
    }
    

    Step 5 - 继承ReactPackage,注意createNativeModules()返回的是加入了 AndroidToastModule 的集合,createJSModules()与createViewManagers()返回的都是空集合,如果Step 4 步继承的是BaseViewManager或其子类,那么createViewManagers()中返回的就是加入了BaseViewManager的集合,其他的就是空集合,一般情况createJSModules()的返回值都是空集合。

    public class AndroidToastPackage implements ReactPackage {
    
        @Override
        public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
            return Arrays.<NativeModule>asList(new AndroidToastModule(reactContext));
        }
    
        @Override
        public List<Class<? extends JavaScriptModule>> createJSModules() {
            return Collections.emptyList();
        }
    
        @Override
        public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
            return Collections.emptyList();
        }
    }
    

    Step 6 - 新建ToastForAndroid.js,文件位置
    ‘ android/react-native-toast-android/ToastForAndroid.js ’代码如下,然后在 ‘android/react-native-toast-android/’下运行如下命令生成package.json文件

    $ npm init      //生成package.json文件
    
    'use strict';
    
    var RCTToastAndroid = require('NativeModules').ToastForAndroid;
    
    
    var ToastForAndroid = {
    
      SHORT: RCTToastAndroid.SHORT,
      LONG: RCTToastAndroid.LONG,
    
      show: function (
        message: string,
        duration: number
      ): void {
        RCTToastAndroid.show(message, duration);
      },
    
    };
    
    module.exports = ToastForAndroid;
    

    Step 7 - 复制ToastForAndroid.js 文件到‘/ReactNativeToastAndroid/ ’ 目录下,如下是index.android.js代码,然后运行测试

    'use strict';
     
    var React = require('react-native');
    var {
      AppRegistry,
      StyleSheet,
      Text,
      Dimensions,
      TouchableHighlight,
      View,
    } = React;
     
    // var ToastForAndroid = require('react-native-toast-android');
    var ToastForAndroid = require('./ToastForAndroid');
    var deviceWidth = Dimensions.get('window').width;
    var deviceHeight = Dimensions.get('window').height;
     
    var ReactNativeSegmentedExample = React.createClass({
       _onPressButton:function(){
              ToastForAndroid.show('点击了!', ToastAndroid.SHORT)
          }); 
       },
      render: function() {
        return (
          renderButton: function() {
            return (
              <TouchableHighlight onPress={this._onPressButton}>
                <Text style={{width:deviceWidth,height:50}}>click goto activity</Text>
              </TouchableHighlight>
            );
          },
        );
      }
    });
    ...
    

    Step 9 - 测试成功,在目录‘ /android/react-native-toast-android/ ’下运行命令:

    $ npm adduser   //增加npm用户
    $ npm publish   //上传react-naive-toast-android到npm上
    

    Step 10 - 其他开发者使用你上传到npm上的组件方法(github上的模板)

    Example

    'use strict';
     
    var React = require('react-native');
    var {
      AppRegistry,
      StyleSheet,
      Text,
      Dimensions,
      TouchableHighlight,
      View,
    } = React;
     
    var ToastForAndroid = require('react-native-toast-android');
    // var ToastForAndroid = require('./ToastForAndroid');
    var deviceWidth = Dimensions.get('window').width;
    var deviceHeight = Dimensions.get('window').height;
     
    var ReactNativeSegmentedExample = React.createClass({
       _onPressButton:function(){
              ToastForAndroid.show('点击了!', ToastAndroid.SHORT)
          }); 
       },
      render: function() {
        return (
          renderButton: function() {
            return (
              <TouchableHighlight onPress={this._onPressButton}>
                <Text style={{width:deviceWidth,height:50}}>click goto activity</Text>
              </TouchableHighlight>
            );
          },
        );
      }
    });
    ...
    
    

    Install

    Step 1 - Install the npm package

    $ npm install react-native-toast-android --save
    

    Step 2 - Update Gradle Settings

    // file: android/settings.gradle
    ...
    
    include ':react-native-toast-android', ':app'
    project(':react-native-toast-android').projectDir = new File(rootProject.projectDir,'../node_modules/react-native-toast-android')
    

    Step 3 - Update app Gradle Build

    // file: android/app/build.gradle
    ...
    
    dependencies {
        ...
        compile project(':react-native-toast-android')
    }
    

    Step 4 - Register React Package

    ...
    import com.higo.zhangyp.toast.AndroidForToastPackage; // <-- import
    
    public class MainActivity extends FragmentActivity implements DefaultHardwareBackBtnHandler {
    
        private ReactInstanceManager mReactInstanceManager;
        private ReactRootView mReactRootView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mReactRootView = new ReactRootView(this);
            mReactInstanceManager = ReactInstanceManager.builder()
                    .setApplication(getApplication())
                    .setBundleAssetName("index.android.bundle")
                    .setJSMainModuleName("index.android")
                    .addPackage(new MainReactPackage())
                    .addPackage(new AndroidForToastPackage()) // <-- Register package here
                    .setUseDeveloperSupport(BuildConfig.DEBUG)
                    .setInitialLifecycleState(LifecycleState.RESUMED)
                    .build();
            mReactRootView.startReactApplication(mReactInstanceManager, "AwesomeProject", null);
            setContentView(mReactRootView);
        }
    ...
    

    2.如何自定义react-native的android组件(二)
    3.react-native-0.16.1 自定义Android组件部分的源码初探

    相关文章

      网友评论

      • 喵腹蛇掌柜:继承SimpleViewManager的类里面的方法怎么被js调用
      • __Berial___:为什么是RCTToastAndroid.SHORT
        afbe1f5137c4:按照你的index.android.js源码去执行会报错,应该是少了个符号什么的
        __Berial___:@zzyyppqq :cold_sweat: 看漏了导入。。一直想着是上面写的class类里的getName。。
        alexis_zyp:@__Berial___ RCTToastAndroid只是一个变量,可以随意命名的

      本文标题:如何创建一个android的react-native组件(一)

      本文链接:https://www.haomeiwen.com/subject/yxpphttx.html