複数のドロワー
同じ画面上に複数のドロワー(左に1つ、右に1つなど)を配置したい場合があります。これは2つの方法で実現できます。
react-native-drawer-layout
を直接使用する(推奨)。- 2つのドロワーナビゲーターをネストする。
react-native-drawer-layout
を使用する
複数のドロワーがある場合、そのうちの1つだけが画面のリストを表示します。2番目のドロワーは、ユーザーのリストなどの追加情報を表示するために使用されることがよくあります。
このような場合、react-native-drawer-layout
を直接使用して2番目のドロワーをレンダリングできます。ドロワーナビゲーターは、最初のドロワーをレンダリングするために使用され、2番目のドロワー内にネストできます。
import * as React from 'react';
import { Button, View } from 'react-native';
import { Drawer } from 'react-native-drawer-layout';
import { createDrawerNavigator } from '@react-navigation/drawer';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button onPress={() => navigation.openDrawer()} title="Open drawer" />
</View>
);
}
const LeftDrawer = createDrawerNavigator();
const LeftDrawerScreen = () => {
return (
<LeftDrawer.Navigator screenOptions={{ drawerPosition: 'left' }}>
<LeftDrawer.Screen name="Home" component={HomeScreen} />
</LeftDrawer.Navigator>
);
};
function RightDrawerScreen() {
const [rightDrawerOpen, setRightDrawerOpen] = React.useState(false);
return (
<Drawer
open={rightDrawerOpen}
onOpen={() => setRightDrawerOpen(true)}
onClose={() => setRightDrawerOpen(false)}
drawerPosition="right"
renderDrawerContent={() => <>{/* Right drawer content */}</>}
>
<LeftDrawerScreen />
</Drawer>
);
}
export default function App() {
return (
<NavigationContainer>
<RightDrawerScreen />
</NavigationContainer>
);
}
ただし、1つの問題があります。HomeScreen
でnavigation.openDrawer()
を呼び出すと、常に左側のドロワーが開きます。右側のドロワーはナビゲーターではないため、navigation
プロパティを介してアクセスすることはできません。
これを解決するには、右側のドロワーを制御する関数を渡すためにコンテキストAPIを使用する必要があります。
import * as React from 'react';
import { Button, View } from 'react-native';
import { Drawer } from 'react-native-drawer-layout';
import { createDrawerNavigator } from '@react-navigation/drawer';
const RightDrawerContext = React.createContext();
function HomeScreen({ navigation }) {
const { openRightDrawer } = React.useContext(RightDrawerContext);
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
onPress={() => navigation.openDrawer()}
title="Open left drawer"
/>
<Button onPress={() => openRightDrawer()} title="Open right drawer" />
</View>
);
}
const LeftDrawer = createDrawerNavigator();
const LeftDrawerScreen = () => {
return (
<LeftDrawer.Navigator screenOptions={{ drawerPosition: 'left' }}>
<LeftDrawer.Screen name="Home" component={HomeScreen} />
</LeftDrawer.Navigator>
);
};
function RightDrawerScreen() {
const [rightDrawerOpen, setRightDrawerOpen] = React.useState(false);
const value = React.useMemo(
() => ({
openRightDrawer: () => setRightDrawerOpen(true),
closeRightDrawer: () => setRightDrawerOpen(false),
}),
[]
);
return (
<Drawer
open={rightDrawerOpen}
onOpen={() => setRightDrawerOpen(true)}
onClose={() => setRightDrawerOpen(false)}
drawerPosition="right"
renderDrawerContent={() => <>{/* Right drawer content */}</>}
>
<RightDrawerContext.Provider value={value}>
<LeftDrawerScreen />
</RightDrawerContext.Provider>
</Drawer>
);
}
export default function App() {
return (
<NavigationContainer>
<RightDrawerScreen />
</NavigationContainer>
);
}
ここでは、RightDrawerContext
を使用して、openRightDrawer
関数をHomeScreen
に渡しています。次に、openRightDrawer
を使用して右側のドロワーを開きます。
2つのドロワーナビゲーターをネストする
別の方法として、2つのドロワーナビゲーターを互いにネストする方法があります。これは、追加の画面を作成し、より多くのネストが必要となるため、推奨されません。これにより、ナビゲーションと型チェックがより冗長になる可能性があります。ただし、両方のナビゲーターに複数の画面が含まれている場合は役立つ場合があります。
ここでは、2つのドロワーナビゲーターが互いにネストされており、1つは左側に、もう1つは右側に配置されています。
import * as React from 'react';
import { Button, View } from 'react-native';
import { createDrawerNavigator } from '@react-navigation/drawer';
import { NavigationContainer } from '@react-navigation/native';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button onPress={() => navigation.openDrawer()} title="Open drawer" />
</View>
);
}
const LeftDrawer = createDrawerNavigator();
const LeftDrawerScreen = () => {
return (
<LeftDrawer.Navigator screenOptions={{ drawerPosition: 'left' }}>
<LeftDrawer.Screen name="Home" component={HomeScreen} />
</LeftDrawer.Navigator>
);
};
const RightDrawer = createDrawerNavigator();
const RightDrawerScreen = () => {
return (
<RightDrawer.Navigator
screenOptions={{ drawerPosition: 'right', headerShown: false }}
>
<RightDrawer.Screen name="HomeDrawer" component={LeftDrawerScreen} />
</RightDrawer.Navigator>
);
};
export default function App() {
return (
<NavigationContainer>
<RightDrawerScreen />
</NavigationContainer>
);
}
ただし、1つの問題があります。HomeScreen
でnavigation.openDrawer()
を呼び出すと、画面の直近の親であるため、常に左側のドロワーが開きます。
これを解決するには、左側のドロワーの親である右側のドロワーを参照するために、navigation.getParent
を使用する必要があります。したがって、コードは次のようになります。
<Button onPress={() => navigation.openDrawer()} title="Open left drawer" />
<Button onPress={() => navigation.getParent().openDrawer()} title="Open right drawer" />
ただし、これは、ボタンが親ナビゲーターについて知っておく必要があることを意味し、これは理想的ではありません。ボタンが他のナビゲーターの中にさらにネストされている場合は、複数のgetParent()
呼び出しが必要になります。これに対処するために、id
プロパティを使用して親ナビゲーターを識別できます。
ドロワーの内容をカスタマイズするには、drawerContent
プロパティを使用して、カスタムコンポーネントをレンダリングする関数を渡すことができます。
最終的なコードは次のようになります。
import * as React from 'react';
import { Button, Text, View } from 'react-native';
import { createDrawerNavigator } from '@react-navigation/drawer';
import { NavigationContainer } from '@react-navigation/native';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
onPress={() => navigation.getParent('LeftDrawer').openDrawer()}
title="Open left drawer"
/>
<Button
onPress={() => navigation.getParent('RightDrawer').openDrawer()}
title="Open right drawer"
/>
</View>
);
}
function RightDrawerContent() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>This is the right drawer</Text>
</View>
);
}
const LeftDrawer = createDrawerNavigator();
function LeftDrawerScreen() {
return (
<LeftDrawer.Navigator
id="LeftDrawer"
screenOptions={{ drawerPosition: 'left' }}
>
<LeftDrawer.Screen name="Home" component={HomeScreen} />
</LeftDrawer.Navigator>
);
}
const RightDrawer = createDrawerNavigator();
function RightDrawerScreen() {
return (
<RightDrawer.Navigator
id="RightDrawer"
drawerContent={(props) => <RightDrawerContent {...props} />}
screenOptions={{
drawerPosition: 'right',
headerShown: false,
}}
>
<RightDrawer.Screen name="HomeDrawer" component={LeftDrawerScreen} />
</RightDrawer.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<RightDrawerScreen />
</NavigationContainer>
);
}
ここでは、ドロワーナビゲーターのid
プロパティに"LeftDrawer"
および"RightDrawer"
の文字列(任意の文字列を使用できます)を渡しています。次に、navigation.getParent('LeftDrawer').openDrawer()
を使用して左側のドロワーを開き、navigation.getParent('RightDrawer').openDrawer()
を使用して右側のドロワーを開きます。
まとめ
- 複数のドロワーを配置するには、
react-native-drawer-layout
をドロワーナビゲーターと組み合わせて直接使用できます。 drawerPosition
プロパティを使用すると、ドロワーを右側に配置できます。react-native-drawer-layout
を使用する場合、ドロワーを制御する方法はコンテキストAPIを使用して渡すことができます。- 複数のナビゲーターをネストする場合、
navigation.getParent
をid
プロパティと組み合わせて使用すると、目的のドロワーを参照できます。