带有嵌套DrawerNavigator,TabNavigator和StackNavigator的Deeplink

时间:2019-07-24 14:25:56

标签: react-native react-navigation deep-linking deeplink

我正在尝试在official documentation之后为我的React Native应用程序配置深层链接,但是我无法使其工作。我的意思是,如果我运行android:windowBackgroundadb shell am start -W -a android.intent.action.VIEW -d “crf://" packageName,但该应用确实会打开,但是我无法打开特定的屏幕。它总是启动到应用程序主屏幕。我几乎可以确定它与嵌套导航器有关,因为我在xcrun simctl openurl booted crf://内有一个TabbarNavigator,在所有这些内都有一个DrawerNavigator。我遵循了文档中有关嵌套导航器的说明,除其他事项外,还遵循了this post,但没有运气。我想去StackNavigatorEventHomeScreenPersonDetailScreen

这是我的代码:

NavigatorRouter

ProgramSessionDetail

App.js

const mainNavigator =  createStackNavigator(
  { 
    [Constants.APP_HOME_SCENE_KEY]:{
      screen: AppHomeScreen,
      navigationOptions: {
        title: 'App Home',
        showBack: false,
        showSearch: false,
      },
      path: ''
    },
    [Constants.EVENT_HOME_SCENE_KEY]:{
      screen:  navPropMapper()(EventHomeScreen),
      navigationOptions:{
        title: 'Home',
        path: 'event'
      }
    },
    [Constants.ATTENDEE_DETAIL_SCENE_KEY]:{
      screen: navPropMapper()(PersonDetailScreen),
      navigationOptions:{
        title: 'Attendee Detail', 
        // path: 'person/:user'
        path: 'person'
      }
    },
    [Constants.PROGRAM_DETAIL_SCENE_KEY]:{
      screen:  navPropMapper()(ProgramSessionDetail),
      navigationOptions:{
        title: 'Program',
        path: 'program/:idLecture'
      }
    }
  },
  { 
    initialRouteName: `${Constants.APP_HOME_SCENE_KEY}`, 
    defaultNavigationOptions: {
      header: props => <NavBar {...props} />,
      gesturesEnabled: false,
      showBack: true,
      showHome: false,
      showSearch: true,
      showWebExplorer: false
    }
  });

const tabbarNavigator = createBottomTabNavigator({
    Main: {
      screen: mainNavigator,
      path: 'tabs'
    },
  }, {
    tabBarComponent: Tabbar,
  });

const drawerNavigator = createDrawerNavigator({
    Drawer: {
      screen: tabbarNavigator,
      navigationOptions:{
        drawerLockMode: 'locked-closed',
      },
      path: 'drawer'
    },
  }, {
    contentComponent: ({ props }) => <DrawerContainer {...props}/>,
    drawerPosition: 'right',
    unmountInactiveRoutes: true,
    defaultNavigationOptions: {
      header: null,
    }
  });

const wraperNavigator = createStackNavigator({
  MainComponents: {
    screen: drawerNavigator,
    path: 'main'
  },
  [Constants.MODAL_FEEDBACK]:{
    screen:  navPropMapper()(Modal),
    navigationOptions:{
      title: 'Feedback',
    }
  },
  [Constants.MODAL_LOGIN]:{
    screen:  navPropMapper()(ModalLogin),
    navigationOptions:{
      title: 'Login',
    }
  },
}, {
  mode: 'modal',
  cardStyle:{
    backgroundColor: 'transparent',
    opacity: 1,
  },
  cardShadowEnabled: true,
  cardOverlayEnabled: true,
  transparentCard: true,
  defaultNavigationOptions: {
    header: null,
    gesturesEnabled: false,
  },
}); 

export default createAppContainer(wraperNavigator)

RootContainer

class App extends Component {

  render () {
    return (
      <Provider store={store}>
        <RootContainer />
      </Provider>
    )
  }
}

export default App

iOS Uri和Scheme

AppDelegate.m

class CRrootContainer extends Component {

  render () {
    return (
      <View style={styles.applicationView}>
        <NavigationRouter uriPrefix={'crf://'}/>
      </View>
    )
  }
}

const mapStateToProps = (state) => {
  return {
    navState: state.navigation,
  }
}

// wraps redux integration
const mapDispatchToProps = (dispatch) => ({
  startup: () => dispatch(StartupActions.startup()),
})

export default connect(mapStateToProps, mapDispatchToProps)(rootContainer)

URL类型:

URL types

Android方案:

AndroidManifest.xml

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
  return [RCTLinkingManager application:application openURL:url
                      sourceApplication:sourceApplication annotation:annotation];
}

