DrawerLayoutAndroidとNavigatorを組み合わせて使いたい
DrawerLayoutAndroidは『画面端をスワイプするとニュッと画面が出てくるアレ』を実現するコンポーネント。
DrawerLayoutAndroid単独の解説してる記事はちょくちょく見たけど、Navigatorと組み合わせてる例はgithub上にあげられたサンプルのリポジトリくらいしかなくてアレだったので整理がてらメモ。
組み合わせってのは、ドロワー内のViewをタップするとそれに対応したコンポーネントに切り替わるヤツね。
↓みたいな動き。
DrawerLayoutAndroidとNavigatorの連携
基本的には下記のコードを見れば終わり。
react-native-material-design/demo-app
ここからメモ。
登場人物は3つのコンポーネント。
- DrawerAndroid
- NavigationView
- Navigator
これらを次のように配置する。
1 2 3 |
<DrawerLayoutAndroid renderNavigationView={() => navigationView}> <Navigator /> </DrawlerLayoutAndroid> |
DrawerLayoutAndroid
にはNavigationView
を描画するためのメソッドrenderNavigationView
がある。
それからDrawerLayoutAndroid
はNavigator
を子として抱えてる。
これをもうちょっと具象化するとこんな感じ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
render() { var navigationView = ( <View style={{flex: 1, backgroundColor: '#fff'}}> <MenuPane navigator={this.refs.navigator} onTapMenu={this._onTapMenuItem.bind(this)}/> </View> ); return ( <DrawerLayoutAndroid ref="drawer" drawerWidth={300} drawerPosition={DrawerLayoutAndroid.positions.Left} renderNavigationView={() => navigationView}> <Navigator ref="navigator" initialRoute={{ component: ClipsList, passProps: {} }} renderScene={this.renderScene.bind(this)} /> </DrawerLayoutAndroid> ); } renderScene(route, navigator) { let RouteComponent = route.component return ( <View style={styles.root} showsVerticalScrollIndicator={false}> <RouteComponent navigator={navigator} {...route.passProps} /> </View> ) } _onTapMenuItem(menuItem) { var drawer = this.refs.drawer; drawer.closeDrawer(); this.refs.navigator.resetTo({ component: menuItem.component, passProps: menuItem.payload, }); } |
『NavigationViewで選択されたアイテム毎に指定されたコンポーネントを表示する』ための流れを整理したい。
こんな感じだろうか。
- NavigationViewに『アイテムが選択されたことを通知するコールバック』をpropsとして与える
- NavigationView内でアイテムが選択されたら親コンポーネントから受け取ったコールバックを発動
- このとき、コールバックの引数としてrouteオブジェクトを与える
- 受け取ったrouteオブジェクトをNavigatorに渡してコンポーネントを切り替える
NavigationViewという特別なコンポーネントがあるわけではないので、任意のコンポーネントを作る必要がある。
ここでは、MenuPaneというコンポーネントを作ってみる。
作りは質素で基本的にはTextを表示するだけのListView。
ちょっと変わってる点はNavigatorと連携するための細工が仕込まれてるくらい。
タップするとコールバックが呼び出されるようになってる。
で、親コンポーネント側では開いてるNavigationView(ドロワー)を閉じつつ、受け取ったrouteオブジェクトをNavigator
に渡してる。
あとはNavigatorのrenderSceneがよしなにやってくれるって感じっすね。。