React-native-navigation: [v2] Animating custom transitions for push?

Created on 23 Oct 2018  路  17Comments  路  Source: wix/react-native-navigation

Issue Description

For some reason, I can't get any custom push animations to work on ios (havent tried android)
I can put following object in setDefaultOptions or push and nothing will work. I've tried alpha, x, y, scale, but no dice.

Also, interestingly, the animations: { enabled: 'true'} value works. If i set to false, there is no transition. However, virtually anything else I do inside of animations: {push: { ... }} does not work.

I've tried with and without content. Any tips?

Thanks

Steps to Reproduce / Code Snippets / Screenshots

Navigation.push(this.props.componentId, {
  component: {
    id: 'blah',
    name: 'blah',
    passProps: {},
    options: {
            animations: {
              push: {
                enabled: "true",
                content: {
                  alpha: {
                    from: 0,
                    to: 1,
                    duration: 3000,
                    interpolation: "accelerate"
                  }
                }
              }
            }
          }
      }
    }
  }

Environment

  • React Native Navigation version: 2.0.2608
  • React Native version: 0.57.3
  • Platform(s) (iOS, Android, or both?): ios
  • Device info (Simulator/Device? OS version? Debug/Release?): Simulator Debug
iOS acceptebug good first task 馃搶 pinned

Most helpful comment

I can confirm that #4105 has broken "animations" options for "topBar", "bottomTabs", "content" in iOS. Would you like me to submit a pull request with a fix?

All 17 comments

Can confirm on android transition animation working. On iOS not.

I can confirm that #4105 has broken "animations" options for "topBar", "bottomTabs", "content" in iOS. Would you like me to submit a pull request with a fix?

Also, there appears to be a discrepancy with the documentation, the Options.ts interfaces and the actual iOS implementation for animation properties.
i.e.
content: { alpha: { from: 0, to: 1, duration: 3000, interpolation: "accelerate" } }
would actually have to be set to the following according to implementation:
content: { startAlpha: 0, endAlpha: 1, duration: 3, interpolation: "accelerate" }

The duration also has to be entered in seconds instead of milliseconds, and defaults to 1s instead of 300ms, both of which contradict the documentation.

Let me know if I can help in any way for the above stated issues.
Cheers.

npm version "2.0.2582" was the latest version I could use retaining the animations options functionality. "2.0.2583" would load with a stack trace and "2.0.2584" onwards the options is behaving like described.

Any update on this?

Tried @enlightenedmouse solution but no dice. I can get Navigation.Element transitions to work (which use that API) but not screens.

Any update on this?

I've got a workaround going for this that solves the issue [V2][iOS] Push Animations Not Working #4419

You'll need to modify RNNScreenTransition.h and RNNScreenTransition.m

RNNScreenTransition.h

#import "RNNOptions.h"
#import "RNNTransitionStateHolder.h"

@interface RNNScreenTransition : RNNOptions

@property (nonatomic, strong) RNNTransitionStateHolder* topBar;
@property (nonatomic, strong) RNNTransitionStateHolder* content;
@property (nonatomic, strong) RNNTransitionStateHolder* bottomTabs;

@property (nonatomic) BOOL hasTopBar;
@property (nonatomic) BOOL hasContent;
@property (nonatomic) BOOL hasBottomTabs;

@property (nonatomic) BOOL enable;
@property (nonatomic) BOOL waitForRender;

- (BOOL)hasCustomAnimation;

@end

RNNScreenTransition.m

#import "RNNScreenTransition.h"


@implementation RNNScreenTransition

- (instancetype)initWithDict:(NSDictionary *)dict {
    self = [super init];

    self.hasTopBar = [dict objectForKey: @"topBar"] != nil;
    self.hasContent = [dict objectForKey: @"content"] != nil;
    self.hasBottomTabs = [dict objectForKey: @"bottomTabs"] != nil;

    self.topBar = [[RNNTransitionStateHolder alloc] initWithDict: dict[@"topBar"]];
    self.content = [[RNNTransitionStateHolder alloc] initWithDict: dict[@"content"]];
    self.bottomTabs = [[RNNTransitionStateHolder alloc] initWithDict: dict[@"bottomTabs"]];

    self.enable = dict[@"enabled"] ? [dict[@"enabled"] boolValue] : YES;
    self.waitForRender = dict[@"waitForRender"] ? [dict[@"waitForRender"] boolValue] : NO;


    return self;
}

