Compare commits

...

5 Commits

Author SHA1 Message Date
Krzysztof Magiera
1958cf37ea Bump version -> 2.0.0-alpha.17 2019-12-04 14:44:09 +01:00
Krzysztof Magiera
75fb558cd3 Fix modal controllers update algorithm. (#245)
The previous algorithm was buggy and did not handle the case when multiple VCs are being dismissed. Unfortunately I couldn't find a reliable way that'd allow for reshuffling modally presented VCs (inserting or deleting VCs not from the top) and so I added a special check that'd throw in the case someone attemted to do this.
2019-12-04 14:41:52 +01:00
Krzysztof Magiera
2b55d60780 Bump version -> 2.0.0-alpha.16 2019-12-02 16:01:49 +01:00
Krzysztof Magiera
744b37fbc3 Fix Android's toolbar config update (#244)
Before this change, updates made to toolbar's subviwews weren't properly reflected. We'd only add new views to toolbar w/o removing stale ones.
2019-12-02 10:47:17 +01:00
Krzysztof Magiera
84d684b52d Support RNN wrapper's animationEnabled option (#243) 2019-12-02 10:45:40 +01:00
5 changed files with 68 additions and 41 deletions

View File

@@ -17,10 +17,11 @@ import androidx.fragment.app.Fragment;
import com.facebook.react.views.text.ReactFontManager;
import java.util.ArrayList;
public class ScreenStackHeaderConfig extends ViewGroup {
private final ScreenStackHeaderSubview mConfigSubviews[] = new ScreenStackHeaderSubview[3];
private int mSubviewsCount = 0;
private final ArrayList<ScreenStackHeaderSubview> mConfigSubviews = new ArrayList<>(3);
private String mTitle;
private int mTitleColor;
private String mTitleFontFamily;
@@ -174,8 +175,13 @@ public class ScreenStackHeaderConfig extends ViewGroup {
}
// subviews
for (int i = 0; i < mSubviewsCount; i++) {
ScreenStackHeaderSubview view = mConfigSubviews[i];
for (int i = mToolbar.getChildCount() - 1; i >= 0; i--) {
if (mToolbar.getChildAt(i) instanceof ScreenStackHeaderSubview) {
mToolbar.removeViewAt(i);
}
}
for (int i = 0, size = mConfigSubviews.size(); i < size; i++) {
ScreenStackHeaderSubview view = mConfigSubviews.get(i);
ScreenStackHeaderSubview.Type type = view.getType();
Toolbar.LayoutParams params =
@@ -201,9 +207,7 @@ public class ScreenStackHeaderConfig extends ViewGroup {
}
view.setLayoutParams(params);
if (view.getParent() == null) {
mToolbar.addView(view);
}
mToolbar.addView(view);
}
}
@@ -214,26 +218,20 @@ public class ScreenStackHeaderConfig extends ViewGroup {
}
public ScreenStackHeaderSubview getConfigSubview(int index) {
return mConfigSubviews[index];
return mConfigSubviews.get(index);
}
public int getConfigSubviewsCount() {
return mSubviewsCount;
return mConfigSubviews.size();
}
public void removeConfigSubview(int index) {
if (mConfigSubviews[index] != null) {
mSubviewsCount--;
}
mConfigSubviews[index] = null;
mConfigSubviews.remove(index);
maybeUpdate();
}
public void addConfigSubview(ScreenStackHeaderSubview child, int index) {
if (mConfigSubviews[index] == null) {
mSubviewsCount++;
}
mConfigSubviews[index] = child;
mConfigSubviews.add(index, child);
maybeUpdate();
}

View File

@@ -165,11 +165,17 @@ class StackView extends React.Component {
transparentCard || options.cardTransparent ? 'transparentModal' : mode;
}
let stackAnimation = undefined;
if (options.animationEnabled === false) {
stackAnimation = 'none';
}
const { screenProps } = this.props;
return (
<Screen
key={`screen_${route.key}`}
style={options.cardStyle}
stackAnimation={stackAnimation}
stackPresentation={stackPresentation}
onDismissed={() => this._removeScene(route)}>
{this._renderHeaderConfig(index, route, descriptor)}

View File

@@ -2,7 +2,7 @@
#import <React/RCTUIManagerObserverCoordinator.h>
#import "RNSScreenContainer.h"
@interface RNSScreenStackView : UIView <RNSScreenContainerDelegate>
@interface RNSScreenStackView : UIView <RNSScreenContainerDelegate, RCTInvalidating>
- (void)markChildUpdated;
- (void)didUpdateChildren;

View File

@@ -143,31 +143,48 @@
NSMutableArray<UIViewController *> *controllersToRemove = [NSMutableArray arrayWithArray:_presentedModals];
[controllersToRemove removeObjectsInArray:controllers];
// presenting new controllers
for (UIViewController *newController in newControllers) {
[_presentedModals addObject:newController];
if (_controller.presentedViewController != nil) {
[_controller.presentedViewController presentViewController:newController animated:YES completion:nil];
// find bottom-most controller that should stay on the stack for the duration of transition
NSUInteger changeRootIndex = 0;
UIViewController *changeRootController = _controller;
for (NSUInteger i = 0; i < MIN(_presentedModals.count, controllers.count); i++) {
if (_presentedModals[i] == controllers[i]) {
changeRootController = controllers[i];
changeRootIndex = i + 1;
} else {
[_controller presentViewController:newController animated:YES completion:nil];
break;
}
}
// hiding old controllers
for (UIViewController *controller in [controllersToRemove reverseObjectEnumerator]) {
[_presentedModals removeObject:controller];
if (controller.presentedViewController != nil) {
UIViewController *restore = controller.presentedViewController;
UIViewController *parent = controller.presentingViewController;
[controller dismissViewControllerAnimated:NO completion:^{
[parent dismissViewControllerAnimated:NO completion:^{
[parent presentViewController:restore animated:NO completion:nil];
}];
}];
} else {
[controller.presentingViewController dismissViewControllerAnimated:YES completion:nil];
// we verify that controllers added on top of changeRootIndex are all new. Unfortunately modal
// VCs cannot be reshuffled (there are some visual glitches when we try to dismiss then show as
// even non-animated dismissal has delay and updates the screen several times)
for (NSUInteger i = changeRootIndex; i < controllers.count; i++) {
if ([_presentedModals containsObject:controllers[i]]) {
RCTAssert(false, @"Modally presented controllers are being reshuffled, this is not allowed");
}
}
void (^finish)(void) = ^{
UIViewController *previous = changeRootController;
for (NSUInteger i = changeRootIndex; i < controllers.count; i++) {
UIViewController *next = controllers[i];
[previous presentViewController:next
animated:(i == controllers.count - 1)
completion:nil];
previous = next;
}
[self->_presentedModals removeAllObjects];
[self->_presentedModals addObjectsFromArray:controllers];
};
if (changeRootController.presentedViewController) {
[changeRootController
dismissViewControllerAnimated:(changeRootIndex == controllers.count)
completion:finish];
} else {
finish();
}
}
- (void)setPushViewControllers:(NSArray<UIViewController *> *)controllers
@@ -244,12 +261,18 @@
_controller.view.frame = self.bounds;
}
- (void)invalidate
{
for (UIViewController *controller in _presentedModals) {
[controller dismissViewControllerAnimated:NO completion:nil];
}
[_presentedModals removeAllObjects];
}
- (void)dismissOnReload
{
dispatch_async(dispatch_get_main_queue(), ^{
for (UIViewController *controller in self->_presentedModals) {
[controller dismissViewControllerAnimated:NO completion:nil];
}
[self invalidate];
});
}

View File

@@ -1,6 +1,6 @@
{
"name": "react-native-screens",
"version": "2.0.0-alpha.15",
"version": "2.0.0-alpha.17",
"description": "First incomplete navigation solution for your react-native app.",
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",