我正在尝试的命令是:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="packageName"> <application android:name=".MainApplication" android:allowBackup="true" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:theme="@style/AppTheme"> <activity android:name=".MainActivity" android:label="@string/app_name" android:screenOrientation="portrait" android:configChanges="keyboard|keyboardHidden|orientation|screenSize" android:launchMode="singleTask"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="crf"/> </intent-filter> </activity> </application> </manifest> (适用于iOS)。

xcrun simctl openurl booted crf://main/drawer/tabs/event for Android(packageName是我的应用包的名称。

我的adb shell am start -W -a android.intent.action.VIEW -d “crf://main/drawer/tabs/event" packageName版本是react-navigation3.6.1

2 个答案:

答案 0 :(得分:0)

您可以尝试设置 事件监听器 吗?

class CRrootContainer extends Component {
  async componentDidMount(){
    if (Platform.OS === "android") {
      let url = await Linking.getInitialURL();
      if(url) this._setDeepLink(url);
    } else {
      Linking.addEventListener("url", this._handleOpenURL);
    }
  };
  _handleOpenURL = event => {
    this._setDeepLink(event.url);
  };
  _setDeepLink = url => {
    const { navigate } = this.props.navigation;
    const route = url.replace(/.*?:\/\//g, "");
    const routeName = route.split("/")[0];
    console.log("root====>", routeName);

    if (routeName === "foo") {
      navigate("fooRoute"); // to navigate route based on deep link url 
    }
  };
  componentWillUnmount() {
    Linking.removeEventListener("url");
  } 
  render () {
    return (
      <View style={styles.applicationView}>
        <NavigationRouter uriPrefix={'crf://'}/>
      </View>
    )
  }
}

const mapStateToProps = (state) => {
  return {
    navState: state.navigation,
  }
}

// wraps redux integration
const mapDispatchToProps = (dispatch) => ({
  startup: () => dispatch(StartupActions.startup()),
})

export default connect(mapStateToProps, mapDispatchToProps)(rootContainer)

答案 1 :(得分:0)

因此,它最终陷入了新秀错误,将path:关键字放在错误的位置;它需要放在navigationOptions之外,而不是在里面。另外,抽屉式导航器和标签栏导航器上的路径值应为空。

const mainNavigator =  createStackNavigator(
{ 
    [Constants.APP_HOME_SCENE_KEY]:{
      screen: AppHomeScreen,
      navigationOptions: {
        title: 'App Home',
        showBack: false,
        showSearch: false,
      },
      path: ''
    },
    [Constants.EVENT_HOME_SCENE_KEY]:{
      screen:  navPropMapper()(EventHomeScreen),
      navigationOptions:{
        title: 'Home',
      },
      path: 'event'
    },
    [Constants.ATTENDEE_DETAIL_SCENE_KEY]:{
      screen: navPropMapper()(PersonDetailScreen),
      navigationOptions:{
        title: 'Attendee Detail'
      },
      path: 'person'
    },
    [Constants.PROGRAM_DETAIL_SCENE_KEY]:{
      screen:  navPropMapper()(ProgramSessionDetail),
      navigationOptions:{
        title: 'Program'
      },
      path: 'program/:idLecture'
    }
  },
  { 
    initialRouteName: `${Constants.APP_HOME_SCENE_KEY}`, 
    defaultNavigationOptions: {
      header: props => <NavBar {...props} />,
      gesturesEnabled: false,
      showBack: true,
      showHome: false,
      showSearch: true,
      showWebExplorer: false
    }
  });

const tabbarNavigator = createBottomTabNavigator({
    Main: {
      screen: mainNavigator,
      path: ''
    },
  }, {
    tabBarComponent: Tabbar,
  });

const drawerNavigator = createDrawerNavigator({
    Drawer: {
      screen: tabbarNavigator,
      navigationOptions:{
        drawerLockMode: 'locked-closed',
      },
      path: ''
    },
  }, {
    contentComponent: ({ props }) => <DrawerContainer {...props}/>,
    drawerPosition: 'right',
    unmountInactiveRoutes: true,
    defaultNavigationOptions: {
      header: null,
    }
  });

const wraperNavigator = createStackNavigator({
  MainComponents: {
    screen: drawerNavigator,
    path: ''
  },
  [Constants.MODAL_FEEDBACK]:{
    screen:  navPropMapper()(Modal),
    navigationOptions:{
      title: 'Feedback',
    }
  },
  [Constants.MODAL_LOGIN]:{
    screen:  navPropMapper()(ModalLogin),
    navigationOptions:{
      title: 'Login',
    }
  },
}, {
  mode: 'modal',
  cardStyle:{
    backgroundColor: 'transparent',
    opacity: 1,
  },
  cardShadowEnabled: true,
  cardOverlayEnabled: true,
  transparentCard: true,
  defaultNavigationOptions: {
    header: null,
    gesturesEnabled: false,
  },
}); 

export default createAppContainer(wraperNavigator)