React Native - Navigator 導覽換頁

react native navigator 快速建立換頁功能。

 

 

在 react native 中,換頁是不可或缺的功能,

Navigator 即為我們主要使用的原件,

以下步驟將實作出簡單的換頁功能,並且於 app 頂端有導覽列。

 

引用元件

import {
  AppRegistry,
  Platform,
  TouchableOpacity,
  StyleSheet,
  Navigator,
  View,
  Text,
} from 'react-native';
  • Platform:可辨別裝置為 ios 或 android
  • TouchableOpacity:提供點擊事件 onPress()
  • StyleSheet:樣式表
  • Navigator:導覽列(本文主要元件)

 

建立導覽框架

Component:appdemo
class appdemo extends Component {

  _renderScene(route, navigator) {
     // page router
     if (route.component == Main) {
       return <Main navigator={navigator} />
     }
     if (route.component == Home) {
       return <Home navigator={navigator} />
     }
  }

  render() {
    return (
      <Navigator
        initialRoute={{ component: Main }}
        renderScene={ this._renderScene } />
    );
  }

}
  • initialRoute:設定預設的 component
  • renderScene:於換頁時 push component,並依據指定的 component,來載入

 

 Component:Main
class Main extends Component {
  _navigate() {
    this.props.navigator.push({
      component: Home,
    })
  }
  render() {
    return (
      <View>
        <Text>this is Main Page</Text>
        <TouchableOpacity onPress= { () => this._navigate() } >
          <Text>GO To Home</Text>
        </TouchableOpacity>
      </View>
    );
  }
}
  • _navigate():透過 onPress 事件,將 navigator push;換到哪一頁,則用 component 來指定欲載入之元件

 

Component:Home
class Home extends Component {
  _back() {
    this.props.navigator.pop();
  }
  render() {
    return (
      <View style={styles.content}>
        <Text>this is Home Page</Text>
        <TouchableOpacity onPress= { () => this._back() } >
          <Text>GO Back</Text>
        </TouchableOpacity>
      </View>
    );
  }
}
  •  _back:若要返回上一頁,則用 navigator.pop() 

 

 StyleSheet:styles
const styles = StyleSheet.create({
  content: {
    flex: 1,
  },
});

 

AppRegistry:appdemo
AppRegistry.registerComponent('appdemo', () => appdemo);

 

修改 _renderScene()

在辨別 route 時候,我們用 if 來決定要載入的 component,

但如果今天頁數眾多,將會出現疊羅漢般的 if,

因此我們將原本寫法變更,將取得之元件,以變數形式載入。

_renderScene(route, navigator) {

    // 方法一: 用 if 方式選擇 route
    // if (route.component == Main) {
    //   return <Main navigator={navigator} />
    // }
    // if (route.component == Home) {
    //   return <Home navigator={navigator} />
    // }

    // 方法二: 直接把傳來的 component 用變數表示
    let Component = route.component;
    return (
      <Component navigator={navigator}  />
    );

}

 

修改換頁動畫 Navigator

在 render Navigator 中我們增加 configureScene ,此可設定頁面滑動的方式(上下、左右)。

render() {
    return (
      <Navigator
        initialRoute={{ component: Main }}
        renderScene={ this._renderScene }
        configureScene={ this._configureScene } />
    );

相對的也建立 _configureScene。

  _configureScene(route, routeStack) {
    // 頁面滑動方式
    return Navigator.SceneConfigs.FloatFromBottom
    //return Navigator.SceneConfigs.PushFromRight
  }
  • FloatFromBottom:由下至上滑入
  • PushFromRight:由右往左滑入

 

增加上方導覽列

在上步驟同樣位置,我們增加 navigationBar,為了調整間距,也增加 sceneStyle。

render() {
    return (
      <Navigator
        initialRoute={{ component: Main }}
        renderScene={ this._renderScene }
        configureScene={ this._configureScene }
        sceneStyle={{ paddingTop: (Platform.OS === 'android' ? 66 : 74) }}
        navigationBar={this._renderNavBar() } />
    );

建立 _renderNavBar()。

_renderNavBar() {
    const styles = {
      title: {
        flex: 1, alignItems: 'center', justifyContent: 'center'
      },
      button: {
        flex: 1, width: 80, alignItems: 'center', justifyContent: 'center'
      },
      buttonText: {
        fontSize: 18, color: '#FFFFFF', fontWeight: '400'
      }
    }

    var routeMapper = {
      LeftButton(route, navigator, index, navState) {
        if (index > 0) {
          return (
            <TouchableOpacity
              onPress={() => navigator.pop() }
              style={styles.button}>
              <Text style={styles.buttonText}>Back</Text>
            </TouchableOpacity>
          );
        } else {
          return (
            <TouchableOpacity
              onPress={() => navigator.pop() }
              style={styles.button}>
              <Text style={styles.buttonText}>Logo</Text>
            </TouchableOpacity>
          );
        }
      },
      RightButton(route, navigator, index, navState) {
        if (index > 0 && route.rightButton) {
          return (
            <TouchableOpacity
              style={styles.button}>
              <Text style={styles.buttonText}>Set</Text>
            </TouchableOpacity>
          );
        } else {
          return null
        }

      },
      Title(route, navigator, index, navState) {
        return (
          <View style={styles.title}>
            <Text style={styles.buttonText}>{route.title ? route.title : 'Home'}</Text>
          </View>
        );
      }
    };

    return (
      <Navigator.NavigationBar
        style={{
          alignItems: 'center',
          backgroundColor: '#55ACEE',
        }}
        routeMapper={routeMapper}
        />
    );
  }
  • 在 routerMapper 中,將設定三種 button 事件以及樣式
  • LeftButton:左側按鈕,通常表示 logo 或是 back(返回)
  • RightButton:右側按鈕,通常表示 setting 設定
  • Title:位於 LeftButton 右側,通常表示當前畫面標題

 

在頁面中傳入參數 Props

若要在 Main 頁面傳入參數至 Home 頁面參數,必須先修改 _renderScene()。

Component:appdemo
_renderScene(route, navigator) {

    let Component = route.component;
    return (
      <Component navigator={navigator} {...route.passProps}  />
    );

  }
  • 在這邊我們追加 { ...route.passProps },於每個 component 進行 props

 

Component:Main
class Main extends Component {
  _navigate(property) {
    this.props.navigator.push({
      component: Home,
      passProps: {
        name: property
      }
    })
  }
  render() {
    return (
      <View>
        <TouchableOpacity onPress= { () => this._navigate('Hello World') } >
          <Text>GO To View</Text>
        </TouchableOpacity>
      </View>
    );
  }
}
  • _navigate():在裡面加入參數文字 Hello World
  • navigator.push:在換頁的時候,將我們剛剛新增的 passProps,新增參數名稱 name(自訂),並傳入 property

 

在頁面中接收參數 Props

上步驟我們完成了參數之傳遞,接下來要在 Home 這一頁進行接收並顯示。

Component:Home
class Home extends Component {
  _back(property) {
    this.props.navigator.pop();
  }
  render() {

    const { name } = this.props;

    return (
      <View style={styles.content}>
        <Text>{name}</Text>
        <TouchableOpacity onPress= { () => this._back() } >
          <Text>GO To View</Text>
        </TouchableOpacity>
      </View>
    );
  }
}
  • name:由 this.props 可接收 passProps 所有參數,在剛剛我們於 passProps 加入 name,故直接 const { name } 取之。
  • 完成後即可看到 Hello World 

 

以上為參考來源之簡易介紹!

參考資料:React Native Navigator — Navigating Like A Pro in React Native 

有勘誤之處,不吝指教。ob'_'ov