Skip to content

Fix/layout freeze paper #978

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions ios/RNCPagerView.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
#import <React/RCTView.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTShadowView.h>
#import <React/UIView+React.h>
#import <UIKit/UIKit.h>
#import "UIView+isHorizontalRtlLayout.h"

NS_ASSUME_NONNULL_BEGIN

@interface RNCPagerView: UIView <RtlLayoutProtocol>
@interface RNCPagerView: RCTView <RtlLayoutProtocol>

- (instancetype)initWithEventDispatcher:(id<RCTEventDispatcherProtocol> )eventDispatcher;
- (instancetype)initWithBridge:(RCTBridge *)bridge;

@property(nonatomic) NSInteger initialPage;
@property(nonatomic) NSInteger lastReportedIndex;
@@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN
@property(nonatomic, copy) RCTDirectEventBlock onPageScrollStateChanged;
@property(nonatomic) BOOL overdrag;
@property(nonatomic) NSString* layoutDirection;
@property(nonatomic, assign) BOOL animating;
@property(nonatomic, assign) BOOL transitioning;

- (void)goTo:(NSInteger)index animated:(BOOL)animated;
- (void)shouldScroll:(BOOL)scrollEnabled;
20 changes: 15 additions & 5 deletions ios/RNCPagerView.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import "RNCPagerView.h"
#import <React/RCTLog.h>
#import <React/RCTViewManager.h>
#import <React/RCTUIManager.h>

#import "UIViewController+CreateExtension.h"
#import "RCTOnPageScrollEvent.h"
@@ -13,7 +14,7 @@ @interface RNCPagerView () <UIPageViewControllerDataSource, UIPageViewController
@property(nonatomic, assign) UIPanGestureRecognizer* panGestureRecognizer;

@property(nonatomic, strong) UIPageViewController *reactPageViewController;
@property(nonatomic, strong) RCTEventDispatcher *eventDispatcher;
@property(nonatomic, strong) id<RCTEventDispatcherProtocol> eventDispatcher;

@property(nonatomic, weak) UIScrollView *scrollView;
@property(nonatomic, weak) UIView *currentView;
@@ -30,10 +31,12 @@ - (void)shouldDismissKeyboard:(NSString *)dismissKeyboard;

@implementation RNCPagerView {
uint16_t _coalescingKey;
__weak RCTBridge * _bridge;
}

- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher {
- (instancetype)initWithBridge:(RCTBridge *)bridge {
if (self = [super init]) {
_bridge = bridge;
_scrollEnabled = YES;
_pageMargin = 0;
_lastReportedIndex = -1;
@@ -44,7 +47,7 @@ - (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher {
_dismissKeyboard = UIScrollViewKeyboardDismissModeNone;
#endif
_coalescingKey = 0;
_eventDispatcher = eventDispatcher;
_eventDispatcher = bridge.eventDispatcher;
_cachedControllers = [NSHashTable hashTableWithOptions:NSHashTableStrongMemory];
_overdrag = NO;
_layoutDirection = @"ltr";
@@ -178,7 +181,7 @@ - (void)setReactViewControllers:(NSInteger)index
uint16_t coalescingKey = _coalescingKey++;

if (animated == YES) {
self.animating = YES;
[self setTransitioning:YES];
}

[self.reactPageViewController setViewControllers:@[controller]
@@ -190,6 +193,8 @@ - (void)setReactViewControllers:(NSInteger)index
strongSelf.currentView = controller.view;

[strongSelf enableSwipe];

[strongSelf setTransitioning:NO];

if (finished) {
strongSelf.animating = NO;
@@ -241,6 +246,11 @@ - (void)disableSwipe {
self.reactPageViewController.view.userInteractionEnabled = NO;
}

- (void)setTransitioning:(BOOL)transitioning {
_transitioning = transitioning;
[_bridge.uiManager setLocalData:@{@"transitioning": @(transitioning)} forView:self];
}

- (void)enableSwipe {
self.reactPageViewController.view.userInteractionEnabled = YES;
}
@@ -267,7 +277,7 @@ - (void)goTo:(NSInteger)index animated:(BOOL)animated {

long diff = labs(index - _currentIndex);

[self goToViewController:index direction:direction animated:(!self.animating && animated) shouldCallOnPageSelected: YES];
[self goToViewController:index direction:direction animated:(!_transitioning && animated) shouldCallOnPageSelected: YES];

if (diff == 0) {
[self goToViewController:index direction:direction animated:NO shouldCallOnPageSelected:YES];
11 changes: 8 additions & 3 deletions ios/RNCPagerViewManager.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

#import "RNCPagerViewManager.h"

#import "RNCPagerViewShadowView.h"
@implementation RNCPagerViewManager

#pragma mark - RTC
@@ -30,7 +30,7 @@ - (void) goToPage
RCTLogError(@"Cannot find RNCPagerView with tag #%@", reactTag);
return;
}
if (!animated || !view.animating) {
if (!animated || !view.transitioning) {
[view goTo:index.integerValue animated:animated];
}
}];
@@ -80,7 +80,12 @@ - (void) changeScrollEnabled


- (UIView *)view {
return [[RNCPagerView alloc] initWithEventDispatcher:self.bridge.eventDispatcher];
return [[RNCPagerView alloc] initWithBridge: self.bridge];
}


- (RCTShadowView *)shadowView {
return [RNCPagerViewShadowView new];
}

@end
5 changes: 5 additions & 0 deletions ios/RNCPagerViewShadowView.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#import <React/RCTShadowView.h>

@interface RNCPagerViewShadowView : RCTShadowView

@end
24 changes: 24 additions & 0 deletions ios/RNCPagerViewShadowView.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#import "RNCPagerViewShadowView.h"

@implementation RNCPagerViewShadowView {
BOOL _transitioning;
}

- (void)layoutWithMetrics:(RCTLayoutMetrics)layoutMetrics
layoutContext:(RCTLayoutContext)layoutContext {
// Prevent layout updates during a transition, as they cause the `setViewControllers`
// method to skip calling its completion block.
if (_transitioning) {
return;
}

[super layoutWithMetrics:layoutMetrics layoutContext:layoutContext];
}

- (void)setLocalData:(NSDictionary *)localData {
[super setLocalData:localData];

_transitioning = [localData[@"transitioning"] boolValue];
}

@end