programing

UIView 애니메이션을 취소하시겠습니까?

powerit 2023. 5. 8. 22:27
반응형

UIView 애니메이션을 취소하시겠습니까?

할 수 ?UIView진행 중인 동안 애니메이션?아니면 CA 레벨로 떨어져야 합니까?

예를 들어, 다음과 같은 작업을 수행했습니다(아마도 애니메이션 종료 작업 설정).

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve: UIViewAnimationCurveLinear];
// other animation properties

// set view properties

[UIView commitAnimations];

하지만 애니메이션이 완료되고 애니메이션 종료 이벤트를 받기 전에 취소하고 싶습니다(간단하게).이것이 가능합니까?구글링을 하다 보면 몇 명의 사람들이 아무런 대답도 없이 같은 질문을 하는 것을 발견하고 한 두 명의 사람들은 그것이 불가능하다고 추측합니다.

사용:

#import <QuartzCore/QuartzCore.h>

.......

[myView.layer removeAllAnimations];

제가 하는 방법은 엔드포인트에 대한 새로운 애니메이션을 만드는 것입니다.매우 짧은 기간을 설정하고 다음을 사용해야 합니다.+setAnimationBeginsFromCurrentState:현재 상태에서 시작할 메서드입니다.YES로 설정하면 현재 애니메이션이 단축됩니다.다음과 같이 보입니다.

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.1];
[UIView setAnimationCurve: UIViewAnimationCurveLinear];
// other animation properties

// set view properties

[UIView commitAnimations];

특정 보기에서 모든 애니메이션을 즉시 중지하는 가장 간단한 방법은 다음과 같습니다.

프로젝트를 QuartzCore.framework에 연결합니다.코드 시작 부분:

#import <QuartzCore/QuartzCore.h>

이제 트랙에서 죽은 뷰의 모든 애니메이션을 중지하려면 다음과 같이 말합니다.

[CATransaction begin];
[theView.layer removeAllAnimations];
[CATransaction commit];

중간 선은 모두 자체적으로 작동하지만 실행 루프가 완료될 때까지 지연됩니다("다시 그리기 모멘트").이러한 지연을 방지하려면 그림과 같이 명시적 트랜잭션 블록으로 명령을 감쌉니다.이 작업은 현재 실행 루프에서 이 계층에 대해 다른 변경이 수행되지 않은 경우에 수행됩니다.

iOS 4 이상에서는 두 번째 애니메이션의 옵션을 사용하여 첫 번째 애니메이션을 짧게 자릅니다.

예를 들어, 활동 표시기가 있는 보기가 있다고 가정합니다.활동 표시기에서 시간이 많이 소요될 수 있는 활동이 시작되는 동안 페이드아웃하고 활동이 완료되면 페이드아웃할 수 있습니다.를 아래코드활동표시있가기는같부다다릅이니음과보기는서라고 합니다.activityView.

