上一篇文章讲了如何用react-navigation
建立各类自定义头部(header)。css
这篇水文讲一下如何实现header右部的菜单项。暂时只支持IOS,缘由后文会说明,并给出一些未论证的想法react
参考京东商品详情页右上角的交互。android
自定义头部右侧很简单,配置navigationOptions
的headerRight
选项,传入咱们的自定义组件便可。git
const AppNavigator = createStackNavigator( { Home: { screen: Home, navigationOptions: { title: '首页' } }, GoodDetail: { screen: GoodDetail, navigationOptions: ({navigation}) => ({ headerTransparent: true, headerStyle: { borderBottomWidth: 0, }, headerTintColor: '#313131', shadowOpacity: 0, headerRight: <HeaderRight navigation={navigation}/> }) } } )
HeaderRight怎么写?分析一哈:github
isMenuVisible
class HeaderRight extends Component { constructor() { super() this.state = { isMenuVisible: false } } toggleMenu = () => { this.setState((prevState) => { isMenuVisible: !prevState.isMenuVisible }) } render() { return ( <TouchableOpacity onPress={this.toggleMenu}> <Image source={require('/path/to/image')}/> { isMenuVisible && ( <HeaderMenu navigation={this.props.navigation} /> ) } </TouchableOpacity> ) } }
哦了,HeaderMenu
是一个无状态组件,也就是菜单项,样式根据业务自行写咯~segmentfault
写完以后好像没什么问题的,可是若是你滚动你的页面(若是你的页面能够滚动),你会发现菜单项不会本身消失。react-native
这怎么行!闭包
解决方法: 咱们给HeaderMenu
外层包裹一个View,宽高为容器宽高,绝对定位,使其充满整个屏幕。再在外层包裹一个TouchableWithoutFeedback
,注册onPress
,点击时执行隐藏菜单的函数,而这个函数能够定义在HeaderRight
中,经过props传递给HeaderMenu
函数
其实我是在写这篇文章的时候才发现,我这个方法只支持IOS(之前用的是另一个方法)。 究其缘由是RN在Android端不支持显示超出父元素部分的内容,用css的话来说就是overflow: hidden
并且只能是hidden。布局
这方面的呼声也不低,期待官方能解决吧。
HeaderMenu
部分写在对应的组件中。在配置HeaderRight时,经过一个闭包保存菜单项的状态。每次点击经过navigation的setParams
API来对指定页面传递这个状态。
这个方法也有缺陷,若是header不是透明的,则菜单项会被header覆盖,就算紧贴header也会略显难看。 以及布局方便须要大改动,而且很麻烦。提一点:菜单项的position是absolute。
react-native-view-overflow
这是我刚搜到的解决方案,经过包裹一层组件来达到显示超出部分的内容的效果。
import ViewOverflow from 'react-native-view-overflow'; <ViewOverflow> <ComponentToEnableOverflow /> </ViewOverflow>
在咱们这个情景下,就要改写默认的header组件,小伙伴能够自行尝试。(丢连接就跑,真刺激)
源代码能够在GitHub上看到。
效果图: