zoukankan      html  css  js  c++  java
  • ReactNative入门(安卓)——API(上)

    Alert - 弹窗

    通过 Alert.alert() 方法调用唤起原生弹窗,点击会触发 onPress 回调(参考下方代码)并清除弹窗。

    import React, {
        AppRegistry,
        Component,
        StyleSheet,
        Alert,
        Text,
        View
    } from 'react-native';
    
    class AwesomeProject extends Component {
        componentDidMount(){
            Alert.alert(
                'Alert标题',
                '一些正文内容',
                [
                    //{text: '稍后询问', onPress: () => console.log('Ask me later pressed')},
                    //{text: '取消', onPress: () => console.log('Cancel Pressed')},
                    {text: 'OK', onPress: () => console.log('OK Pressed')}
                ]
            )
        }
        render() {
            return (
                <View style={styles.container}>
                    <Text style={styles.text}>
                        DEMO
                    </Text>
                </View>
            );
        }
    }
    View Code

    按钮数量将决定其排版(下图),不同于ios,安卓无法定义按钮样式:

    (单个按钮情况)

    (两个按钮情况)

    (三个按钮情况)

    Animated - 动画接口

    篇幅较大,故独立写了两篇文章:

    ReactNative入门 —— 动画篇(上)

    ReactNative入门 —— 动画篇(下)

    AppRegistry - APP注册接口

    最常用的接口,特别是 AppRegistry.registerComponent 方法,用于注册根组件到当前APP,进而让原生系统加载时可以执行对应的bundle文件:

    AppRegistry.registerComponent('AppName', () => RootComponent);

    除了 registerComponent 之外,还提供了其它一些比较少用的接口:

    registerConfig(config<Array>)  //注册配置
    registerRunnable(appKey<String>, func<Function>)  //注册函数监听
    getAppKeys()  //获取registerRunnable注册的监听键
    runApplication(appKey<String>, appParams<any>)  //运行App

    AppState - 应用状态

    通过此接口可以获悉应用在当前处于后台还是前台激活的状态,常用方法和应用场景类似于h5的visibilitychange。

    注意该接口要最新版本(2.0+)的 react-native 才能调用。

    获取到的应用状态常规有:

    active:表示应用处于前台运行状态;
    background:表示应用处于后台挂起状态;
    inactive:过渡状态,常规不会发生,可以先忽略该状态。

    我们可以使用 AppState.addEventListenerAppState.removeEventListener 方法来监听、移除应用状态的 change 事件。

    另外也可以直接使用 AppState.currentState 来获得应用当前的状态:

    import React, {
        AppRegistry,
        Component,
        StyleSheet,
        Alert,
        AppState,
        Text,
        View
    } from 'react-native';
    
    class AwesomeProject extends Component {
        componentDidMount() {
            AppState.addEventListener('change', this._handleAppStateChange);
            //组件挂载时获取当前状态
            Alert.alert('当前状态', AppState.currentState, [{text: 'OK'}]);
        }
    
        componentWillUnmount() {
            AppState.removeEventListener('change', this._handleAppStateChange);
        }
    
        _handleAppStateChange(currentAppState) {
            currentAppState==='active' && Alert.alert('状态转变', currentAppState, [{text: 'OK'}])
        }
    
        render() {
            return (
                <View style={styles.container}>
                    <Text style={styles.text}>
                        DEMO
                    </Text>
                </View>
            );
        }
    }
    View Code

    注:如果在模拟器中出现“screenPhysicalPixels undefined”的问题,试着执行 react-native upgrade 来更新gradle(见此issue

    AsyncStorage - 异步存储

    类似于 localStorage,常用于本地存储一些键值对类型的数据,这些存储的数据对应整个应用本身而已是全局性质的(类似 localStorage 在同个域下共享)

    其对外方法主要有:

    getItem(key<String>, [callback<Function(error, result)>])
    获取单个数据,返回一个 Promise 对象
    
    setItem(key<String>, [callback<Function(error)>])
    设置单个数据,返回一个 Promise 对象
    
    removeItem(key<String>, [callback<Function(error)>])
    移除单个数据,返回一个 Promise 对象
    
    mergeItem(key<String>, value<String>, [callback<Function(error)>])
    合并某个已存在的数据项,通常该项为stringified json格式。该接口返回一个 Promise 对象
    
    clear([callback<Function(error)>])
    清除全部 AsyncStorage 数据,返回一个 Promise 对象
    
    getAllKeys(callback<Function(error, keys)>)
    获取所有键,返回一个 Promise 对象
    flushGetRequests() 清空所有进行中的查询 multiGet(keys<Array>, [callback<Function(error, keys)>]) 
    获取多项,查询 keys(字符串数组)指定的多个键来查询对应的值。该接口返回一个 Promise 对象
    
    multiGet(keys<Array>, [callback<Function(error, keyValuePairs)>]) 
    获取多项,参数 keys 是一个字符串数组,回调里的形参 keyValuePairs 是字符串的二维数组,表示最终获得的键值对组。该接口返回一个 Promise 对象
    
    multiSet(keyValuePairs<Array>, [callback<Function(error, keys)>]) 
    设置多项,参数 keyValuePairs 是字符串的二维数组。该接口返回一个 Promise 对象
    
    multiRemove(keys<Array>, [callback<Function(error)>]) 
    移除 keys(字符串数组)指定的多项。返回一个 Promise 对象
    
    multiMerge(keyValuePairs<Array>, [callback<Function(error)>]) 
    合并多项已有的键值对,参数 keyValuePairs 是字符串的二维数组。该接口返回一个 Promise 对象。注意该接口还不完善,未能被所有原生支持。

    先来看一个简单的 AsyncStorage 数据设置与获取:

    import React, {
        AppRegistry,
        Component,
        StyleSheet,
        Alert,
        AsyncStorage,
        Text,
        View
    } from 'react-native';
    
    class AwesomeProject extends Component {
        constructor(props) {
            super(props);
            this.state = {
                time : '123'
            };
        }
        componentDidMount() {
            AsyncStorage.setItem('timeStamp', Date.now() + '', function(err){
                //错误处理
                err && console.log(err)
            }).done(function(){
                Alert.alert(
                    '恭喜',
                    '数据设置成功',
                    [
                        {text: 'OK', onPress: () => {}}
                    ]
                )
            })
        }
        _getData() {
            AsyncStorage.getItem('timeStamp', function(err, data){
                if(err) return console.log(err);
                this.setState({
                    time : data
                })
            }.bind(this));
        }
    
        render() {
            return (
                <View style={styles.container}>
                    <Text style={styles.text}>
                        {this.state.time || '暂无数据'}
                    </Text>
    
                    <View style={styles.btnWrap}>
                        <Text style={styles.btn} onPress={this._getData.bind(this)}>点我获取</Text>
                    </View>
                </View>
            );
        }
    }
    View Code

    再来一个 multiSet 和 multiGet 的示例:

    class AwesomeProject extends Component {
        constructor(props) {
            super(props);
            this.state = {
                a : ''
            };
        }
        componentDidMount() {
            var me = this;
            AsyncStorage.multiSet([['a','1'], ['b','2']], function(err){
                if(err) return console.log(err);
                AsyncStorage.multiGet(['a', 'b'], function(err, keyValuePairs) {
                    keyValuePairs.forEach(function (keyValuePair) {
                        if (keyValuePair[0] === 'a') {
                            me.setState({
                                a: keyValuePair[1]
                            })
                        }
                    });
                })
            })
        }
        _mergeData() {
            var me = this;
            AsyncStorage.multiSet([['a','5'], ['c','2']], function(err){
                if(err) return console.log(err);
                AsyncStorage.getItem('a', function(err, value) {
                    me.setState({
                        a: value
                    })
                })
            })
        }
    
        render() {
            return (
                <View style={styles.container}>
                    <Text style={styles.text}>
                        {this.state.a || '加载中'}
                    </Text>
    
                    <View style={styles.btnWrap}>
                        <Text style={styles.btn} onPress={this._mergeData.bind(this)}>点我合并</Text>
                    </View>
    
                    <View style={styles.btnWrap}>
                        <Text style={styles.btn} onPress={AsyncStorage.getItem.bind(this, ['0',{}])}>点我reload</Text>
                    </View>
                </View>
            );
        }
    }
    View Code

    注意 multiMerge 接口还不能被所有原生环境支持,调用的时候很可能会直接报错。事实上可以直接用 multiSet 替代。

    BackAndroid - 返回处理

    可以通过该接口来处理应用返回事件。

    通过 BackAndroid.addEventListener 和 BackAndroid.removeEventListener 事件,可以监听/移除用户点击安卓设备系统返回键的事件。

    通过 BackAndroid.exitApp() 方法可以直接退出当前应用:

    class AwesomeProject extends Component {
        constructor(props) {
            super(props);
            this.state = {
                a : ''
            };
        }
        componentDidMount() {
            BackAndroid.addEventListener('hardwareBackPress', this._handleBackPressed.bind(this));
        }
        componentWillUnmount() {
            BackAndroid.removeEventListener('change', this._handleBackPressed.bind(this));
        }
        _handleBackPressed() {
            this.setState({
                a : 'backPressed'
            })
        }
        _exitApp() {
            BackAndroid.exitApp()
        }
    
        render() {
            return (
                <View style={styles.container}>
                    <Text style={styles.text}>
                        {this.state.a || '加载中'}
                    </Text>
    
                    <View style={styles.btnWrap}>
                        <Text style={styles.btn} onPress={this._exitApp.bind(this)}>退出应用</Text>
                    </View>
                </View>
            );
        }
    }

    效果1——点击系统返回键:

    效果2——调用 exitApp 方法:

    CameraRoll - 相册接口

    与相册交互的接口,然而安卓这块没IOS的支持好用(无法保存非本地图片)。

    1. 通过 CameraRoll.saveImageWithTag(uri) 可以保存某张本地图片到相册,其中 uri 必须为本地地址(例如 'file:///sdcard/img.png')

    该接口返回一个 Promise 对象(成功时的回调参数为图片存储后的图片ID):

        _handleSavePic() {
            var me = this;
            CameraRoll.saveImageWithTag('file:///sdcard/img.png').done(function(uri){
                me.setState({
                    a : uri
                })
            }, function(err){
                Alert.alert(
                    '保存失败',
                    JSON.stringify(err),
                    [
                        {text: 'OK'}
                    ]
                )
            })
        }

    2. 通过 CameraRoll.getPhotos(params<Object>) 可以从相册里去获取图片,其中 params 参数格式为:

    {
      first : 3,  //获取图片的个数
      groupTypes : React.propTypes.oneOf([  //分组类型
          'Album',
          'All',
          'Event',
          'Faces',
          'Library',
          'PhotoStream',
          'savePhotos'
      ]),
      assetType : React.propTypes.oneOf([  //资源类型
          'Photos',
          'All',
          'Videos'
      ])
    }

    该接口返回一个 Promise 对象,成功的回调参数数据格式为:

    {
      edges: [{
          node: {
              timestamp: 1405312098,
              group_name: 'CameraRoll',
              type: 'ALAssetTypePhoto',
              image: {
                  isStored: true,
                  height: 669,
                  uri: 'asset-library: //asset/assert.JPG?id=C9DB366F-350876C78006&ext=JPG',
                   1008
              }
        },
        {node: ....}
      }],
      page_info: {
          has_next_page: true,
          start_cursor: 'asset-library: //asset/assert.JPG?id=C9DB366F-350876C78006&ext=JPG',
          end_cursor: 'asset-library...'
      }
    }
    //参考至“ReactNative入门与实战”一书162页

    来个简单示例:

        _handleGetImages() {
            var me = this;
            var params = {
                first : 3,
                groupTypes : 'Album',
                assetType : 'Photos'
            };
            CameraRoll.getPhotos(params).done(function(data){
                var edges = data.edges,
                    photos = [];
                edges.forEach(function(edge){
                    photos.push(edge.node.image.uri)
                });
                me.setState({
                    photos: photos
                })
            }, function(err){
                Alert.alert(
                    '打开相册失败',
                    JSON.stringify(err),
                    [
                        {text: 'OK'}
                    ]
                )
            })
        }

    Clipboard - 剪切板

    该模块接口具有获取/设置剪切板内容的能力。

    通过 Clipboard.getString() 可以获得设备剪切板内容,通过 Clipboard.setString(content<String>) 可以设置剪切板内容:

    class AwesomeProject extends Component {
        constructor(props) {
            super(props);
        }
        _onPress(){
            Clipboard.setString('你好啊')
        }
    
        render() {
            return (
                <View style={styles.container}>
                    <TouchableOpacity>
                        <View style={[styles.button,{backgroundColor:'#CCC'}]}>
                            <TextInput />
                        </View>
                    </TouchableOpacity>
    
                    <TouchableOpacity onPress={this._onPress}>
                        <View style={styles.button}>
                            <Text style={styles.buttonText}>修改剪切板内容为“你好啊”</Text>
                        </View>
                    </TouchableOpacity>
                </View>
            );
        }
    }

    DatePickerAndroid - 日期选择器

    通过 DatePickerAndroid.open(options<Object>) 方法可以打开一个标准的Android时间选择器的对话框,并返回一个Promise对象。

    其中 options 参数参考如下:

    date (Date对象或毫秒时间戳) - 默认显示的日期
    minDate (Date对象或毫秒时间戳) - 可选的最小日期
    maxDate (Date对象或毫秒时间戳) - 可选的最大日期

    Promise的回调参数为: 

    action - 对应动作,若为取消对话框,该值为 DatePickerAndroid.dismissedAction
    year - 选中的年份,若为取消对话框,该值为undefined
    month (0-11) - 选中的月份,若为取消对话框,该值为undefined
    day - 选中的天值,若为取消对话框,该值为undefined

    因此我们可以通过判断 Promise 回调中的 action 是否等价于 DatePickerAndroid.dismissedAction,来得知用户是否做了取消对话框的行为:

    class AwesomeProject extends Component {
        constructor(props) {
            super(props);
        }
        _onPress(){
            DatePickerAndroid.open({
                date: new Date(),
                minDate: new Date('1900/01/01'),
                maxDate: new Date('2100/12/12')
            }).done(function(params){
                var content = '';
                if(params.action !== DatePickerAndroid.dismissedAction){
                    content = '你选中了' + params.year + '年' + (params.month+1) + '月' + params.day + '日'
                } else {
                    content = '你退出了时间选择对话框'
                }
    
                Alert.alert(
                    '时间选择结果',
                    content,
                    [
                        {text: 'OK', onPress: () => console.log('OK Pressed')}
                    ]
                )
            })
        }
    
        render() {
            return (
                <View style={styles.container}>
                    <TouchableOpacity onPress={this._onPress}>
                        <View style={styles.button}>
                            <Text style={styles.buttonText}>打开日期选择器</Text>
                        </View>
                    </TouchableOpacity>
    
                    <TouchableOpacity>
                        <View style={styles.button}>
                            <Text style={styles.buttonText}>somebtn</Text>
                        </View>
                    </TouchableOpacity>
                </View>
            );
        }
    }
    View Code

    Dimensions - 获取应用窗口尺寸

    可通过 Dimensions.get('window') 来获取当前窗口尺寸,得到一个含有 width 和 height 属性的对象。

    常用于设置图片宽高(例如设置图片宽度为屏幕宽度):

    import React, {
        AppRegistry,
        Component,
        StyleSheet,
        Dimensions,
        Text,
        View
    } from 'react-native';
    
    class AwesomeProject extends Component {
        constructor(props) {
            super(props);
            this.state = {
                width : '',
                height : ''
            };
        }
        componentDidMount() {
            var win_info = Dimensions.get('window');
            this.setState({
                 win_info.width,
                height: win_info.height
            })
        }
        render() {
            return (
                <View style={styles.container}>
                    <Text style={styles.text}>
                        屏幕宽度:{this.state.width || '加载中'}
                    </Text>
                    <Text style={styles.text}>
                        屏幕高度:{this.state.height || '加载中'}
                    </Text>
                </View>
            );
        }
    }

    启动后显示效果如下:

    InteractionManager - 交互管理器

    在web页面,我们常规会使用 setImmediate/setTimeout/requestAnimationFrame 来定义动画下一帧的执行时间点,在 RN 的动画交互中,我们通过使用 InteractionManager.runAfterInteractions() 来做对应处理是最佳的选择。

    例如我们希望安卓切换场景的时候,能在场景切换动画结束了才开始执行某些操作,可以这么写:

    componentDidMount: function(){
        InteractionManager.runAfterInteractions(() => {
            //TODO: some events
        });
    }

    另外我们可以通过 createInteractionHandle() 接口创建一个交互句柄,通知系统当前有个动画交互开始了。

    动画结束时再通过 clearInteractionHandle(handle) 来通知系统该动画交互已结束。

    示例:

    var handle = InteractionManager.createInteractionHandle();
    // 开始执行某些动画交互... (`runAfterInteractions` 任务会被压入队列中等候动画结束)
    // 动画交互执行完毕的时候执行clearInteractionHandle通知系统交互结束:
    InteractionManager.clearInteractionHandle(handle);
    // 触发runAfterInteractions

    另外 InteractionManager 还有一个静态方法 setDeadline(deadline<Number>),用于(使用setTimeout来)挂起所有尚未执行的任务。

    donate

  • 相关阅读:
    禁止页面缓存 移动端
    常见的请求头与响应头介绍
    阮一峰 ES6学习
    禁止页面缩放 移动端
    10月30日学习日志
    11月7日学习日志
    11月6日学习日志
    10月31日学习日志
    11月1日学习日志
    11月9日学习日志
  • 原文地址:https://www.cnblogs.com/vajoy/p/5204151.html
Copyright © 2011-2022 走看看