React Native 学习指南(三) - 把玩更多UI组件

1,803 阅读2分钟

在之前的天气小应用实战中,我们已经基本了解一些基础组件的使用:<View><Text><Image>,接下来我们通过官方示例 UIExplorer 看看触摸手势这样在移动设备上的常用操作将怎样在 React Native 中实现,再尝试 <ListView><TabView><NavigatorView> 这些进阶组件。

官方示例 UIExplorer

触控操作 (TouchableHighlight)

要让组件实现触控操作,使用 <TouchableHighlight> 对组件进行包装即可,并制定 onPress 等操作响应方法。

// 参见 https://github.com/facebook/react-native/blob/master/Examples/UIExplorer/js/TouchableExample.js

<TouchableHighlight
    style={styles.wrapper}
    onPress={() => console.log('stock THW image - highlight')}>
    <Image source={heartImage} style={styles.image}/>
</TouchableHighlight>

手势响应 (GestureResponder)

和 iOS 中手势系统一样,GestureResponder 是一个相对抽象的底层接口,这里我们将通过了解基于此的更高层实现的 PanResponder 来理解手势响应。

不同于 <TouchableHighlight>, PanResponder 并不是组件,而是一个类。

_panResponder: {}, // 声明一个 PanResponder 变量

// 创建 PanRespondre 实例,并实现相关响应操作方法
componentWillMount: function() {
    this._panResponder = PanResponder.create({
      onStartShouldSetPanResponder: this._handleStartShouldSetPanResponder,
      onMoveShouldSetPanResponder: this._handleMoveShouldSetPanResponder,
      onPanResponderGrant: this._handlePanResponderGrant,
      onPanResponderMove: this._handlePanResponderMove,
      onPanResponderRelease: this._handlePanResponderEnd,
      onPanResponderTerminate: this._handlePanResponderEnd,
    });
},

render 函数中给视图组件添加手势

render: function() {
    return (
      <View
        style={styles.container}>
        <View
          style={styles.circle}
          {...this._panResponder.panHandlers}
     />
</View>

以上手势触控操作都只是参照官方示例做简单梳理,更多具体的代码实现可参见 UIExplorer

使用 <ListView> 组件

列表视图,即 iOS 开发中的 TableView。

添加列表视图组件,有两个必要属性: dataSourcerenderRow,也就是数据源以及渲染列表单元组件。


getInitialState: function() {
    var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
    return {
      dataSource: ds.cloneWithRows(this._genRows({})),
    };
},

<ListView
    dataSource={this.state.dataSource}
    renderRow={this._renderRow}
/>

  _renderRow: function(rowData: string, sectionID: number, rowID: number, highlightRow: (sectionID: number, rowID: number) => void) {
    var rowHash = Math.abs(hashCode(rowData));
    var imgSource = THUMB_URLS[rowHash % THUMB_URLS.length];
    return (
      <TouchableHighlight onPress={() => {
          this._pressRow(rowID);
          highlightRow(sectionID, rowID);
        }}>
        <View>
          <View style={styles.row}>
            <Image style={styles.thumb} source={imgSource} />
            <Text style={styles.text}>
              {rowData + ' - ' + LOREM_IPSUM.substr(0, rowHash % 301 + 10)}
            </Text>
          </View>
        </View>
      </TouchableHighlight>
    );
  },

  _genRows: function(pressData: {[key: number]: boolean}): Array<string> {
    var dataBlob = [];
    for (var ii = 0; ii < 100; ii++) {
      var pressedText = pressData[ii] ? ' (pressed)' : '';
      dataBlob.push('Row ' + ii + pressedText);
    }
    return dataBlob;
  },

原理和使用 UITableView 大相径庭,熟悉了之后并不难理解。官方示例参见:ListViewExample.js

使用 Navigator

即类似 iOS 中的 NavigationController。允许应用在不同屏幕之间切换“场景(Scene)”,通过一个“栈”来维护场景的推入(push)和弹出(pop)。参见官方示例 Navigator

平台特定组件

React-Native 的一大特点就是支持跨平台开发,但是由于 iOS 与 Android 交互方式之间存在差异,因此还需要针对不同平台使用特定组件。一般这些平台特定组件都有相应平台的后缀标识,例如 <TabBarIOS><SwitchAndroid>

总结

通过官方示例 UIExplorer ,我们可以了解更多更多组件来支持特定功能的实现。接下来,就要征战最令人头疼的样式布局了。