React Navigation: применение отдельных переходов к сценам

Я хочу применить различные переходы к сценам в моем StackNavigator в React Navigation для моего приложения React Native (iOS).

export const AppNavigator = StackNavigator({
  Home: { screen: Home },
  NewChild: { screen: NewChild },
  Journal: { screen: Journal }
});

Я мог бы захотеть, чтобы NewChild загружался снизу вверх, как модальное окно. Или я мог бы хотеть, чтобы он скользил справа налево. Было бы здорово, если бы это можно было настроить. Из документации кажется, что вы можете установить для своей StackNavigation либо карточку, либо модальность для всего этого.


person Seán McGowan    schedule 08.07.2017    source источник
comment
Вы можете использовать пользовательский переходник, чтобы сделать любой переход, который вы хотите. Есть несколько хороших статей о том, как это делается. Я постараюсь связать их.   -  person Kraylog    schedule 08.07.2017
comment
Эта проблема также определяет хак, который вы можете использовать для получения различной конфигурации для каждого экрана в навигаторе. github.com/react-community/react-navigation/issues/707   -  person Kraylog    schedule 08.07.2017
comment
Круто, спасибо за ссылку!   -  person Seán McGowan    schedule 09.07.2017


Ответы (3)


Как вы уже видели в документации, сейчас это невозможно. Вы можете отслеживать эту проблему и эта проблема, запрашивающая эту функцию. Он включен в дорожную карту для версии 2, но, поскольку версия 1 даже не выпущен еще, ваш лучший выбор, вероятно, либо:

  1. Реализуйте свой собственный transitionConfig, который каким-то образом обрабатывает это для каждого экрана. Я не уверен, возможно ли это.
  2. Создайте форк реализации, используя идеи из основного выпуска. Или просто сделайте свой форк специфичным для вашего кода и поддерживайте его до тех пор, пока эта проблема не будет решена.
person Michael Cheng    schedule 08.07.2017
comment
Понятно. Спасибо за ответ Михаил. - person Seán McGowan; 09.07.2017

Спасибо всем в теме, мне помогло.

У меня много сцен, которыми управляет только один StackNavigator, и я хотел сделать для некоторых из них другую анимацию.

Прежде всего, я сделал константу в своем маршрутизаторе, которая включала все сцены, которые я хотел отобразить с горизонтальным переходом:

const horizontalTransitionScenes = [
  AddContact,
];

После этого я разработал свой маршрутизатор приложений с помощью StackNavigator:

const App = StackNavigator({
  AddContact: {
    screen: AddContact,
  },
  EditContact: {
    screen: EditContact,
  },
});

Я использовал CardStackStyleInterpolator, чтобы изменить переходы между сценами. Меня можно импортировать так: import CardStackStyleInterpolator from 'react-navigation/src/views/CardStack/CardStackStyleInterpolator';

Теперь мы можем добавить параметры transitionConfig в наш StackNavigator, чтобы отображать различную анимацию в зависимости от наших сцен:

 const App = StackNavigator(
{
    AddContact: {
        screen: AddContact
    },
    EditContact: {
        screen: EditContact
    }
},
{
    transitionConfig: (currentState: any) => {
        if (
            currentState.scenes[
                currentState.scenes.length - 1
            ].route.routeName.includes(horizontalTransitionScenes)
        ) {
            return {
                screenInterpolator: CardStackStyleInterpolator.forHorizontal
            };
        }
        return {
            screenInterpolator: CardStackStyleInterpolator.forVertical
        };
    }
}
);

С помощью этой реализации StackNavigator вы сможете отображать различные виды анимации для нужных вам сцен.

Хорошего дня ????

person William Garneau    schedule 13.08.2018

Я смог добиться этого, выполнив некоторую условную логику, мы находимся на react-navigation 3.3.2.

Вы должны импортировать Easing и Animated из react-native, а затем вы можете условно отображать переходы для определенного экрана по имени или также по индексу (ниже по имени).

Объявляя конфигурацию вне навигатора и переключая transitionSpec на {}, он сработает только на этом конкретном экране — то же самое с условием для screenInterpolator.

От Screen1 до Screen2 есть анимация, но ни на одном другом экране такой анимации нет.

const screen2Config = {
  duration: 300,
  easing: Easing.out(Easing.poly(4)),
  timing: Animated.timing,
};

export const ScreenStack = createStackNavigator({
  Screen1: {
    screen: Screen1,
    navigationOptions: ({ navigation }) => ({
      headerTitle: 'Screen1',
      headerTitleAllowFontScaling: false,
    }),
  },
  Screen2: {
    screen: Screen2,
    navigationOptions: ({ navigation }) => ({
      headerTitle: 'Screen2',
      headerTitleAllowFontScaling: false,
      tabBarVisible: false,
    }),
  },
  Screen3: {
    screen: Screen3,
    navigationOptions: ({ navigation }) => ({
      headerTitle: 'Screen3',
      headerTitleAllowFontScaling: false,
    }),
  },
  Screen4: {
    screen: Screen4,
    navigationOptions: ({ navigation }) => ({
      headerTitle: 'Screen4',
      headerTitleAllowFontScaling: false,
    }),
  },
}, {
  headerMode: 'float',
  mode: 'modal',
  transitionConfig: sceneProps => ({
    transitionSpec: sceneProps.scene.route.routeName === 'Screen2' ? screen2Config : {},
    screenInterpolator: (sceneProps) => {
      if (sceneProps.scene.route.routeName === 'Screen2') {
        const { layout, position, scene } = sceneProps;
        const { index } = scene;

        const width = layout.initWidth;
        const translateX = position.interpolate({
          inputRange: [index - 1, index, index + 1],
          outputRange: [width, 0, 0],
        });

        const opacity = position.interpolate({
          inputRange: [index - 1, index - 0.99, index],
          outputRange: [0, 1, 1],
        });

        return { opacity, transform: [{ translateX }] };
      }
    },
  }),
});
person Sara Inés Calderón    schedule 21.03.2019