带有路线或导航的 react-native-side-menu 的完整工作示例 [关闭]
Posted
技术标签:
【中文标题】带有路线或导航的 react-native-side-menu 的完整工作示例 [关闭]【英文标题】:Full working example of react-native-side-menu with routes or navigation [closed] 【发布时间】:2016-08-14 17:57:36 【问题描述】:我发现很少有帖子给出了一些关于如何将导航\路由与 react-native-side-menu 集成的“提示”,遗憾的是没有找到任何显示此类功能的完整工作示例的帖子。
我也不确定导航\路线最简单的实现是什么,以及这两个选项之间有什么区别(当然这不是专门针对侧边菜单,但在我的情况下应该结合在一起)。
任何人都可以指出这样的例子吗?
【问题讨论】:
【参考方案1】:所以最终我能够集成标准的 Navigator,如 Facebook 的官方示例代码所示:
https://github.com/facebook/react-native/tree/master/Examples/UIExplorer/Navigator
使用 react-native-side-menu 组件,整个代码如下所示:
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var SideMenu = require('react-native-side-menu');
var
Component,
Navigator,
AppRegistry,
View,
Text,
Image,
StyleSheet,
ScrollView,
TouchableOpacity
= ReactNative;
class FirstPage extends Component
render()
return (
<View style=styles.page><Text style=styles.pageContent>First Page</Text></View>
);
class FirstPageMenu extends Component
constructor(props)
super(props);
this.state = ;
toggle()
this.setState(
isOpen: !this.state.isOpen,
);
updateMenuState(isOpen)
this.setState( isOpen, );
onMenuItemSelected = (item) =>
this.setState(
isOpen: false,
selectedItem: item,
);
this.props.navigator.replace( id: item );
render()
const menu = <Menu onItemSelected=this.onMenuItemSelected navigator=this.props.navigator/>;
return (
<SideMenu
menu=menu
isOpen=this.state.isOpen
onChange=(isOpen) => this.updateMenuState(isOpen)>
<MenuButton onPress=() => this.toggle()/>
<FirstPage/>
</SideMenu>
);
;
class SecondPage extends Component
...
class SecondPageMenu extends Component
...
class ThirdPage extends Component
...
class ThirdPageMenu extends Component
...
class MenuNavigator extends Component
constructor(props)
super(props);
this._setNavigatorRef = this._setNavigatorRef.bind(this);
renderScene(route, nav)
switch (route.id)
case 'first':
return <FirstPageMenu navigator=nav />;
case 'second':
return <SecondPageMenu navigator=nav />;
case 'third':
return <ThirdPageMenu navigator=nav />;
default:
return <FirstPageMenu navigator=nav />;
render()
return (
<Navigator
ref=this._setNavigatorRef
initialRoute=id: 'first'
renderScene=this.renderScene
configureScene=(route) =>
if (route.sceneConfig)
return route.sceneConfig;
return Navigator.SceneConfigs.FloatFromBottom;
/>
);
componentWillUnmount()
this._listeners && this._listeners.forEach(listener => listener.remove());
_setNavigatorRef(navigator)
if (navigator !== this._navigator)
this._navigator = navigator;
if (navigator)
var callback = (event) =>
console.log(
`NavigatorMenu: event $event.type`,
route: JSON.stringify(event.data.route),
target: event.target,
type: event.type,
);
;
// Observe focus change events from the owner.
this._listeners = [
navigator.navigationContext.addListener('willfocus', callback),
navigator.navigationContext.addListener('didfocus', callback),
];
;
class MenuButton extends Component
handlePress(e)
if (this.props.onPress)
this.props.onPress(e);
render()
return (
<View style=styles.menuButton >
<TouchableOpacity
onPress=this.handlePress.bind(this)
style=this.props.style>
<Text>this.props.children</Text>
<Image
source= uri: 'http://i.imgur.com/vKRaKDX.png', width: 40, height: 40, />
</TouchableOpacity>
</View>
);
class Menu extends Component
static propTypes =
onItemSelected: React.PropTypes.func.isRequired,
;
constructor(props)
super(props);
render()
return (
<ScrollView scrollsToTop=false style=styles.menu>
<Text
onPress=() => this.props.onItemSelected('first')
style=styles.item>
First
</Text>
<Text
onPress=() => this.props.onItemSelected('second')
style=styles.item>
Second
</Text>
<Text
onPress=() => this.props.onItemSelected('third')
style=styles.item>
Third
</Text>
</ScrollView>
);
;
var styles = StyleSheet.create(
menuButton:
marginTop: 20,
backgroundColor: '#777'
,
menu:
flex: 1,
width: window.width,
height: window.height,
padding: 20,
,
item:
fontSize: 16,
fontWeight: '300',
paddingTop: 20,
,
page:
flex: 1,
alignItems: 'center',
backgroundColor: '#777'
,
pageContent:
flex: 1,
alignItems: 'center',
top: 200,
,
menu:
flex: 1,
width: window.width,
height: window.height,
padding: 20,
,
item:
fontSize: 16,
fontWeight: '300',
paddingTop: 20,
,
);
module.exports = MenuNavigator;
并且索引文件应该只指向导航器:
const React = require('react-native');
const AppRegistry, = React;
const MenuNavigator = require('./SideMenuWithNavigation');
AppRegistry.registerComponent('MyApp', () => MenuNavigator);
【讨论】:
有点棘手但有效!谢谢! 我想在单击侧面菜单中的注销图标时显示警报。这段代码有可能吗? 代替 this.props.onItemSelected 您可以为菜单中某些特定项目的 onPress 事件调用任何其他方法【参考方案2】:如果您指的是抽屉菜单,请检查 react-native-material-design 和给定的演示应用。
【讨论】:
我说的是这个组件:github.com/react-native-fellowship/react-native-side-menu【参考方案3】:我的 Github 上有一个带有 react-native-side-menu
和 navigator
的启动器。
这个初学者也使用redux(不会阻止回答如何处理导航器+侧边菜单)。
在使用侧边菜单时,routing
的 trick
用于替换之前的路线以防止其堆叠(就像在普通导航中一样):
navigate(route)
const routeStack = [].concat(this.refs.navigator.getCurrentRoutes());
const previousRouteId = routeStack[routeStack.length - 1].id;
if (route.id !== previousRouteId)
this.refs.navigator.replace(route);
if (this.state.sideMenuOpened)
this.closeSideMenu();
检查我的启动器reactNativeReduxFastStarter
快速预览代码:
import React,
Component
from 'react';
import
StyleSheet,
Text,
Dimensions,
Navigator,
StatusBar
from 'react-native';
import SideMenu from 'react-native-side-menu';
import Icon from 'react-native-vector-icons/Ionicons';
import AppRoutes from '../../../common/config';
import
SideMenuContent,
Button
from '../../components';
import Home from '../home';
import AppState from '../appState';
const SCREEN_WIDTH = Dimensions.get('window').width;
class App extends Component
constructor(props)
super(props);
this.init();
init()
this.state =
sideMenuOpened: false
;
openSideMenu()
this.setState(
sideMenuOpened : false
);
closeSideMenu()
if (this.state.sideMenuOpened)
this.setState(
sideMenuOpened : false
);
toggleSideMenu()
this.setState(
sideMenuOpened: !this.state.sideMenuOpened
);
updateSideMenuState(isOpened)
this.setState(
sideMenuOpened: isOpened
);
navigate(route)
const routeStack = [].concat(this.refs.navigator.getCurrentRoutes());
const previousRouteId = routeStack[routeStack.length - 1].id;
if (route.id !== previousRouteId)
this.refs.navigator.replace(route);
if (this.state.sideMenuOpened)
this.closeSideMenu();
renderScene(route, navigator)
switch (route.id)
case 1:
const route1 = AppRoutes.getRouteFromRouteId(1);
return (
<Home
ref=route1.refView
navigator=navigator
navigate=(toRoute)=>this.navigate(toRoute)
/>
);
case 2:
const route2 = AppRoutes.getRouteFromRouteId(2);
return (
<AppState
ref=route2.refView
navigator=navigator
navigate=(toRoute)=>this.navigate(toRoute)
/>
);
default:
return (
<Home
ref=route1.refView
navigator=navigator
navigate=(toRoute)=>this.navigate(toRoute)
/>
);
renderRouteMapper()
const routes = AppRoutes.getAllRoutes();
return
Title : (route, navigator, index, navState) =>
const currentRouteId = navState.routeStack[index].id;
return (
<Text style=styles.titleNavText>
routes[currentRouteId - 1].navbar.navBarTitle
</Text>
);
,
LeftButton : (route, navigator, index, navState) =>
const currentRouteId = navState.routeStack[index].id;
return (
<Button
style=styles.leftNavButton
onPress=(e)=>this.toggleSideMenu(e)
>
<Icon
name=routes[currentRouteId - 1].navbar.navBarLeftIconName
size=32
color='#333333'
/>
</Button>
);
,
RightButton : (route, navigator, index, navState) =>
return null;
;
render()
StatusBar.setBarStyle('light-content', true);
const DEFAULT_ROUTE = id: 1, refView: 'HomeView' ;
return (
<SideMenu
menu=<SideMenuContent
backGndColor="#ECECEC"
navigate=(route)=>this.navigate(route)
/>
isOpen=this.state.sideMenuOpened
onChange=(isOpened) => this.updateSideMenuState(isOpened)
bounceBackOnOverdraw=false
openMenuOffset=SCREEN_WIDTH * 0.8
>
<Navigator
ref="navigator"
initialRoute= DEFAULT_ROUTE
sceneStyle= styles.navigator
renderScene=(route, navigator)=>this.renderScene(route, navigator)
configureScene=()=>Navigator.SceneConfigs.Fadeandroid
navigationBar=
<Navigator.NavigationBar
routeMapper=this.renderRouteMapper()
style=styles.navBar
/>
/>
</SideMenu>
);
const styles = StyleSheet.create(
navigator:
backgroundColor: '#fff',
borderLeftWidth: 0.5,
borderLeftColor: '#F1F1F1',
,
navBar:
backgroundColor: '#fff',
borderWidth: 0.5,
borderColor: '#F1F1F1'
,
leftNavButton :
flex : 1,
flexDirection : 'column',
alignItems : 'center',
marginTop : 4,
paddingTop : 0,
paddingBottom : 10,
paddingLeft : 20,
paddingRight : 10
,
rightNavButton :
flex : 1,
flexDirection : 'column',
alignItems : 'center',
marginTop : 4,
paddingTop : 6,
paddingBottom : 10,
paddingLeft : 10,
paddingRight : 10
,
titleNavText :
marginTop : 14,
color : '#333333'
);
export default App;
【讨论】:
【参考方案4】:你可以在 github 上查看这个完整的 sidemenu 项目。本项目包含ToolbarAndroid、路由、DrawerLayoutAndroid、溢出菜单等组件。
https://github.com/darde/react-native-sidemenu
【讨论】:
以上是关于带有路线或导航的 react-native-side-menu 的完整工作示例 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章