Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Implemented slide views from left and right.

  • Loading branch information...
commit 9d005c6e3e8946b75219a0be893a66d2e80c6377 1 parent 89ec4c8
@tomaz authored
Showing with 92 additions and 13 deletions.
  1. +92 −13 Example3/LionTableViewTesting/LionAutoLayoutTestingAppDelegate.m
View
105 Example3/LionTableViewTesting/LionAutoLayoutTestingAppDelegate.m
@@ -11,8 +11,14 @@
#import "ViewController2.h"
#import "LionAutoLayoutTestingAppDelegate.h"
+typedef void(^GBPlaceholderReplaceBlock)(NSView *placeholder, NSView *currentView, NSView *newView);
+
@interface LionAutoLayoutTestingAppDelegate ()
+- (NSArray *)layoutConstraintsForView:(NSView *)view offsetBy:(NSPoint)offset;
+- (void)slideViewControllerFromLeft:(NSViewController *)controller;
+- (void)slideViewControllerFromRight:(NSViewController *)controller;
- (void)replacePlaceholderViewWith:(NSViewController *)controller;
+- (void)replacePlaceholderViewWith:(NSViewController *)controller block:(GBPlaceholderReplaceBlock)handler;
@property (nonatomic, strong) NSViewController *currentViewController;
@property (nonatomic, strong) ViewController1 *viewController1;
@property (nonatomic, strong) ViewController2 *viewController2;
@@ -37,31 +43,104 @@ - (void)applicationDidFinishLaunching:(NSNotification *)note {
#pragma mark - User actions
- (IBAction)changeToViewController1:(id)sender {
- [self replacePlaceholderViewWith:self.viewController1];
+ [self slideViewControllerFromLeft:self.viewController1];
}
- (IBAction)changeToViewController2:(id)sender {
- [self replacePlaceholderViewWith:self.viewController2];
+ [self slideViewControllerFromRight:self.viewController2];
+}
+
+#pragma mark - Subviews handling
+
+- (NSArray *)layoutConstraintsForView:(NSView *)view offsetBy:(NSPoint)offset {
+ // We always return constraints in order: left, width, top, height.
+ NSMutableArray *result = [NSMutableArray arrayWithCapacity:4];
+ NSView *placeholder = self.placeholderView;
+ [result addObject:[NSLayoutConstraint constraintWithItem:view
+ attribute:NSLayoutAttributeLeft
+ relatedBy:NSLayoutRelationEqual
+ toItem:placeholder
+ attribute:NSLayoutAttributeLeft
+ multiplier:1.0 constant:offset.x]];
+ [result addObject:[NSLayoutConstraint constraintWithItem:view
+ attribute:NSLayoutAttributeWidth
+ relatedBy:NSLayoutRelationEqual
+ toItem:placeholder
+ attribute:NSLayoutAttributeWidth
+ multiplier:1.0 constant:0.0]];
+ [result addObject:[NSLayoutConstraint constraintWithItem:view
+ attribute:NSLayoutAttributeTop
+ relatedBy:NSLayoutRelationEqual
+ toItem:placeholder
+ attribute:NSLayoutAttributeTop
+ multiplier:1.0 constant:offset.y]];
+ [result addObject:[NSLayoutConstraint constraintWithItem:view
+ attribute:NSLayoutAttributeHeight
+ relatedBy:NSLayoutRelationEqual
+ toItem:placeholder
+ attribute:NSLayoutAttributeHeight
+ multiplier:1.0 constant:0.0]];
+
+ // Finally prepare a new animation for the transition; we need it so that we can intercept animationDidStop:finished: and remove old view.
+ CABasicAnimation *animation = [CABasicAnimation animation];
+ animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+ animation.delegate = self;
+ [[result objectAtIndex:0] setAnimations:[NSDictionary dictionaryWithObject:animation forKey:@"constant"]];
+ return result;
+}
+
+- (void)slideViewControllerFromLeft:(NSViewController *)controller {
+ [self replacePlaceholderViewWith:controller block:^(NSView *placeholder, NSView *currentView, NSView *newView) {
+ CGFloat width = placeholder.bounds.size.width;
+ NSArray *constraints = [self layoutConstraintsForView:newView offsetBy:NSMakePoint(-width, 0.0)];
+ [newView setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [placeholder addSubview:newView];
+ [placeholder addConstraints:constraints];
+ [[[placeholder.constraints objectAtIndex:0] animator] setConstant:width];
+ [[[constraints objectAtIndex:0] animator] setConstant:0.0];
+ }];
}
-#pragma mark - Helpers
+- (void)slideViewControllerFromRight:(NSViewController *)controller {
+ [self replacePlaceholderViewWith:controller block:^(NSView *placeholder, NSView *currentView, NSView *newView) {
+ CGFloat width = placeholder.bounds.size.width;
+ NSArray *constraints = [self layoutConstraintsForView:newView offsetBy:NSMakePoint(width, 0.0)];
+ [newView setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [placeholder addSubview:newView];
+ [placeholder addConstraints:constraints];
+ [[[placeholder.constraints objectAtIndex:0] animator] setConstant:-width];
+ [[[constraints objectAtIndex:0] animator] setConstant:0.0];
+ }];
+}
- (void)replacePlaceholderViewWith:(NSViewController *)controller {
+ [self replacePlaceholderViewWith:controller block:^(NSView *placeholder, NSView *currentView, NSView *newView) {
+ if (currentView) {
+ [currentView removeFromSuperview];
+ }
+ if (newView) {
+ NSDictionary *views = NSDictionaryOfVariableBindings(newView);
+ [newView setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [placeholder addSubview:newView];
+ [placeholder addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[newView]|" options:0 metrics:nil views:views]];
+ [placeholder addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[newView]|" options:0 metrics:nil views:views]];
+ }
+ }];
+}
+
+- (void)replacePlaceholderViewWith:(NSViewController *)controller block:(GBPlaceholderReplaceBlock)handler {
if (controller == self.currentViewController) return;
self.currentViewController = controller;
NSView *placeholderView = self.placeholderView;
NSView *currentView = self.placeholderView.subviews.lastObject;
NSView *newView = self.currentViewController.view;
- if (currentView) {
- [currentView removeFromSuperview];
- }
- if (newView) {
- NSDictionary *views = NSDictionaryOfVariableBindings(newView);
- [newView setTranslatesAutoresizingMaskIntoConstraints:NO];
- [placeholderView addSubview:newView];
- [placeholderView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[newView]|" options:0 metrics:nil views:views]];
- [placeholderView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[newView]|" options:0 metrics:nil views:views]];
- }
+ handler(placeholderView, currentView, newView);
+}
+
+- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
+ // Once animation is finished, we should remove previous view. Note that the delegate is called two times as we have two animations running for both views. Hence we need to take care to only remove original view! We simply remove first view in hierarchy as we always append new one after it - kind of a hack, but works...
+ if (!flag || self.placeholderView.subviews.count < 2) return;
+ [[self.placeholderView.subviews objectAtIndex:0] removeFromSuperview];
}
#pragma mark - Properties
Please sign in to comment.
Something went wrong with that request. Please try again.