2012-02-29 4 views
14

내 응용 프로그램 중 하나에 대해 자동 레이아웃 지원 뷰 분할 클래스를 만들고 있습니다. 다양한 기능 중 하나는 NSSplitView에서 보았 듯이 창을 축소하고 축소를 활성화 할 수 있다는 것입니다. 나는 제약을 사용하고 있기 때문에NSLayoutConstraint.constant 애니메이션 무시 중

, 내가 설정 한 다음 창에 필요한 폭 = (현재 폭) 제약 조건을 배치하고, 이것을 달성하고있어 애니메이션 방식으로 제약의 상수 0 :

- (NSLayoutConstraint*)newHiddenConstraintAnimated:(BOOL)animated { 
    NSLayoutConstraint * constraint = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:NSWidth(self.view.frame)]; 
    constraint.priority = NSLayoutPriorityRequired; 

    CABasicAnimation * anim = [CABasicAnimation animation]; 
    anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; 
    anim.duration = 0.2; 
    constraint.animations = [NSDictionary dictionaryWithObject:anim forKey:@"constant"]; 

    [self.view addConstraint:constraint]; 

    [(animated ? constraint.animator : constraint) setConstant:0.0]; 

    return constraint; 
} 

이것은 아름답게 작동합니다. 불행히도, 창을 나중에 확장해도 그다지 좋지 않습니다. 나는 약간의 타이밍 코드를 삽입하면

- (void)removeHiddenConstraintAnimated:(BOOL)animated { 
    if(!animated) { 
     [self.view removeConstraint:self.hiddenConstraint]; 
    } 
    else { 
     NSLayoutConstraint * constraint = self.hiddenConstraint; 
     NSView * theView = self.view; 

     [NSAnimationContext beginGrouping]; 

     [constraint.animator setConstant:self.width]; 

     [NSAnimationContext currentContext].completionHandler = ^{ 
      [theView removeConstraint:constraint]; 
     }; 

     [NSAnimationContext endGrouping]; 
    } 

    self.hiddenConstraint = nil; 
} 

, 나는 애니메이션을하는 시간이되기 전에 제약 조건을 제거 완료 핸들러가 거의 즉시 발사 것을 볼 수 있습니다. NSAnimationContext에 지속 시간을 설정해도 아무 효과가 없습니다.

내가 여기서 잘못 할 수있는 아이디어가 있습니까?

+0

분할보기 클래스를 끝내셨습니까? 오픈 소스 화 가능성은? –

+0

나는 그 순간을 계획하지 않는다. 이 응용 프로그램에 상당히 특화된 것으로, [PURRDACTED]의'NSSplitView'가 autolayout으로 더 잘 작동하도록 재 설계되었습니다. –

+0

오, 잡았다. [redacted]와 관련하여 자동 레이아웃과 관련하여 좋은 점이 있지만 이전 목표와 역 호환되지는 않습니다. 오 잘, 나는 내가 추측 할 수있게 할 것이다! :) –

답변

15

당신은이에 먼저 완료 핸들러를 설정 한 경우에만 그 다음에 메시지를 보내 애니메이터 프록시. 그렇지 않으면 애니메이션 시작 후 완료 핸들러를 설정하면 애니메이션이 즉시 시작되고 애니메이션이 끝나기 전에 상수가 제거되는 것 같습니다.

[NSAnimationContext beginGrouping]; 
    NSAnimationContext.currentContext.duration = animagionDuration; 
    NSAnimationContext.currentContext.completionHandler = ^{[self removeConstraint:collapseConstraint];}; 
    [collapseConstraint.animator setConstant:expandedHeight]; 
    [NSAnimationContext endGrouping]; 

이 완벽하게 작동하지만, 당신이 -setConstant: 후 완료 핸들러를 설정하면, 애니메이션이 실행하는 기회가되지 않습니다 난 그냥 간단한 코드의 조각으로이 문제를 확인했습니다.

+0

와우, 정말 효과가있었습니다. 팁 고마워! –

+0

전혀 아니지만, 몇 시간 전 나는 같은 문제에 부딪 쳤고, 그것은 나를 실험에 이르게 한 당신의 질문이었습니다 :) – skh

1

난 그냥 내 자신이 너무이 순진 분석 할 수 있지만,이 재료와 그립에 받고 있어요는 :

당신이 지정하는 것을 나에게 보인다 (당신의 다른 블록) 제약의 속성에 애니메이션 애니메이션을 실행하기 전에 제약 조건에 대한 참조를 nil (잠정적으로 해제)로 설정하면됩니다.

애니메이션 완성 블록 내에서 hideConstraint를 nil로 설정하거나 애니메이션 완료 블록에 의해 트리거하려고한다고 기대합니다. 가능성으로, 만약 내가 잘못 내가 더 잘 :)

+0

뷰에 추가하는 제약 조건을 소유하고 있다고 가정하는 것이 합리적입니다. 따라서 제약 조건이 'hiddenConstraint' 속성을 통해 참조되지 않더라도 뷰의 제약 조건 목록에 의해 참조되어야합니다. 블록은 사용자가 사용하는 객체 변수의 값을 유지하기 때문에 블록 자체에서도 유지됩니다. –

+0

피터가 말했듯이 '제약'은 강력한 참조이며 블록에 의해 캡쳐되며보기가 아니더라도 제약 조건을 유지합니다. 적당히 복잡한 자동 레이아웃에는 수 백 가지의 제약이 있으며, 대다수는 그것들을 소유하고있는 뷰에 의해서만 참조됩니다. –

+0

친절한 답변 주셔서 감사합니다. –

3

가 생각하기 때문에 완료 핸들러가 즉시 발사되는이되지 않은있는 내가 그것을 이해하는 데 도움이하는 이유에 대해 한 두 마디를 부탁드립니다 것을

주 애니메이션을 실행해야합니다. 내가 만든 애니메이션이 여전히 뷰에 첨부되어 있는지 확인하고 확인합니다. 기본적으로 CABasicAnimation은 CAAnimation에서 상속 한 removedOnCompletion 속성 (기본적으로 YES로 설정 됨)을 통해 완료되면 자체를 제거하도록 설정됩니다.

당신은 동의

anim.removedOnCompletion = NO; 
+0

'anim.removedOnCompletion = NO; '를 추가해도 아무런 효과가 없습니다. 그래도 좋은 제안. –

12

에이 꽤 이상하다, 잘 버그 수 할 것입니다. 나는 내 지식의 가장 좋은 방법으로 이것을 해야하기 때문에 분명히보고 할 것입니다.

내가 beginGroupingendGrouping 문 대신 NSAnimationContext 클래스 메소드 +runAnimationGroup:completionHandler:을 사용하여 작동하도록 얻을 수 있었다 :

[NSAnimationContext runAnimationGroup:^(NSAnimationContext* context){ 
    [constraint.animator setConstant:self.width]; 
} completionHandler:^(void){ 
    [theView removeConstraint:constraint]; 
    NSLog(@"completed"); 
}]; 
+0

아아, 내 코드에 영향을 미치지 않은 것 같습니다. 나는 아마도 레이더 파일을 만들 것이다. 이것은 확실히 그것이 작동 해야하는 것처럼 보인다. –

+0

이상합니다. 확실히 여기에서 잘 작동합니다. –

+0

나를 위해 일해도. – stevex

관련 문제