2014-10-30 74 views
6

我試過了我能想到的所有東西,包括我在SO和其他郵件列表中找到的所有建議,但我無法弄清楚如何在自動佈局打開時以編程方式摺疊具有動畫的NSSplitView窗格。如何使用自動佈局在動畫中摺疊NSSplitView窗格?

這就是我現在所擁有的(寫在斯威夫特的樂趣),但它以多種方式倒下:

@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 
    }) 
} 

期望的行爲和外觀是Mail.app,其中動畫真的很好的。

我有一個完整的示例應用程序可在https://github.com/mdiep/NSSplitViewTest

+0

嘗試發送'-setPosition:ofDividerAtIndex:'到分割視圖的'animator'代理。 – 2014-10-31 03:30:40

+0

@KenThomases我試過了。沒有骰子。 – mdiep 2014-10-31 12:13:36

回答

0

如果您正在使用自動佈局,並且想要爲視圖的尺寸/位置的某個方面設置動畫,則可能會有更多運氣爲約束本身設置動畫。我已經快速地與NSSplitView一起去了,但迄今爲止只有有限的成功。在按下按鈕後,我可以分裂擴展和崩潰,但最終我不得不繞過干擾約束而導致的其他問題。如果你不熟悉它,這裏有一個簡單的約束動畫:

- (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 */ 

    }]; 

請記住,你只能一個動畫約束constant,你不能動畫的priority

10

的Objective-C:

[[splitViewItem animator] setCollapse:YES] 

斯威夫特:

splitViewItem.animator().collapsed = true 

從蘋果公司的幫助:

無論孩子的ViewController對應 SplitViewItem是關口在SplitViewController中失效。默認值是 。這可以通過動畫代理來設置,以便對摺疊或未摺疊進行動畫製作。可以通過在「動畫詞典」中使用「摺疊」鍵將其設置爲 來自定義使用的確切動畫。如果在將 添加到SplitViewController之前將它設置爲YES,則最初將摺疊爲 ,並且SplitViewController不會導致 視圖在未摺疊之前加載。這是符合KVC/KVO標準的 ,如果該值從用戶交互中更改,則會更新。

+1

不幸的是,'NSSplitViewItem'是10.10上新API的一部分。如果能夠使用它,我不需要問這個問題。 :) – mdiep 2014-11-10 14:21:59

+0

檢查編輯。 – 2014-11-10 18:45:03

+3

我明白。但NSSplitViewItem僅在10.10及更高版本上可用。 – mdiep 2014-11-11 21:03:46

0

由於某種原因,沒有任何動畫框架的方法可用於我的滾動視圖。儘管我沒有嘗試對約束進行動畫處理。

我最終創建了一個自定義動畫來爲分隔線位置設置動畫。如果有人有興趣,這裏是我的解決方案:

動畫。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 

動畫的.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 

我使用它這樣的 - 我有一個3窗格拆分視圖,和上午固定量移動/縮小右窗格(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(即佈置NSSplitView子視圖)可被完全摺疊,如果它可以達到Zero尺寸(寬度或高度)。所以,我們只需要在動畫之前停用適當的約束,並允許視圖達到Zero維度。動畫之後,我們可以再次激活需要的約束

請參閱我的評論SO問題How to expand and collapse NSSplitView subviews with animation?