Programming

NSLayoutConstraints는 애니메이션 가능합니까?

procodes 2020. 5. 10. 11:57
반응형

NSLayoutConstraints는 애니메이션 가능합니까? [복제]


이 질문에는 이미 답변이 있습니다.

풍경의 거대한 키보드에 의해 차단되도록 일부 뷰를 애니메이션하려고합니다. 프레임에 단순히 애니메이션을 적용하면 잘 작동하지만 다른 사람들은 이것이 비생산적이며 대신 NSLayoutConstraints를 업데이트해야한다고 제안했습니다. 그러나 애니메이션 효과가없는 것 같습니다. 누구든지 성공을 위해 일하게 되었습니까?

//heightFromTop is an NSLayoutConstraint referenced from IB
[UIView animateWithDuration:0.25 animations:^{
    self.heightFromTop.constant= 550.f;
}];

결과적으로 문제의 높이로 즉시 점프합니다.


이 정확한 패턴을 따르십시오.

self.heightFromTop.constant = 550.0f;
[myView setNeedsUpdateConstraints];

[UIView animateWithDuration:0.25f animations:^{
   [myView layoutIfNeeded];
}];

여기서 myView도면이다 self.heightFromTop첨가 하였다. 애니메이션 블록에서 수행 한 유일한 작업은 구속 조건을 설정하는 것이기 때문에 레이아웃이 즉시 발생하지 않으므로 뷰가 "점프"합니다. 코드에서을 설정 한 후 다음 실행 루프에서 레이아웃이 발생 heightFromTop.constant하며 그 시간까지 이미 애니메이션 블록 범위를 벗어납니다.

스위프트 2에서 :

self.heightFromTop.constant = 550
myView.setNeedsUpdateConstraints()

UIView.animateWithDuration(0.25, animations: {
   myView.layoutIfNeeded()
})

Apple이 제안한 방법은 약간 다릅니다 ( 예 : "자동 레이아웃으로 변경 한 애니메이션 애니메이션"섹션 참조 ). 먼저 애니메이션 전에 layoutIfNeeded를 호출해야합니다. 그런 다음 애니메이션 블록 안에 애니메이션을 추가 한 다음 마지막에 layoutIfNeeded를 다시 호출하십시오. 자동 레이아웃으로 전환하는 나와 같은 사람들에게는 애니메이션 블록 내부의 프레임으로 수행했던 이전 애니메이션과 더 유사한 방법입니다. 애니메이션 전과 애니메이션 후에 layoutIfNeeded를 두 번 호출하면됩니다.

[self.view layoutIfNeeded]; // Ensures that all pending layout operations have been completed

[UIView animateWithDuration:1.0f animations:^{

  // Make all constraint changes here
  self.heightFromTop.constant= 550.f;

  [self.view layoutIfNeeded]; // Forces the layout of the subtree animation block and then captures all of the frame changes

}];

@Centurion의 접근 방식을 시도했지만 스토리 보드에서로드 된 경우 어떻게 든 내보기가 잘못된 프레임으로 애니메이션됩니다. 첫 번째 layoutIfNeeded로 바꾸면 문제가 사라지 updateConstraintsIfNeeded지만 이유는 모르겠습니다. 누구나 설명을 할 수 있다면 대단히 감사하겠습니다.

[self.view updateConstraintsIfNeeded];
[UIView animateWithDuration:1.0 animations:^{
    self.myConstraint.constant= 100;
    [self.view layoutIfNeeded];
}];

나는 비슷한 문제가 있었고이 스레드는 그것을 극복하는 데 큰 도움이되었습니다.

erurainon의 답변이 올바른 길로 안내되었지만 약간 다른 답변을 제안하고 싶습니다. erurainon의 제안 된 코드는 애니메이션 전환 대신 점프가 있었기 때문에 나에게는 효과가 없었습니다. cnotethegr8에서 제공하는 링크를 통해 실제 답변을 얻을 수 있습니다.

자동 레이아웃 설명서 https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/AutoLayoutbyExample/AutoLayoutbyExample.html (페이지 하단까지)

Erurainon의 답변과 몇 가지 차이점 :

  1. 애니메이션 메서드를 호출하기 전에 컨테이너 뷰에서 레이아웃 레이아웃을 호출합니다 (myView의 setNeedsUpdateConstraints 대신).
  2. 애니메이션 블록에서 새로운 구속 조건을 설정하십시오.
  3. myView 대신 애니메이션 메서드의 컨테이너보기에서 제약 조건을 설정 한 후 layoutIfNeeded를 호출하십시오.

위 링크에서 Apple이 제안한 패턴을 준수합니다.

I wanted to animate a particular view, closing or expanding it at the click of a button. Since I'm using autolayout and didn't want to hard code any dimensions (in my case height) in the code, I decided to capture the height in viewDidLayoutSubviews. You need to use this method and not viewWillAppear when using autolayout. Since viewDidLayoutSubviews may be called many times, I used a BOOL to let me know about the first execution for my initialization.

// Code snippets

@property (weak, nonatomic) IBOutlet UIView *topView; // Container for minimalView
@property (weak, nonatomic) IBOutlet UIView *minimalView; // View to animate

@property (nonatomic) CGFloat minimalViewFullHeight; // Original height of minimalView

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *minimalViewHeightConstraint;

@property (nonatomic) BOOL executedViewDidLayoutSubviews;


- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];


    // First execution of viewDidLayoutSubviews?
    if(!self.executedViewDidLayoutSubviews){
        self.executedViewDidLayoutSubviews = YES;


        // Record some original dimensions
        self.minimalViewFullHeight = self.minimalView.bounds.size.height;


        // Setup our initial view configuration & let system know that 
        // constraints need to be updated.
        self.minimalViewHeightConstraint.constant = 0.0;
        [self.minimalView setNeedsUpdateConstraints];

        [self.topView layoutIfNeeded];
    }
}

Resize full action snippet

// An action to close our minimal view and show our normal (full) view
- (IBAction)resizeFullAction:(UIButton *)sender {

    [self.topView layoutIfNeeded];

    [UIView transitionWithView:self.minimalView
                  duration:1.0
                   options:UIViewAnimationOptionTransitionCrossDissolve
                animations:^{
                    self.minimalViewHeightConstraint.constant = 0.0;

                    // Following call to setNeedsUpdateConstraints may not be necessary
                    [self.minimalView setNeedsUpdateConstraints];

                    [self.topView layoutIfNeeded];

                } completion:^(BOOL finished) {
                    ;
                }];

    // Other code to show full view
    // ...
}

Resize small action snippet

// An action to open our minimal view and hide our normal (full) view
- (IBAction)resizeSmallAction:(UIButton *)sender {

    [self.topView layoutIfNeeded];

    [UIView transitionWithView:self.minimalView
                  duration:1.0
                   options:UIViewAnimationOptionTransitionCrossDissolve
                animations:^{
                    self.minimalViewHeightConstraint.constant = self.minimalViewFullHeight;
                    [self.minimalView setNeedsUpdateConstraints];

                    [self.topView layoutIfNeeded];

                } completion:^(BOOL finished) {
                    ;
                }];

        // Other code to hide full view
        // ...
    }

You can use animateWithDuration instead of transitionWithView if you wish.

Hope this helps.

참고URL : https://stackoverflow.com/questions/12926566/are-nslayoutconstraints-animatable

반응형