Реализация UISplitViewController с использованием React Navigation - PullRequest
0 голосов
/ 11 мая 2018

Мне нужно реализовать поддержку планшетов в приложении React Native, над которым я работаю. Мы решили, что использование UISplitViewController имеет для нас наибольшее значение, но React Navigation (https://reactnavigation.org) не поддерживает его.

Я попытался решить эту проблему простым способом, поместив 2 навигатора рядом друг с другом и изменив их getStateForAction, чтобы открыть определенные экраны в подробном представлении:

export interface Props {
  MasterNavigator: NavigationContainer;
  DetailNavigator: NavigationContainer;
  detailRouteNames: string[];
}

export class MasterDetailView extends React.Component<Props> {
  masterNavigator: any;
  detailNavigator: any;

  componentDidMount() {
    const { MasterNavigator, DetailNavigator, detailRouteNames } = this.props;
    const defaultMasterGetStateForAction = MasterNavigator.router.getStateForAction;

    MasterNavigator.router.getStateForAction = (action: any, state: any) => {
      if (action.type === NavigationActions.NAVIGATE && detailRouteNames.indexOf(action.routeName) !== -1) {
        action.params.isRootScreen = true;
        this.detailNavigator.dispatch(NavigationActions.reset({ index: 0, actions: [action] }));

        return state;
      }

      return defaultMasterGetStateForAction(action, state);
    };

    const defaultDetailGetStateForAction = DetailNavigator.router.getStateForAction;

    DetailNavigator.router.getStateForAction = (action: any, state: any) => {
      if (action.type === NavigationActions.BACK && state.routes.length === 1) {
        this.masterNavigator.dispatch(NavigationActions.back());
        return null;
      }

      return defaultDetailGetStateForAction(action, state);
    };
  }

  render() {
    const { MasterNavigator, DetailNavigator } = this.props;

    return (
      <View style={styles.view}>
        <View style={styles.masterContainer}>
          <MasterNavigator ref={(mn: any) => this.masterNavigator = mn}/>
        </View>
        <View style={styles.divider}/>
        <View style={styles.detailContainer}>
          <DetailNavigator ref={(dn: any) => this.detailNavigator = dn}/>
        </View>
      </View>
    );
  }
}

Главный навигатор - это TabNavigator с StackNavigator с на каждой вкладке, подробный навигатор - StackNavigator. Вот как это выглядит: result

Этот подход вроде работает, но кнопка возврата на Android ведет себя некорректно. Я хочу, чтобы он возвращался назад в подробном навигаторе, затем в главном навигаторе. Можно заставить его работать с парой хаков, но тогда становится невозможным вернуться назад из приложения с помощью кнопки назад (по какой-то причине, когда я нажимаю на нее, ничего не происходит). Я мог бы попытаться исправить это, переопределив поведение кнопки «Назад» и отправив действие «Назад» на навигаторы мастер / подробности или закрыв приложение, но при отправке действия на навигатор невозможно узнать, ответило ли оно на него или нет ( особенно с главным навигатором, который является TabNavigator), поэтому кажется, что я застрял.

Есть ли какие-то особые соображения при использовании навигаторов таким образом? Подходит ли React Navigation для этого варианта использования? Если нет, то каковы другие способы эмуляции UISplitViewController в приложениях React Native?

1 Ответ

0 голосов
/ 13 мая 2018

Проблема с неправильным поведением кнопки «назад» была моей ошибкой. На одном из экранов был обработчик кнопки «Назад», который всегда возвращал true, что потребляло все нажатия кнопок «Назад» (да!). Я исправил это и добавил следующий обработчик кнопки возврата в MasterDetailView:

private onPressBack = (): boolean => {
    const action = NavigationActions.back();
    return this.detailNavigator.dispatch(action) || this.masterNavigator.dispatch(action);
};

И да, есть способ выяснить, использовал ли навигатор действие: navigator.dispatch(action) возвращает true, если событие было использовано, и false в противном случае.

Как только проблема с кнопкой возврата устранена, эта установка очень хорошо эмулирует UISplitViewController.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...