React Native 學習筆記十三(原生模組之Toast)
阿新 • • 發佈:2018-12-31
在學習官網上的Toast 的過程中 出現很多的坑
廢話就不說了 官網上都有 官網講解
實現思路 :
我們之前已經將react-native 嵌入原生了 那麼 我們就在之前的基礎上進行修改就好了
建立ToastUtils.java 繼承ReactContextBaseJavaModule 我們要明確自己的目的 就是使用js呼叫 Toast 就像android 原生一樣 能夠在螢幕底端進行輸出 那麼我們需要自己封裝方法 供js呼叫 我們希望呼叫的形式為ToastShow.show('des',ToastShow.LONG) 那麼我們就要自定義 show方法 以及常量 來提供給js
所以具體程式碼的實現如下:
importandroid.widget.Toast; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import java.util.HashMap; import java.util.Map; import javax.annotation.Nullable; /** * Created by zhangyanjiao on 17/9/19.* * 功能:在js中寫Toast.show('toast text',Toast.SHORT) 可以像原生的toast一樣輸出東西 * 注:RN已經內建了一個名為ToastAndroid的模組 */ public class ToastUtils extends ReactContextBaseJavaModule{ private static final String DURATION_SHORT_KEY="SHORT"; private static final String DURATION_LONG_KEY="LONG"; public ToastUtils(ReactApplicationContext reactContext) { super(reactContext); } /** *該方法的返回值 的RCT字首可以自動被移除 所以 即使返回值是RCTToast 在js中也會編譯通過 * 在js中會根據這個方法返回的字串來查詢對應的類 * @return */ @Override public String getName() { return "ToastShow"; } /** * 該方法 不一定需要實現 所以可能返回值為空 一般用來返回一些可以被js同步訪問的常量 或者是預定義的值 * 在本類中 我們需要給js兩個常量 * @return */ @Nullable @Override public Map<String, Object> getConstants() { final HashMap<String, Object> constants = new HashMap<>(); constants.put(DURATION_LONG_KEY, Toast.LENGTH_LONG); constants.put(DURATION_SHORT_KEY, Toast.LENGTH_SHORT); return constants; } /** * 要匯出一個方法給JavaScript使用,Java方法需要使用註解@ReactMethod。方法的返回型別必須為void。 * React Native的跨語言訪問是非同步進行的,所以想要給JavaScript返回一個值的唯一辦法是使用回撥函式或者傳送事件 * 下面的引數型別在@ReactMethod註明的方法中,會被直接對映到它們對應的JavaScript型別。 Boolean -> Bool Integer -> Number Double -> Number Float -> Number String -> String Callback -> function ReadableMap -> Object ReadableArray -> Array * @param msg 彈出的提示資訊 * @param duration 顯示事件長短 */ @ReactMethod public void show(String msg,int duration){ Toast.makeText(getReactApplicationContext(),msg,duration).show(); } }
然後要進行註冊 否則的話 js將無法找到該類
建立 RegistPackage.java 實現ReactPackage介面
import com.facebook.react.ReactPackage; import com.facebook.react.bridge.JavaScriptModule; 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; /** * Created by zhangyanjiao on 16/9/20. */ public class RegistPackage implements ReactPackage { @Override public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { List<NativeModule> modules = new ArrayList<>(); modules.add(new ToastUtils(reactContext)); return modules; } @Override public List<Class<? extends JavaScriptModule>> createJSModules() { return Collections.emptyList(); } @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { return Collections.emptyList(); } }
別忘了在mainActivity中新增 addPackage
.addPackage(new RegistPackage())
最後為了在js檔案中更方便的使用 我們對呼叫進行封裝
建立ToastShow.js檔案 具體實現如下
'use strict' /** * This exposes the native ToastAndroid module as a JS module. This has a function 'show' * which takes the following parameters: * * 1. String message: A string with the text to toast * 2. int duration: The duration of the toast. May be ToastAndroid.SHORT or ToastAndroid.LONG */ import { NativeModules } from 'react-native'; // 下一句中的ToastAndroid即對應上文 // public String getName()中返回的字串 // 練習時請務必選擇另外的名字! export default NativeModules.ToastShow;
此時我們就可以安心引用了
在index.android.js檔案中
import React, { Component } from 'react'; import { AppRegistry, StyleSheet, Text, View, } from 'react-native'; import ToastShow from './ToastShow' var { NativeModules } = require('react-native'); class MyApp extends Component { constructor(props) { super(props); } render() { ToastShow.show('我是彈窗',ToastShow.LONG); return( <View > <Text>{'hahahhahhahah'}</Text> </View> ) } } AppRegistry.registerComponent('MyApp', () => MyApp);
記住修改完 要進行重新的編譯 執行 直接使用熱更新的話 會報錯