2014-10-30 4 views
6

Ich habe alles versucht, was ich denken kann, einschließlich aller Vorschläge, die ich hier auf SO und in anderen Mailinglisten gefunden habe, aber ich kann nicht herausfinden, wie man einen NSSplitView Bereich mit einer Animation bei aktiviertem Auto Layout programmatisch einstellt.Wie verkleinert man einen NSSsplitView-Bereich mit Animation bei Verwendung von Auto Layout?

Hier ist, was ich jetzt habe (geschrieben in Swift zum Spaß), aber es fällt auf vielfältige Weise nach unten:

@IBAction func toggleSourceList(sender: AnyObject?) { 
    let isOpen = !splitView.isSubviewCollapsed(sourceList.view.superview!) 
    let position = (isOpen ? 0 : self.lastWidth) 

    if isOpen { 
     self.lastWidth = sourceList.view.frame.size.width 
    } 

    NSAnimationContext.runAnimationGroup({ context in 
     context.allowsImplicitAnimation = true 
     context.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn) 
     context.duration = self.duration 

     self.splitView.setPosition(position, ofDividerAtIndex: 0) 
    }, completionHandler: {() -> Void in 
    }) 
} 

Das gewünschte Verhalten und Aussehen, das von Mail.app ist, das ist wirklich schön animiert.

Ich habe eine vollständige Beispiel-App verfügbar unter https://github.com/mdiep/NSSplitViewTest.

+0

Versuchen Sie '-setPosition: ofDividerAtIndex:' an den 'animator'-Proxy der Split-Ansicht zu senden. –

+0

@KenThomases Ich habe das versucht. Kein Würfel. – mdiep

Antwort

0

Wenn Sie Auto-Layout verwenden und einige Aspekte der Dimensionen/Position der Ansicht animieren möchten, haben Sie möglicherweise mehr Glück, wenn Sie die Beschränkungen selbst animieren. Ich bin mit einer NSSplitView schnell gegangen, habe aber bisher nur begrenzten Erfolg gehabt. Ich kann nach einem Tastendruck eine Trennung erhalten, um zu expandieren und zu kollabieren, aber letztendlich musste ich versuchen, mich durch viele andere Probleme zu hacken, die durch die Störung verursacht wurden. Falls Ihr nicht kennt es, hier ist eine einfache Einschränkung Animation:

- (IBAction)animate:(NSButton *)sender { 
    /* Shrink view to invisible */ 

    NSLayoutConstraint *constraint = self.viewWidthConstraint; 
    [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) { 

     [[NSAnimationContext currentContext] setDuration:0.33]; 
     [[NSAnimationContext currentContext] setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]]; 
     [[constraint animator] setConstant:0]; 

    } completionHandler:^{ 
     /* Do Some clean-up, if required */ 

    }]; 

Denken Sie daran, animieren Sie können nur Einschränkungen constant ist, wird seine priority nicht animieren.

10

Objective-C:

[[splitViewItem animator] setCollapse:YES] 

Swift:

splitViewItem.animator().collapsed = true 

Von Apple Hilfe:

Unabhängig davon, ob das Kind Viewcontroller entsprechend der SplitViewItem ist Spalte ist im SplitViewController abgelaufen. Der Standardwert ist NO. Dies kann mit dem Animator-Proxy festgelegt werden, um die Kollabierung oder Uncollapse zu animieren. Die genaue verwendete Animation kann angepasst werden, indem sie im -animations Wörterbuch mit einem Schlüssel von "collapsed" gesetzt wird. Wenn auf YES gesetzt wird, bevor es zum SplitViewController hinzugefügt wird, ist es zunächst zusammengebrochen und der SplitViewController wird nicht die Ansicht geladen werden, bis es nicht verklemmt wird. Dies ist KVC/KVO-konform und wird aktualisiert, wenn sich der Wert von der Benutzerinteraktion ändert.

+1

Leider ist 'NSSplitViewItem' Teil einer neuen API am 10.10. Wenn ich das nutzen könnte, hätte ich die Frage nicht stellen müssen. :) – mdiep

