首页 文章

自定义DrawerNavigator - ReactNative

提问于
浏览
0

我有通过DrawerNavigator的侧边菜单 . 我知道要自定义抽屉,它在“contentComponents”道具中 .

我想要举个例子,按下一个打开模态的按钮:Share(在其他社交媒体上分享应用)

但就目前而言,我所有的按钮都是路线 . 因此,如果我点击它,它会重定向到页面(正常) . 我只是想添加一个反应而不是重定向的按钮 .

我不知道如何在Component中动态定制 . 我想硬编码每个按钮(一些用于重定向,一些用于显示简单模态) .

这是我的代码:

index.android.js

const DrawerContent = (props) => (
<ScrollView>
    <View style={styles.container}>
        <Text style={styles.logo}>TechDico</Text>
        <Text style={{ paddingLeft: 10, paddingRight: 10, fontSize: 13, textAlign: 'center', color: '#f4f4f4' }}>Des millions de traductions classées par domaine d'activité</Text>
    </View>
    <DrawerItems style={{ marginTop: 30 }} {...props} />
</ScrollView>
)

const appNavigator = DrawerNavigator({
    Redirection1: {
        screen: Index,
        navigationOptions: {
            drawerLabel: 'Redirection1',
            drawerIcon: ({ tintColor }) => (<Icon name="home" size={20} color={tintColor} />),
        }
    },
    DisplayModal: {
        screen: Index,
        navigationOptions: {
            drawerLabel: 'DisplayModal',
            drawerIcon: ({ tintColor }) => (<Icon name="home" size={20} color={tintColor} />),
        }
    },
    Redirection2: {
        screen: Index,
        navigationOptions: {
            drawerLabel: 'Redirection2',
            drawerIcon: ({ tintColor }) => (<Icon name="home" size={20} color={tintColor} />),
        }
    }, }, {
        // define customComponent here
        contentComponent: DrawerContent,
        contentOptions: {
            inactiveTintColor: '#000000',
            activeTintColor: '#1eacff',
            showIcon: true,
        }
    });

Index class

export default class Index extends Component {
    renderRoot = () => {
        const { navigation } = this.props;

        console.log("My Navigation ", navigation);

        switch (navigation.state.key) {
            case 'Redirection1':
                return (
                    <App navigation={navigation} />
                );
            case 'DisplayModal':

// TODO I don't want to return so I can remove to cancel the redirection, but now, how can I display a modal without redirect. 
                return (
                    <DisplayModal navigation={navigation} />
                );
            case 'Redirection2':
                return (
                    <Redirection2 navigation={navigation} />
                );
            default:
                return (
                    <Test navigation={navigation} />
                );
        }
    }

我正在使用'react-navigation' .

1 回答

  • 2

    我也在考虑同样的任务 . 我认为有多个路由指向相同的屏幕类型可能最终导致状态管理混乱,因为每个屏幕实例都不同 .

    看看 DrawerSidebar / DrawerNavigatorItems 中的源代码,侧边栏列表中的所有项目似乎都是抽屉路径配置中的项目(除非我们完全重写 DrawerNavigatorItems ) . 因此,也许我们可能会为某些路线设置一个假屏幕,并在 componentWillMount 中实施所需的操作,然后导航到默认路由 .

    这是一个示例代码:

    let drawer = DrawerNavigator({
      Main: {
        screen: MainScreen,
      },
      About: {
        screen: AboutScreen,
      },
      ContactUs: {
        screen: ContactUsFakeScreen,
      },
    });
    
    const mailUrl = "mailto:test@test.com";
    
    class ContactUsFakeScreen extends React.Component {
        componentWillMount() {
            let self = this;
            Linking.canOpenURL(mailUrl)
                .then(self.openEmail)
                .catch(err => self.openEmail(false));
        }
    
        openEmail(supported) {
            if (supported) {
                Linking.openURL(mailUrl).catch(err => {});
            }
    
            let { navigation } = this.props;
            navigation.navigate('Main');        
        }
    
        render() {
            return null;
        }
    }
    

    这里 Main / MainScreenAbout / AboutScreen 是常规路线和屏幕,而 ContactUs / ContactUsFakeScreen 只是假装是路线和屏幕 . 单击 ContactUs 将触发 componentWillMount 处理电子邮件屏幕,然后最终导航到 MainScreenMain 路线) .

    另一种方法可能是从抽屉路由器劫持 getStateForAction 并在那里添加一些额外的路由逻辑来替换目标路由 . 这些方面的东西:

    const defaultDrawerGetStateForAction = drawer.router.getStateForAction;
    
        drawer.router.getStateForAction = (action, state) => {
            let newState = defaultDrawerGetStateForAction(action, state);
            if (action.type === 'Navigation/NAVIGATE' && action.routeName === 'ContactUs') {
                // extra logic here ...
                newState.routes.forEach(r => {
                    if (r.key === 'DrawerClose') {
                        // switching route from ContactUs to Main.
                        r.index = 0;
                    }
                });
            }
            return newState;
        }
    

    如果抽屉列表中的某个项目甚至不可操作(如版权),那么假屏幕看起来会更简单(通过 navigationOptions 注释样式):

    let drawer = DrawerNavigator({
        ...
        Copyright: {
            screen: Copyright,
        },
    });
    
    class Copyright extends React.Component {
        static navigationOptions = {
            drawerLabel: ({ tintColor, focused }) => 
                    (<Text style={{color: '#999'}}>Copyright 2017</Text>)
                )
    
        };
    
        componentWillMount() {
            let { navigation } = this.props;
            navigation.navigate('Main');        
        }
    
        render() {
            return null;
        }
    }
    

相关问题