Get rid of stackcontainer (for now)

This commit is contained in:
Krzysztof Magiera
2018-09-07 18:04:08 +02:00
parent d940a02fac
commit 8e13c58b6e
9 changed files with 5 additions and 338 deletions

View File

@@ -9,12 +9,12 @@ import {
import { createStackNavigator, createSwitchNavigator } from 'react-navigation'; import { createStackNavigator, createSwitchNavigator } from 'react-navigation';
import Stack from './stack'; import Stack from './stack';
import Container from './container'; import Tabs from './tabs';
import Navigation from './navigation'; import Navigation from './navigation';
const SCREENS = { const SCREENS = {
Stack: { screen: Stack, title: 'ScreenStack example' }, Stack: { screen: Stack, title: 'Stack example' },
Container: { screen: Container, title: 'ScreenContainer example' }, Tabs: { screen: Tabs, title: 'Tabs example' },
Navigation: { screen: Navigation, title: 'React Navigation example' }, Navigation: { screen: Navigation, title: 'React Navigation example' },
}; };

View File

@@ -7,7 +7,7 @@ import {
Animated, Animated,
Easing, Easing,
} from 'react-native'; } from 'react-native';
import { Screen, ScreenStack } from 'react-native-screens'; import { Screen, ScreenContainer } from 'react-native-screens';
const COLORS = ['azure', 'pink', 'cyan']; const COLORS = ['azure', 'pink', 'cyan'];
@@ -110,16 +110,8 @@ export class Stack extends Component {
render() { render() {
const screens = this.state.stack.map(this.renderScreen); const screens = this.state.stack.map(this.renderScreen);
return ( return (
<ScreenStack <ScreenContainer style={styles.container}>{screens}</ScreenContainer>
transitioning={this.state.transitioning}
progress={this.state.progress}
style={styles.container}>
{screens}
</ScreenStack>
); );
// return (
// <ScreenContainer style={styles.container}>{screens}</ScreenContainer>
// );
} }
} }

View File

@@ -19,7 +19,6 @@ public class RNScreenPackage implements ReactPackage {
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Arrays.<ViewManager>asList( return Arrays.<ViewManager>asList(
new ScreenContainerViewManager(), new ScreenContainerViewManager(),
new ScreenStackViewManager(),
new ScreenViewManager() new ScreenViewManager()
); );
} }

View File

@@ -1,35 +0,0 @@
package com.swmansion.rnscreens;
import android.content.Context;
import java.util.List;
public class ScreenStack extends ScreenContainer {
private float mTransitioning;
public ScreenStack(Context context) {
super(context);
}
public void setTransitioning(float transitioning) {
if (transitioning != mTransitioning) {
mTransitioning = transitioning;
markUpdated();
}
}
@Override
protected boolean isScreenActive(Screen screen, List<Screen> allScreens) {
int size = allScreens.size();
if (size < 1) {
return false;
}
Screen lastScreen = allScreens.get(size - 1);
if (mTransitioning != 0 && size > 1) {
Screen secondToLast = allScreens.get(size - 2);
return screen == lastScreen || screen == secondToLast;
}
return screen == lastScreen;
}
}

View File

@@ -1,24 +0,0 @@
package com.swmansion.rnscreens;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.annotations.ReactProp;
public class ScreenStackViewManager extends ScreenContainerViewManager {
protected static final String REACT_CLASS = "RNSScreenStack";
@Override
public String getName() {
return REACT_CLASS;
}
@Override
protected ScreenContainer createViewInstance(ThemedReactContext reactContext) {
return new ScreenStack(reactContext);
}
@ReactProp(name = "transitioning", defaultFloat = 0)
public void setTransitioning(ScreenStack view, float transitioning) {
view.setTransitioning(transitioning);
}
}

View File

@@ -1,14 +0,0 @@
#import <React/RCTViewManager.h>
#import <React/RCTUIManagerObserverCoordinator.h>
#import "RNSScreenContainer.h"
@interface RNSScreenStackView : UIView <RNSScreenContainerDelegate>
- (void)markChildUpdated;
- (void)didUpdateChildren;
@end
@interface RNSScreenStackManager : RCTViewManager
@end

View File

