Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Implemented slide views from left and right.

  • Loading branch information...
commit 9d005c6e3e8946b75219a0be893a66d2e80c6377 1 parent 89ec4c8
tomaz authored
105 Example3/LionTableViewTesting/LionAutoLayoutTestingAppDelegate.m
@@ -11,8 +11,14 @@
11 11 #import "ViewController2.h"
12 12 #import "LionAutoLayoutTestingAppDelegate.h"
13 13
  14 +typedef void(^GBPlaceholderReplaceBlock)(NSView *placeholder, NSView *currentView, NSView *newView);
  15 +
14 16 @interface LionAutoLayoutTestingAppDelegate ()
  17 +- (NSArray *)layoutConstraintsForView:(NSView *)view offsetBy:(NSPoint)offset;
  18 +- (void)slideViewControllerFromLeft:(NSViewController *)controller;
  19 +- (void)slideViewControllerFromRight:(NSViewController *)controller;
15 20 - (void)replacePlaceholderViewWith:(NSViewController *)controller;
  21 +- (void)replacePlaceholderViewWith:(NSViewController *)controller block:(GBPlaceholderReplaceBlock)handler;
16 22 @property (nonatomic, strong) NSViewController *currentViewController;
17 23 @property (nonatomic, strong) ViewController1 *viewController1;
18 24 @property (nonatomic, strong) ViewController2 *viewController2;
@@ -37,31 +43,104 @@ - (void)applicationDidFinishLaunching:(NSNotification *)note {
37 43 #pragma mark - User actions
38 44
39 45 - (IBAction)changeToViewController1:(id)sender {
40   - [self replacePlaceholderViewWith:self.viewController1];
  46 + [self slideViewControllerFromLeft:self.viewController1];
41 47 }
42 48
43 49 - (IBAction)changeToViewController2:(id)sender {
44   - [self replacePlaceholderViewWith:self.viewController2];
  50 + [self slideViewControllerFromRight:self.viewController2];
  51 +}
  52 +
  53 +#pragma mark - Subviews handling
  54 +
  55 +- (NSArray *)layoutConstraintsForView:(NSView *)view offsetBy:(NSPoint)offset {
  56 + // We always return constraints in order: left, width, top, height.
  57 + NSMutableArray *result = [NSMutableArray arrayWithCapacity:4];
  58 + NSView *placeholder = self.placeholderView;
  59 + [result addObject:[NSLayoutConstraint constraintWithItem:view
  60 + attribute:NSLayoutAttributeLeft
  61 + relatedBy:NSLayoutRelationEqual
  62 + toItem:placeholder
  63 + attribute:NSLayoutAttributeLeft
  64 + multiplier:1.0 constant:offset.x]];
  65 + [result addObject:[NSLayoutConstraint constraintWithItem:view
  66 + attribute:NSLayoutAttributeWidth
  67 + relatedBy:NSLayoutRelationEqual
  68 + toItem:placeholder
  69 + attribute:NSLayoutAttributeWidth
  70 + multiplier:1.0 constant:0.0]];
  71 + [result addObject:[NSLayoutConstraint constraintWithItem:view
  72 + attribute:NSLayoutAttributeTop
  73 + relatedBy:NSLayoutRelationEqual
  74 + toItem:placeholder
  75 + attribute:NSLayoutAttributeTop
  76 + multiplier:1.0 constant:offset.y]];
  77 + [result addObject:[NSLayoutConstraint constraintWithItem:view
  78 + attribute:NSLayoutAttributeHeight
  79 + relatedBy:NSLayoutRelationEqual
  80 + toItem:placeholder
  81 + attribute:NSLayoutAttributeHeight
  82 + multiplier:1.0 constant:0.0]];
  83 +
  84 + // Finally prepare a new animation for the transition; we need it so that we can intercept animationDidStop:finished: and remove old view.
  85 + CABasicAnimation *animation = [CABasicAnimation animation];
  86 + animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
  87 + animation.delegate = self;
  88 + [[result objectAtIndex:0] setAnimations:[NSDictionary dictionaryWithObject:animation forKey:@"constant"]];
  89 + return result;
  90 +}
  91 +
  92 +- (void)slideViewControllerFromLeft:(NSViewController *)controller {
  93 + [self replacePlaceholderViewWith:controller block:^(NSView *placeholder, NSView *currentView, NSView *newView) {
  94 + CGFloat width = placeholder.bounds.size.width;
  95 + NSArray *constraints = [self layoutConstraintsForView:newView offsetBy:NSMakePoint(-width, 0.0)];
  96 + [newView setTranslatesAutoresizingMaskIntoConstraints:NO];
  97 + [placeholder addSubview:newView];
  98 + [placeholder addConstraints:constraints];
  99 + [[[placeholder.constraints objectAtIndex:0] animator] setConstant:width];
  100 + [[[constraints objectAtIndex:0] animator] setConstant:0.0];
  101 + }];
45 102 }
46 103
47   -#pragma mark - Helpers
  104 +- (void)slideViewControllerFromRight:(NSViewController *)controller {
  105 + [self replacePlaceholderViewWith:controller block:^(NSView *placeholder, NSView *currentView, NSView *newView) {
  106 + CGFloat width = placeholder.bounds.size.width;
  107 + NSArray *constraints = [self layoutConstraintsForView:newView offsetBy:NSMakePoint(width, 0.0)];
  108 + [newView setTranslatesAutoresizingMaskIntoConstraints:NO];
  109 + [placeholder addSubview:newView];
  110 + [placeholder addConstraints:constraints];
  111 + [[[placeholder.constraints objectAtIndex:0] animator] setConstant:-width];
  112 + [[[constraints objectAtIndex:0] animator] setConstant:0.0];
  113 + }];
  114 +}
48 115
49 116 - (void)replacePlaceholderViewWith:(NSViewController *)controller {
  117 + [self replacePlaceholderViewWith:controller block:^(NSView *placeholder, NSView *currentView, NSView *newView) {
  118 + if (currentView) {
  119 + [currentView removeFromSuperview];
  120 + }
  121 + if (newView) {
  122 + NSDictionary *views = NSDictionaryOfVariableBindings(newView);
  123 + [newView setTranslatesAutoresizingMaskIntoConstraints:NO];
  124 + [placeholder addSubview:newView];
  125 + [placeholder addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[newView]|" options:0 metrics:nil views:views]];
  126 + [placeholder addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[newView]|" options:0 metrics:nil views:views]];
  127 + }
  128 + }];
  129 +}
  130 +
  131 +- (void)replacePlaceholderViewWith:(NSViewController *)controller block:(GBPlaceholderReplaceBlock)handler {
50 132 if (controller == self.currentViewController) return;
51 133 self.currentViewController = controller;
52 134 NSView *placeholderView = self.placeholderView;
53 135 NSView *currentView = self.placeholderView.subviews.lastObject;
54 136 NSView *newView = self.currentViewController.view;
55   - if (currentView) {
56   - [currentView removeFromSuperview];
57   - }
58   - if (newView) {
59   - NSDictionary *views = NSDictionaryOfVariableBindings(newView);
60   - [newView setTranslatesAutoresizingMaskIntoConstraints:NO];
61   - [placeholderView addSubview:newView];
62   - [placeholderView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[newView]|" options:0 metrics:nil views:views]];
63   - [placeholderView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[newView]|" options:0 metrics:nil views:views]];
64   - }
  137 + handler(placeholderView, currentView, newView);
  138 +}
  139 +
  140 +- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
  141 + // 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...
  142 + if (!flag || self.placeholderView.subviews.count < 2) return;
  143 + [[self.placeholderView.subviews objectAtIndex:0] removeFromSuperview];
65 144 }
66 145
67 146 #pragma mark - Properties

0 comments on commit 9d005c6

Please sign in to comment.
Something went wrong with that request. Please try again.