2014-10-30 2 views
6

Я пробовал все, о чем я могу думать, включая все предложения, которые я нашел здесь, на SO и в других списках рассылки, но я не могу понять, как программно свернуть область NSSplitView с анимацией, когда включен автоматический макет.Как свернуть панель NSSplitView с анимацией при использовании автоматического макета?

Вот что я прямо сейчас (написано в Swift для удовольствия), но он падает вниз несколькими способами:

@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:' в прокси-сервер анимации split. –

+0

@KenThomases Я пробовал это. Нет кубиков. – mdiep

ответ

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] 

Swift:

splitViewItem.animator().collapsed = true 

С помощью Apple:

ли или нет ребенок ViewController, соответствующая SplitViewItem является седло истек в SplitViewController. По умолчанию NO. Это можно установить с помощью прокси-сервера аниматора, чтобы оживить сбой или uncollapse. Точную анимацию можно настроить, установив ее в словарь -анимации с ключом «свернуть». Если это значение установлено в YES до того, как оно будет добавлено в SplitViewController, оно будет изначально сработало, а SplitViewController не приведет к загрузке изображения до тех пор, пока оно не будет распаковано. Это соответствует KVC/KVO и будет обновляться, если значение изменяется от взаимодействия пользователя.

+1

К сожалению, 'NSSplitViewItem' является частью нового API на 10.10. Если бы я мог использовать это, мне не нужно было задавать вопрос. :) – mdiep

+0

Проверьте изменения. –

+3

Я понимаю. Но NSSplitViewItem доступен только с 10.10 и позже. – mdiep

1

В конечном итоге мне удалось выяснить это с некоторой помощью. Я преобразовал свой тестовый проект в многоразовый подклассу NSSplitView: https://github.com/mdiep/MDPSplitView

0

По какой-то причине ни один из методов анимации кадров не работал для моего scrollview. Тем не менее, я не пытался оживить ограничения.

В результате я создал пользовательскую анимацию для анимации положения разделителя. Если кому-то интересно, вот мое решение:

Анимация.ч:

@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. После анимации мы снова можем активировать необходимые ограничения.

Посмотрите мои комментарии по этому вопросу How to expand and collapse NSSplitView subviews with animation?.

Смежные вопросы