@@ -1,245 +0,0 @@
#import "RNSScreenStack.h"
#import "RNSScreen.h"
#import <React/RCTBridge.h>
#import <React/RCTUIManager.h>
#import <React/RCTUIManagerUtils.h>
@interface RNSCustomAnimator : NSObject <UIViewControllerAnimatedTransitioning>
@property (nonatomic) BOOL presenting;
@end
@implementation RNSCustomAnimator
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
UIView *container = transitionContext.containerView;
if (_presenting) {
[container addSubview:toView];
toView.alpha = 0.99;
} else {
[container insertSubview:toView belowSubview:fromView];
}
// When view is added to UINavController it flattens view's translation into frame and makes it
// so that the view with translation applied is centered. We often don't want that as we want the
// view to animated from side. In order to achieve this we reset the translation applied to the
// view such that the frame is at point 0,0 and translation adds an offset from that position.
CATransform3D origTransform = toView.layer.transform;
toView.transform = CGAffineTransformIdentity;
toView.frame = CGRectMake(0, 0, toView.frame.size.width, toView.frame.size.height);
toView.layer.transform = origTransform;
[UIView
animateWithDuration:[self transitionDuration:transitionContext]
animations:^{
// We need to animate at least one property, otherwise the interactive animation wouldn't
// behave as expected. I haven't had enough time to investigate and hence as a workaround
// we are animating alpha from 1 to 0.99
if (_presenting) {
toView.alpha = 1.0;
} else {
fromView.alpha = 0.99;
}
} completion:^(BOOL finished) {
BOOL success = !transitionContext.transitionWasCancelled;
if (!success) {
[toView removeFromSuperview];
}
[transitionContext completeTransition:success];
}];
}
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
// as long as it is non-zero it does not matter what value is here, we turn animation into
// "interactive" mode anyways which make it be controlled by "progress" property anyways.
return 0.1;
}
@end
@interface RNSScreenStackView () <UINavigationControllerDelegate>
@property (nonatomic) NSInteger transitioning;
@property (nonatomic) CGFloat progress;
@end
@implementation RNSScreenStackView {
BOOL _needUpdate;
BOOL _transitioningStateChanged;
UINavigationController *_controller;
NSMutableSet<RNSScreenView *> *_activeScreens;
NSMutableArray<RNSScreenView *> *_reactSubviews;
UIPercentDrivenInteractiveTransition *_interactor;
__weak RNSScreenStackManager *_manager;
}
- (instancetype)initWithManager:(RNSScreenStackManager*)manager
{
if (self = [super init]) {
_manager = manager;
_reactSubviews = [NSMutableArray new];
_controller = [[UINavigationController alloc] init];
_controller.navigationBarHidden = YES;
_controller.delegate = self;
_needUpdate = NO;
[self addSubview:_controller.view];
}
return self;
}
- (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController
interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController
{
return _interactor;
}
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC
{
RNSCustomAnimator *animator = [RNSCustomAnimator new];
animator.presenting = _transitioning > 0;
return animator;
}
- (void)markUpdated
{
// We want 'updateContainer' to be executed on main thread after all enqueued operations in
// uimanager are complete. In order to achieve that we enqueue call on UIManagerQueue from which
// we enqueue call on the main queue. This seems to be working ok in all the cases I've tried but
// there is a chance it is not the correct way to do that.
if (!_needUpdate) {
_needUpdate = YES;
RCTExecuteOnUIManagerQueue(^{
RCTExecuteOnMainQueue(^{
_needUpdate = NO;
[self updateContainer];
});
});
}
}
- (void)markChildUpdated
{
// do nothing
}
- (void)didUpdateChildren
{
// do nothing
}
- (void)setProgress:(CGFloat)progress
{
_progress = progress;
[_interactor updateInteractiveTransition:progress];
}
- (void)setTransitioning:(NSInteger)transitioning
{
if (_transitioning == transitioning) {
return;
}
_transitioningStateChanged = YES;
_transitioning = transitioning;
[self markUpdated];
}
- (void)insertReactSubview:(RNSScreenView *)subview atIndex:(NSInteger)atIndex
{
subview.hidden = NO;
subview.reactSuperview = self;
[_reactSubviews insertObject:subview atIndex:atIndex];
[self markUpdated];
}
- (void)removeReactSubview:(RNSScreenView *)subview
{
// Right after the view gets removed properties such as transform will get reset. In addition to
// that UINavigationController takes a snapshot of the view before it gets completely unmounted.
// This causes an effect in which even so the view are detached from the hierarchy they could still
// be visible for a frame. This is often undesirable e.g. in a case when we want to slide view
// outside of the visible bounds, because as a result it will jump back to position 0,0 right before
// the transition is over. To prevent that we hide the view right before removing it from the subviews
// array.
subview.hidden = YES;
subview.reactSuperview = nil;
[_reactSubviews removeObject:subview];
[self markUpdated];
}
- (NSArray<UIView *> *)reactSubviews
{
return _reactSubviews;
}
- (void)didUpdateReactSubviews
{
// do nothing
}
- (void)updateContainer
{
NSMutableArray<UIViewController *> *controllers = [NSMutableArray new];
for (RNSScreenView *screen in _reactSubviews) {
[controllers addObject:screen.controller];
}
if (_transitioningStateChanged) {
if (_transitioning == 0) {
// finish or cancel transitioning
if ([_controller.viewControllers indexOfObject:controllers.lastObject] != NSNotFound) {
[_interactor finishInteractiveTransition];
} else {
[_interactor cancelInteractiveTransition];
}
_interactor = nil;
} else {
_interactor = [UIPercentDrivenInteractiveTransition new];
if (_transitioning < 0) {
[_controller setViewControllers:controllers animated:NO];
[_controller popViewControllerAnimated:YES];
} else {
UIViewController *lastController = [controllers lastObject];
[controllers removeLastObject];
[_controller setViewControllers:controllers animated:NO];
[_controller pushViewController:lastController animated:YES];
}
}
_transitioningStateChanged = NO;
} else {
[_controller setViewControllers:controllers animated:NO];
}
}
- (void)layoutSubviews
{
[super layoutSubviews];
[self reactAddControllerToClosestParent:_controller];
_controller.view.frame = self.bounds;
}
@end
@implementation RNSScreenStackManager
RCT_EXPORT_MODULE()
RCT_EXPORT_VIEW_PROPERTY(transitioning, NSInteger)
RCT_EXPORT_VIEW_PROPERTY(progress, CGFloat)
- (UIView *)view
{
return [[RNSScreenStackView alloc] initWithManager:self];
}
@end

View File

@@ -8,7 +8,6 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
448078F52114595900280661 /* RNSScreenContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 448078F12114595900280661 /* RNSScreenContainer.m */; }; 448078F52114595900280661 /* RNSScreenContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 448078F12114595900280661 /* RNSScreenContainer.m */; };
448078F62114595900280661 /* RNSScreenStack.m in Sources */ = {isa = PBXBuildFile; fileRef = 448078F32114595900280661 /* RNSScreenStack.m */; };
448078F72114595900280661 /* RNSScreen.m in Sources */ = {isa = PBXBuildFile; fileRef = 448078F42114595900280661 /* RNSScreen.m */; }; 448078F72114595900280661 /* RNSScreen.m in Sources */ = {isa = PBXBuildFile; fileRef = 448078F42114595900280661 /* RNSScreen.m */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
@@ -29,8 +28,6 @@
448078EF2114595900280661 /* RNSScreen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSScreen.h; sourceTree = "<group>"; }; 448078EF2114595900280661 /* RNSScreen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSScreen.h; sourceTree = "<group>"; };
448078F02114595900280661 /* RNSScreenContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSScreenContainer.h; sourceTree = "<group>"; }; 448078F02114595900280661 /* RNSScreenContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSScreenContainer.h; sourceTree = "<group>"; };
448078F12114595900280661 /* RNSScreenContainer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNSScreenContainer.m; sourceTree = "<group>"; }; 448078F12114595900280661 /* RNSScreenContainer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNSScreenContainer.m; sourceTree = "<group>"; };
448078F22114595900280661 /* RNSScreenStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSScreenStack.h; sourceTree = "<group>"; };
448078F32114595900280661 /* RNSScreenStack.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNSScreenStack.m; sourceTree = "<group>"; };
448078F42114595900280661 /* RNSScreen.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNSScreen.m; sourceTree = "<group>"; }; 448078F42114595900280661 /* RNSScreen.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNSScreen.m; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
@@ -60,8 +57,6 @@
448078F42114595900280661 /* RNSScreen.m */, 448078F42114595900280661 /* RNSScreen.m */,
448078F02114595900280661 /* RNSScreenContainer.h */, 448078F02114595900280661 /* RNSScreenContainer.h */,
448078F12114595900280661 /* RNSScreenContainer.m */, 448078F12114595900280661 /* RNSScreenContainer.m */,
448078F22114595900280661 /* RNSScreenStack.h */,
448078F32114595900280661 /* RNSScreenStack.m */,
134814211AA4EA7D00B7C361 /* Products */, 134814211AA4EA7D00B7C361 /* Products */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
@@ -123,7 +118,6 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
448078F72114595900280661 /* RNSScreen.m in Sources */, 448078F72114595900280661 /* RNSScreen.m in Sources */,
448078F62114595900280661 /* RNSScreenStack.m in Sources */,
448078F52114595900280661 /* RNSScreenContainer.m in Sources */, 448078F52114595900280661 /* RNSScreenContainer.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;