mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-01-31 09:18:29 +08:00
Compare commits
7 Commits
2.0.0-beta
...
2.0.0-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
953b3b30db | ||
|
|
e50b7eae72 | ||
|
|
0e00f49e69 | ||
|
|
26d8dc21d2 | ||
|
|
3193e7da8f | ||
|
|
cce8373a20 | ||
|
|
823d11e691 |
@@ -252,7 +252,9 @@ public class ScreenContainer<T extends ScreenFragment> extends ViewGroup {
|
||||
if (!orphaned.isEmpty()) {
|
||||
Object[] orphanedAry = orphaned.toArray();
|
||||
for (int i = 0; i < orphanedAry.length; i++) {
|
||||
detachScreen((ScreenFragment) orphanedAry[i]);
|
||||
if (orphanedAry[i] instanceof ScreenFragment) {
|
||||
detachScreen((ScreenFragment) orphanedAry[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,10 @@ public class ScreenFragment extends Fragment {
|
||||
((ViewGroup) parent).endViewTransition(view);
|
||||
((ViewGroup) parent).removeView(view);
|
||||
}
|
||||
// view detached from fragment manager get their visibility changed to GONE after their state is
|
||||
// dumped. Since we don't restore the state but want to reuse the view we need to change visibility
|
||||
// back to VISIBLE in order for the fragment manager to animate in the view.
|
||||
view.setVisibility(View.VISIBLE);
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,11 +31,6 @@ public class ScreenStackFragment extends ScreenFragment {
|
||||
mFragment = fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startAnimation(Animation animation) {
|
||||
super.startAnimation(animation);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAnimationEnd() {
|
||||
super.onAnimationEnd();
|
||||
|
||||
@@ -35,7 +35,7 @@ public class ScreenViewManager extends ViewGroupManager<Screen> {
|
||||
public void setStackPresentation(Screen view, String presentation) {
|
||||
if ("push".equals(presentation)) {
|
||||
view.setStackPresentation(Screen.StackPresentation.PUSH);
|
||||
} else if ("modal".equals(presentation) || "containedModal".equals(presentation)) {
|
||||
} else if ("modal".equals(presentation) || "containedModal".equals(presentation) || "fullScreenModal".equals(presentation) || "formSheet".equals(presentation)) {
|
||||
// at the moment Android implementation does not handle contained vs regular modals
|
||||
view.setStackPresentation(Screen.StackPresentation.MODAL);
|
||||
} else if ("transparentModal".equals(presentation) || "containedTransparentModal".equals((presentation))) {
|
||||
|
||||
@@ -10,7 +10,9 @@ typedef NS_ENUM(NSInteger, RNSScreenStackPresentation) {
|
||||
RNSScreenStackPresentationModal,
|
||||
RNSScreenStackPresentationTransparentModal,
|
||||
RNSScreenStackPresentationContainedModal,
|
||||
RNSScreenStackPresentationContainedTransparentModal
|
||||
RNSScreenStackPresentationContainedTransparentModal,
|
||||
RNSScreenStackPresentationFullScreenModal,
|
||||
RNSScreenStackPresentationFormSheet
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, RNSScreenStackAnimation) {
|
||||
|
||||
@@ -80,6 +80,12 @@
|
||||
_controller.modalPresentationStyle = UIModalPresentationFullScreen;
|
||||
#endif
|
||||
break;
|
||||
case RNSScreenStackPresentationFullScreenModal:
|
||||
_controller.modalPresentationStyle = UIModalPresentationFullScreen;
|
||||
break;
|
||||
case RNSScreenStackPresentationFormSheet:
|
||||
_controller.modalPresentationStyle = UIModalPresentationFormSheet;
|
||||
break;
|
||||
case RNSScreenStackPresentationTransparentModal:
|
||||
_controller.modalPresentationStyle = UIModalPresentationOverFullScreen;
|
||||
break;
|
||||
@@ -315,6 +321,8 @@ RCT_EXPORT_VIEW_PROPERTY(onDismissed, RCTDirectEventBlock);
|
||||
RCT_ENUM_CONVERTER(RNSScreenStackPresentation, (@{
|
||||
@"push": @(RNSScreenStackPresentationPush),
|
||||
@"modal": @(RNSScreenStackPresentationModal),
|
||||
@"fullScreenModal": @(RNSScreenStackPresentationFullScreenModal),
|
||||
@"formSheet": @(RNSScreenStackPresentationFormSheet),
|
||||
@"containedModal": @(RNSScreenStackPresentationContainedModal),
|
||||
@"transparentModal": @(RNSScreenStackPresentationTransparentModal),
|
||||
@"containedTransparentModal": @(RNSScreenStackPresentationContainedTransparentModal)
|
||||
|
||||
@@ -10,6 +10,11 @@
|
||||
#import <React/RCTTouchHandler.h>
|
||||
|
||||
@interface RNSScreenStackView () <UINavigationControllerDelegate, UIAdaptivePresentationControllerDelegate, UIGestureRecognizerDelegate>
|
||||
|
||||
@property (nonatomic) NSMutableArray<UIViewController *> *presentedModals;
|
||||
@property (nonatomic) BOOL updatingModals;
|
||||
@property (nonatomic) BOOL scheduleModalsUpdate;
|
||||
|
||||
@end
|
||||
|
||||
@interface RNSScreenStackAnimator : NSObject <UIViewControllerAnimatedTransitioning>
|
||||
@@ -17,11 +22,9 @@
|
||||
@end
|
||||
|
||||
@implementation RNSScreenStackView {
|
||||
BOOL _needUpdate;
|
||||
UINavigationController *_controller;
|
||||
NSMutableArray<RNSScreenView *> *_reactSubviews;
|
||||
NSMutableSet<RNSScreenView *> *_dismissedScreens;
|
||||
NSMutableArray<UIViewController *> *_presentedModals;
|
||||
__weak RNSScreenStackManager *_manager;
|
||||
}
|
||||
|
||||
@@ -34,7 +37,6 @@
|
||||
_dismissedScreens = [NSMutableSet new];
|
||||
_controller = [[UINavigationController alloc] init];
|
||||
_controller.delegate = self;
|
||||
_needUpdate = NO;
|
||||
[self addSubview:_controller.view];
|
||||
_controller.interactivePopGestureRecognizer.delegate = self;
|
||||
|
||||
@@ -160,8 +162,23 @@
|
||||
|
||||
- (void)didUpdateReactSubviews
|
||||
{
|
||||
// do nothing
|
||||
[self updateContainer];
|
||||
// we need to wait until children have their layout set. At this point they don't have the layout
|
||||
// set yet, however the layout call is already enqueued on ui thread. Enqueuing update call on the
|
||||
// ui queue will guarantee that the update will run after layout.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self updateContainer];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)didMoveToWindow
|
||||
{
|
||||
[super didMoveToWindow];
|
||||
if (self.window) {
|
||||
// when stack is added to a window we try to update push and modal view controllers. It is
|
||||
// because modal operations are blocked by UIKit when parent VC is not mounted, so we need
|
||||
// to redo them when the stack is attached.
|
||||
[self updateContainer];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setModalViewControllers:(NSArray<UIViewController *> *)controllers
|
||||
@@ -197,26 +214,57 @@
|
||||
}
|
||||
}
|
||||
|
||||
// prevent re-entry
|
||||
if (_updatingModals) {
|
||||
_scheduleModalsUpdate = YES;
|
||||
return;
|
||||
}
|
||||
_updatingModals = YES;
|
||||
|
||||
__weak RNSScreenStackView *weakSelf = self;
|
||||
|
||||
void (^dispatchFinishTransitioning)(void) = ^{
|
||||
void (^afterTransitions)(void) = ^{
|
||||
if (weakSelf.onFinishTransitioning) {
|
||||
weakSelf.onFinishTransitioning(nil);
|
||||
}
|
||||
weakSelf.updatingModals = NO;
|
||||
if (weakSelf.scheduleModalsUpdate) {
|
||||
// if modals update was requested during setModalViewControllers we set scheduleModalsUpdate
|
||||
// flag in order to perform updates at a later point. Here we are done with all modals
|
||||
// transitions and check this flag again. If it was set, we reset the flag and execute updates.
|
||||
weakSelf.scheduleModalsUpdate = NO;
|
||||
[weakSelf updateContainer];
|
||||
}
|
||||
};
|
||||
|
||||
void (^finish)(void) = ^{
|
||||
UIViewController *previous = changeRootController;
|
||||
for (NSUInteger i = changeRootIndex; i < controllers.count; i++) {
|
||||
UIViewController *next = controllers[i];
|
||||
BOOL animate = (i == controllers.count - 1);
|
||||
[previous presentViewController:next
|
||||
animated:animate
|
||||
completion:animate ? dispatchFinishTransitioning : nil];
|
||||
previous = next;
|
||||
NSUInteger oldCount = weakSelf.presentedModals.count;
|
||||
if (changeRootIndex < oldCount) {
|
||||
[weakSelf.presentedModals
|
||||
removeObjectsInRange:NSMakeRange(changeRootIndex, oldCount - changeRootIndex)];
|
||||
}
|
||||
if (changeRootIndex >= controllers.count) {
|
||||
dispatchFinishTransitioning();
|
||||
if (changeRootController.view.window == nil || changeRootIndex >= controllers.count) {
|
||||
// if change controller view is not attached, presenting modals will silently fail on iOS.
|
||||
// In such a case we trigger controllers update from didMoveToWindow.
|
||||
// We also don't run any present transitions if changeRootIndex is greater or equal to the size
|
||||
// of new controllers array. This means that no new controllers should be presented.
|
||||
afterTransitions();
|
||||
return;
|
||||
} else {
|
||||
UIViewController *previous = changeRootController;
|
||||
for (NSUInteger i = changeRootIndex; i < controllers.count; i++) {
|
||||
UIViewController *next = controllers[i];
|
||||
BOOL lastModal = (i == controllers.count - 1);
|
||||
[previous presentViewController:next
|
||||
animated:lastModal
|
||||
completion:^{
|
||||
[weakSelf.presentedModals addObject:next];
|
||||
if (lastModal) {
|
||||
afterTransitions();
|
||||
};
|
||||
}];
|
||||
previous = next;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -227,7 +275,6 @@
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
[_presentedModals setArray:controllers];
|
||||
}
|
||||
|
||||
- (void)setPushViewControllers:(NSArray<UIViewController *> *)controllers
|
||||
@@ -237,6 +284,12 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// if view controller is not yet attached to window we skip updates now and run them when view
|
||||
// is attached
|
||||
if (self.window == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
UIViewController *top = controllers.lastObject;
|
||||
UIViewController *lastTop = _controller.viewControllers.lastObject;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native-screens",
|
||||
"version": "2.0.0-beta.6",
|
||||
"version": "2.0.0-beta.8",
|
||||
"description": "First incomplete navigation solution for your react-native app.",
|
||||
"scripts": {
|
||||
"start": "node node_modules/react-native/local-cli/cli.js start",
|
||||
|
||||
2
src/screens.d.ts
vendored
2
src/screens.d.ts
vendored
@@ -15,7 +15,7 @@ declare module 'react-native-screens' {
|
||||
export function enableScreens(shouldEnableScreens?: boolean): void;
|
||||
export function screensEnabled(): boolean;
|
||||
|
||||
export type StackPresentationTypes = 'push' | 'modal' | 'transparentModal';
|
||||
export type StackPresentationTypes = 'push' | 'modal' | 'transparentModal' | 'fullScreenModal' | 'formSheet';
|
||||
export type StackAnimationTypes = 'default' | 'fade' | 'flip' | 'none';
|
||||
|
||||
export interface ScreenProps extends ViewProps {
|
||||
|
||||
Reference in New Issue
Block a user