- (void)showActivityIndicator {
    activityView.alpha = 0.0;
    activityView.hidden = NO;
    [UIView animateWithDuration:0.5
                 animations:^(void) {
                     activityView.alpha = 1.0;
                 }];

- (void)hideActivityIndicator {
    [UIView animateWithDuration:0.5
                 delay:0 options:UIViewAnimationOptionBeginFromCurrentState
                 animations:^(void) {
                     activityView.alpha = 0.0;
                 }
                 completion:^(BOOL completed) {
                     if (completed) {
                         activityView.hidden = YES;
                     }
                 }];
}

애니메이션을 취소하려면 UIView 애니메이션 외부에서 현재 애니메이션 중인 속성을 설정하기만 하면 됩니다.그러면 애니메이션이 어디에 있든 애니메이션이 중지되고 UIView가 방금 정의한 설정으로 이동합니다.

이 답변을 부활시켜서 미안하지만, iOS 10에서는 약간의 변화가 있었고, 이제 취소가 가능하고 우아하게 취소할 수도 있습니다!

iOS 10 이후에는 UIViewPropertyAnimator로 애니메이션을 취소할 수 있습니다!

UIViewPropertyAnimator(duration: 2, dampingRatio: 0.4, animations: {
    view.backgroundColor = .blue
})
animator.stopAnimation(true)

true를 통과하면 애니메이션이 취소되고 취소한 곳에서 바로 중지됩니다.완료 메서드는 호출되지 않습니다.그러나 거짓을 전달한 경우 애니메이션을 완료해야 합니다.

animator.finishAnimation(.start)

애니메이션을 완료하고 현재 상태(.current)를 유지하거나 초기 상태(.start) 또는 종료 상태(.end)로 이동할 수 있습니다.

그런데, 일시 중지했다가 나중에 다시 시작할 수도 있습니다.

animator.pauseAnimation()
animator.startAnimation()

참고: 갑작스러운 취소를 원하지 않는 경우 애니메이션을 취소하거나 일시 중지한 후 애니메이션을 변경할 수도 있습니다!

보기 속성 대신 상수를 변경하여 제약 조건을 애니메이션화하는 경우 다른 방법은 iOS 8에서 작동하지 않습니다.

애니메이션 예제:

self.constraint.constant = 0;
[self.view updateConstraintsIfNeeded];
[self.view layoutIfNeeded];
[UIView animateWithDuration:1.0f
                      delay:0.0f
                    options:UIViewAnimationOptionCurveLinear
                 animations:^{
                     self.constraint.constant = 1.0f;
                     [self.view layoutIfNeeded];
                 } completion:^(BOOL finished) {

                 }];

솔루션:

제약 조건 변경의 영향을 받는 뷰 레이어와 해당 하위 레이어에서 애니메이션을 제거해야 합니다.

[self.constraintView.layer removeAllAnimations];
for (CALayer *l in self.constraintView.layer.sublayers)
{
    [l removeAllAnimations];
}

애니메이션을 부드럽게 일시 중지/중지하려는 경우

self.yourView.layer.speed = 0;

출처: 도면층 트리의 애니메이션 일시 중지 방법

위의 어느 것도 해결해 주지 않았지만, 이것은 도움이 되었습니다.UIView애니메이션은 속성을 즉시 설정한 다음 애니메이션을 만듭니다.프레젠테이션 도면층이 모델(설정된 속성)과 일치하면 애니메이션이 중지됩니다.

저는 제 문제를 해결했습니다. "당신처럼 보이는 곳에서 애니메이션을 만들고 싶어요."('당신'은 풍경을 의미합니다.)원하는 경우:

  1. Quartz Core를 추가합니다.
  2. CALayer * pLayer = theView.layer.presentationLayer;

프레젠테이션 계층에 위치 설정

는 다과같은몇가사옵다니용합션을지음▁including다▁options▁few▁a를 포함한 몇 가지 옵션을 합니다.UIViewAnimationOptionOverrideInheritedDuration

하지만 애플의 문서가 모호하기 때문에, 저는 그것이 사용될 때 정말로 다른 애니메이션을 무시하는지 아니면 타이머를 재설정하는지 모르겠습니다.

[UIView animateWithDuration:blah... 
                    options: UIViewAnimationOptionBeginFromCurrentState ... 
                    animations: ^ {
                                   theView.center = CGPointMake( pLayer.position.x + YOUR_ANIMATION_OFFSET, pLayer.position.y + ANOTHER_ANIMATION_OFFSET);
                   //this only works for translating, but you get the idea if you wanna flip and scale it. 
                   } completion: ^(BOOL complete) {}];

그리고 그것은 지금으로서는 괜찮은 해결책이 되어야 합니다.

[UIView setAnimationsEnabled:NO];
// your code here
[UIView setAnimationsEnabled:YES];

Stephen Darlington 솔루션의 빠른 버전

UIView.beginAnimations(nil, context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(0.1)
// other animation properties

// set view properties
UIView.commitAnimations()

저도 같은 문제가 있습니다. API에는 특정 애니메이션을 취소할 수 있는 기능이 없습니다.

+ (void)setAnimationsEnabled:(BOOL)enabled

모든 애니메이션을 사용할 수 없으므로 사용할 수 없습니다.두 가지 솔루션이 있습니다.

애니메이션 개체를 하위 뷰로 만듭니다.그런 다음 해당 보기에 대한 애니메이션을 취소하려면 보기를 제거하거나 숨깁니다.매우 간단하지만 보기를 유지해야 할 경우 애니메이션 없이 하위 보기를 다시 만들어야 합니다.

다음과 같이 애니메이션을 하나만 반복하고 필요한 경우 대리 선택기를 만들어 애니메이션을 다시 시작합니다.

-(void) startAnimation {
NSLog(@"startAnim alpha:%f", self.alpha);
[self setAlpha:1.0];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationRepeatCount:1];
[UIView setAnimationRepeatAutoreverses:YES];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(pulseAnimationDidStop:finished:context:)];
[self setAlpha:0.1];
[UIView commitAnimations];
}

- (void)pulseAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
if(hasFocus) {
    [self startAnimation];
} else {
    self.alpha = 1.0;
}
}

-(void) setHasFocus:(BOOL)_hasFocus {
hasFocus = _hasFocus;
if(hasFocus) {
    [self startAnimation];
}
}