- (BOOL)hasCustomAnimation {
    return (self.hasTopBar || self.hasContent || self.hasBottomTabs);
}

@end

As @enlightenedmouse pointed out, instead of declaring transition options as stated in the docs, use the properties below. Duration is in seconds in stead of ms.

self.springDamping = [RNNUtils getDoubleOrKey:transition withKey:@"springDamping" withDefault:0.85];
self.springVelocity = [RNNUtils getDoubleOrKey:transition withKey:@"springVelocity" withDefault:0.8];
self.startDelay = [RNNUtils getDoubleOrKey:transition withKey:@"startDelay" withDefault:0];
self.duration = [RNNUtils getDoubleOrKey:transition withKey:@"duration" withDefault:1];
self.startAlpha = [RNNUtils getDoubleOrKey:transition withKey:@"startAlpha" withDefault:1];
self.endAlpha = [RNNUtils getDoubleOrKey:transition withKey:@"endAlpha" withDefault:1];
self.interactivePop = [RNNUtils getBoolOrKey:transition withKey:@"interactivePop" withDefault:NO];
self.startX = [RNNUtils getDoubleOrKey:transition[@"x"] withKey:@"from" withDefault:0];
self.startY = [RNNUtils getDoubleOrKey:transition[@"y"] withKey:@"from" withDefault:0];
self.endX = [RNNUtils getDoubleOrKey:transition[@"x"] withKey:@"to" withDefault:0];
self.endY = [RNNUtils getDoubleOrKey:transition[@"y"] withKey:@"to" withDefault:0];
self.fromId = [transition objectForKey:@"fromId"];
self.toId = [transition objectForKey:@"toId"];
self.isSharedElementTransition = [[transition objectForKey:@"type"] isEqualToString:@"sharedElement"];
self.interpolation = [self animationOptionsFromString:transition[@"interpolation"]];

For example, to have a pushed screen fade in instead of slide in:

Navigation.push('RootStack', {
                    component: {
                        name: 'LoginScreen',
                        options: {
                            animations: {
                                push: {
                                    waitForRender: true,
                                    content: {
                                        startAlpha: 0,
                                        endAlpha: 1,
                                        duration: 1,
                                        interpolation: "accelerate"
                                    }
                                },
                            },
                        }
                    }
                });

same here with 2.5.0

Hello,
I'm having same issue with 2.5.1
Can't anyone give us some information about how to get this working and/or when would that be ?
@guyca

Yeah this is quite a nightmare... any updates on this?

Hey guys, this should be resolved in 2.14.0-snapshot.246, would appreciate feedback if there's anything else to address in this matter. Thanks 馃檱

Got it working for both push & pop on Android (as before). On iOS we see that _push_ is now working as intended, but _pop_ is not. Can you confirm that this setup is correct:

    Navigation.push(this.props.componentId, {
        component: {
            name: 'MyComponent',
            options: {
                animations: {
                    pop: {
                        content: {
                            alpha: {
                                from: 1,
                                to: 0,
                                duration: 300,
                                startDelay: 0,
                                interpolation: 'decelerate',
                            },
                        },
                    },
                    push: {
                        waitForRender: true,
                        content: {
                            alpha: {
                                from: 0,
                                to: 1,
                                duration: 300,
                                startDelay: 0,
                                interpolation: 'accelerate',
                            },
                        },
                    },
                },
            },
        },
    })

Push works for iOS with the animation property alpha. Unfortunately I could not get it work with other properties like scaleX.

animations: { push: { enabled: "true", // waitForRender: true, content: { scaleX: { from: 0, to: 1, duration: 300, interpolation: "accelerate", }, }, },

Hey guys, this should be resolved in 2.14.0-snapshot.246, would appreciate feedback if there's anything else to address in this matter. Thanks 馃檱

Hi @guyca - in 2.14.0 - prior to #4880 being included - a showModal with _no_ custom animation configuration specified would result in a slide-up animation on iOS. Post 2.14.0, there is no slide-up animation on showModal (but there is a slide-down on dismissModal). I didn't see an open issue for this. Is this expected behavior (and if so, how can we restore the slide-up animation that was previously a default)?

@F1ow did you solve it ? I have the same issue scaleX doesn't work on ios. Can you help me. Thanks

@F1ow did you solve it ? I have the same issue scaleX doesn't work on ios. Can you help me. Thanks

Unfortunately not.

Was this page helpful?
0 / 5 - 0 ratings