+0

Überprüfen Sie die Bearbeitung. –

+3

Ich verstehe. NSSplitViewItem ist jedoch erst ab 10.10 verfügbar. – mdiep

0

Aus irgendeinem Grund funktionierte keine der Methoden zum Animieren von Frames für meine Scrollview. Ich habe nicht versucht, die Beschränkungen zu animieren.

Ich habe am Ende eine benutzerdefinierte Animation erstellt, um die Teilerposition zu animieren. Wenn jemand interessiert ist, hier ist meine Lösung:

Animation.h:

@interface MySplitViewAnimation : NSAnimation <NSAnimationDelegate> 

@property (nonatomic, strong) NSSplitView* splitView; 
@property (nonatomic) NSInteger dividerIndex; 
@property (nonatomic) float startPosition; 
@property (nonatomic) float endPosition; 
@property (nonatomic, strong) void (^completionBlock)(); 

- (instancetype)initWithSplitView:(NSSplitView*)splitView 
        dividerAtIndex:(NSInteger)dividerIndex 
          from:(float)startPosition 
           to:(float)endPosition 
        completionBlock:(void (^)())completionBlock; 
@end 

Animation, .m

@implementation MySplitViewAnimation 

- (instancetype)initWithSplitView:(NSSplitView*)splitView 
        dividerAtIndex:(NSInteger)dividerIndex 
          from:(float)startPosition 
           to:(float)endPosition 
        completionBlock:(void (^)())completionBlock; 
{ 
    if (self = [super init]) { 
     self.splitView = splitView; 
     self.dividerIndex = dividerIndex; 
     self.startPosition = startPosition; 
     self.endPosition = endPosition; 
     self.completionBlock = completionBlock; 

     [self setDuration:0.333333]; 
     [self setAnimationBlockingMode:NSAnimationNonblocking]; 
     [self setAnimationCurve:NSAnimationEaseIn]; 
     [self setFrameRate:30.0]; 
     [self setDelegate:self]; 
    } 
    return self; 
} 

- (void)setCurrentProgress:(NSAnimationProgress)progress 
{ 
    [super setCurrentProgress:progress]; 

    float newPosition = self.startPosition + ((self.endPosition - self.startPosition) * progress); 

    [self.splitView setPosition:newPosition 
       ofDividerAtIndex:self.dividerIndex]; 

    if (progress == 1.0) { 
     self.completionBlock(); 
    } 
} 

@end 

ich es so bin mit - Ich habe eine 3 Scheibe Teiler Ansicht und bewege den rechten Fensterbereich in/out um einen festen Betrag (235).

- (IBAction)togglePropertiesPane:(id)sender 
{ 
    if (self.rightPane.isHidden) { 

     self.rightPane.hidden = NO; 

     [[[MySplitViewAnimation alloc] initWithSplitView:_splitView 
              dividerAtIndex:1 
                from:_splitView.frame.size.width 
                to:_splitView.frame.size.width - 235                            
         completionBlock:^{ 
       ; 
           }] startAnimation]; 
} 
else { 
    [[[MySplitViewAnimation alloc] initWithSplitView:_splitView 
             dividerAtIndex:1               
               from:_splitView.frame.size.width - 235 
               to:_splitView.frame.size.width 
            completionBlock:^{   
     self.rightPane.hidden = YES; 
            }] startAnimation]; 
    } 
} 
0

NSSplitViewItem (d.h. subview von NSSplitView angeordnet) vollständig zusammengeklappt werden kann, wenn es Zero Dimension (Breite oder Höhe) erreichen kann. Wir müssen also vor der Animation die entsprechenden Einschränkungen deaktivieren und zulassen, dass die Ansicht die Dimension Zero erreicht. Nach der Animation können wir die erforderlichen Einschränkungen erneut aktivieren.

Siehe meinen Kommentar für SO Frage How to expand and collapse NSSplitView subviews with animation?.

Verwandte Themen