#はじめに
前回に続きReact Nativeで疲弊してるfkdsです。
現時点では「あれ?React NativeってReactとReact Nativeって言語覚えないといけないから、ネイティブアプリ作れる人が触る必要ないよねこれ?」と思い始めてます。
さて、今回はDrawerNavigationとStackNavigationを共存させる方法と、それを共存させたあとに出てくるDrawerItemsで余計なの出てくるんだけど問題を解消する方法です。
毎度のことですが、もはやかなり俺俺実装になっているので、絶対他に正解あるだろこれって状態で実装しています。
皆様のマサカリお待ちしています。
・・・React Nativeエンジニアさん、いるよね・・・?
#今回やりたかったこと
もうすでに書きましたが
- DrawerNavigationとStackNavigationを共存させる
- を共存させたあとに出てくるDrawerItemsで余計なの出てくるんだけど問題を解消
の2本立てです。
##導入したバージョン
前回と同じく
"react": "16.3.1"
"react-native": "0.55.4"
"react-navigation": "2.6.2"
##実装したコード
import { createStackNavigator, createDrawerNavigator, DrawerItems } from "react-navigation";
import ScreenA from "./ScreenA";
import ScreenB from "./ScreenB";
import style from "./NavigatorStyle";
/**
* メインのStackNavigation部分です
*/
const stackNavigator = createStackNavigator(
{
ScreenA: {
screen: ScreenA,
navigationOptions: ({ navigation }) => ({
title: "画面A",
gesturesEnabled: false
})
},
ScreenB: {
screen: ScreenB,
navigationOptions: ({ navigation }) => ({
title: "画面B",
gesturesEnabled: false
})
}
}
);
/**
* DrawerNavigationの各Cell生成
* @param {*} props
*/
const DrawerCell = props => {
// StackNavigatorをDrawerNavigationを表示させない為の処理
// 絶対別の方法があると思ってる場所
if (props.scene.route.key === "StackNavigator") {
return null;
}
return (
<View style={style.drawerCell>
<Text style={style.drawerCellLabel}>{props.scene.route.key}</Text>
</View>
);
};
export default (mainNavigator = createDrawerNavigator(
{
ScreenA: {
screen: ScreenA
},
ScreenB: {
screen: ScreenB
},
StackNavigator: {
screen: stackNavigator,
navigationOptions: {
drawerLabel: () => null, // 余計なitemを消す方法で探すとこれが出てくるが、正直タップ判定残ったりしてゴミなので残してるけど不要な処理
drawerLockMode: "locked-closed" // これつけておくとthis.props.navigation.toggleDrawer();じゃないとメニュー開かなくさせられる
}
}
},
{
// メニュー部分
contentComponent: props => (
<View style={style.container}>
<View Style={style.profile}>
<View Style={style.profileImg}>
<Image style={style.profileImg} source={require("./../../resource/dummyIcon.png")} />
</View>
</View>
<ScrollView>
<DrawerItems
{...props}
getLabel={scene => <DrawerCell scene={scene} {...props} />}
/>
</ScrollView>
</View>
),
initialRouteName: "StackNavigator",
drawerWidth: 300,
}
));
import Navigator from "./src/component/Navigator";
// ~~import省略~~
type Props = {};
export default class App extends Component<Props> {
render() {
return (
<Provider {...stores}>
<Navigator />
</Provider>
);
}
}
##May be 説明
今回はコメントに書いたから要らないですよね。
DrawerCellを使わないで出すと、StackNavigatorっていうCellがDrawerNavigation上に出ます。
非常に邪魔です。消したいですよね。消しましょう。
ただ今回実装したものは、かなりの力業です。
クラス構造が変わったら速攻で死ぬパターンなので、正しい判別方法を探しましょう。そして教えてください。
なおgithubのissue等によく出てくるdrawerLabel: () => nullはトラップです。
タップ判定残ります。めっちゃ気になります。
#終わりに
iOSで実装するならワンパンレベルの内容でここまで疲弊したのはReact Nativeさん、あなたが初めてですよ。
正直サンプル系のコードを全然見ることが出来ていないので、本日はサンプル系のコードを見て他のアプリだとどうなっているのか見てみたいと思います。
僕の実装は力業すぎるので、絶対他に方法があるはずです。
以上。
#2018/07/20追記
https://github.com/react-navigation/react-navigation/blob/master/examples/NavigationPlayground/js/Drawer.js
これを見た。
この方法は別で見たからわかるけど、こういう画面だから出来ている実装。
[Inbox]-[Email]
[Drafts]-[Email]
でもやりたいのはこれ
[Login]
|
[Home]
├---[ScreenA]
├---[ScreenB]
└---[ScreenC]
で、Drawerに出すのはScreenA〜CでかつHomeでしか使わない。
という状況なので、これのいい解決方法ないかなーといった感じですね。
ネイティブだとこの手のメニューなんかはNavigationと別で考えられるから楽なんだけどねー。
#2018/07/20 15:55追記
https://shift.infinite.red/react-navigation-drawer-tutorial-part-2-9c382217ac6b
ここのStep4を参考に独自でメニュー実装って手もあるねという話だけ追記。
Step2でHeaderにかぶらないように表示する方法を紹介してたりするので、メモ
https://shift.infinite.red/react-navigation-drawer-tutorial-a802fc3ee6dc