2)의 문제는 애니메이션이 현재 애니메이션 주기를 완료할 때마다 애니메이션을 중지하는 데 항상 지연이 발생한다는 것입니다.

이게 도움이 되길 바랍니다.

위와 같은 방법으로 애니메이션을 취소하더라도didStopSelector계속 실행됩니다.따라서 애니메이션으로 구동되는 응용 프로그램에 논리 상태가 있으면 문제가 발생합니다.이러한 이유로 위에서 설명한 방법으로 다음의 컨텍스트 변수를 사용합니다.UIView애니메이션프로그램의 현재 상태를 컨텍스트 매개 변수로 애니메이션에 전달하는 경우 애니메이션이 중지될 때didStopSelector함수는 현재 상태와 컨텍스트로 전달된 상태 값을 기반으로 어떤 작업을 수행할지 또는 단순히 반환할지 결정할 수 있습니다.

CALayer * pLayer = self.layer.presentationLayer;
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView animateWithDuration:0.001 animations:^{
    self.frame = pLayer.frame;
}];

상태를 원본 또는 최종으로 되돌리지 않고 애니메이션을 일시 중지하려면:

CFTimeInterval paused_time = [myView.layer convertTime:CACurrentMediaTime() fromLayer:nil];
myView.layer.speed = 0.0;
myView.layer.timeOffset = paused_time;

작업할 때UIStackView애니메이션, 게다가removeAllAnimations()초기 값으로 몇 가지 값을 설정해야 합니다.removeAllAnimations()예측할 수 없는 상태로 설정할 수 있습니다.있습니다stackView와 함께view1그리고.view2내부에서 하나의 보기를 볼 수 있고 하나는 숨겨야 합니다.

public func configureStackView(hideView1: Bool, hideView2: Bool) {
    let oldHideView1 = view1.isHidden
    let oldHideView2 = view2.isHidden
    view1.layer.removeAllAnimations()
    view2.layer.removeAllAnimations()
    view.layer.removeAllAnimations()
    stackView.layer.removeAllAnimations()
    // after stopping animation the values are unpredictable, so set values to old
    view1.isHidden = oldHideView1 //    <- Solution is here
    view2.isHidden = oldHideView2 //    <- Solution is here

    UIView.animate(withDuration: 0.3,
                   delay: 0.0,
                   usingSpringWithDamping: 0.9,
                   initialSpringVelocity: 1,
                   options: [],
                   animations: {
                    view1.isHidden = hideView1
                    view2.isHidden = hideView2
                    stackView.layoutIfNeeded()
    },
                   completion: nil)
}

답변된 솔루션 중 어떤 것도 저에게 효과가 없었습니다.이 문제를 이렇게 해결했습니다(정확한 방법인지는 모르겠습니다만). 너무 빨리 호출할 때 문제가 발생했기 때문입니다(이전 애니메이션이 아직 완료되지 않았습니다).나는 내가 원하는 애니메이션을 고객에게 전달합니다.애니 블록.

extension UIView
{

    func niceCustomTranstion(
        duration: CGFloat = 0.3,
        options: UIView.AnimationOptions = .transitionCrossDissolve,
        customAnim: @escaping () -> Void
        )
    {
        UIView.transition(
            with: self,
            duration: TimeInterval(duration),
            options: options,
            animations: {
                customAnim()
        },
            completion: { (finished) in
                if !finished
                {
                    // NOTE: This fixes possible flickering ON FAST TAPPINGS
                    // NOTE: This fixes possible flickering ON FAST TAPPINGS
                    // NOTE: This fixes possible flickering ON FAST TAPPINGS
                    self.layer.removeAllAnimations()
                    customAnim()
                }
        })

    }

}

필요에 따라 시작 및 중지할 수 있는 유연한 애니메이션을 찾으려면 UIViewPropertyAnimator를 사용합니다.

샘플 코드

let sampleView = UIView()

lazy var animator: UIViewPropertyAnimator = {
    let animator = UIViewPropertyAnimator(duration: 1.2, curve: .easeOut)
    animator.isInterruptible = true
    return animator
}()

// add and your animatable property
animator.addAnimations {
   // what you need to animate add here
   sampleView.alpha = 0
}

// start animation
animator.startAnimation(afterDelay: 0.5)

애니메이션 중간에 멈춰야 할 경우.현재 상태에서 애니메이션이 중지됩니다.

// stop animation
if animator.isRunning {
    animator.stopAnimation(true)
}

언급URL : https://stackoverflow.com/questions/554997/cancel-a-uiview-animation

반응형