두 개를 만드는 대신 하나의보기 UIImageViews
를 변경하는 것이 논리적으로 보입니다 image
. 그렇게하면 인스턴트 스위치 대신 두 이미지 사이에 페이드 / 크로스 디졸브가 발생합니까?
두 개를 만드는 대신 하나의보기 UIImageViews
를 변경하는 것이 논리적으로 보입니다 image
. 그렇게하면 인스턴트 스위치 대신 두 이미지 사이에 페이드 / 크로스 디졸브가 발생합니까?
답변:
편집 : 아래 @algal 의 더 나은 솔루션이 있습니다 .
이를 수행하는 또 다른 방법은 사전 정의 된 CAAnimation 전환을 사용하는 것입니다.
CATransition *transition = [CATransition animation];
transition.duration = 0.25;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade;
transition.delegate = self;
[self.view.layer addAnimation:transition forKey:nil];
view1.hidden = YES;
view2.hidden = NO;
Apple의 View Transitions 예제 프로젝트를 참조하십시오 : https://developer.apple.com/library/content/samplecode/ViewTransitions/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007411
새로운 블록 기반 UIKit animation
방법을 사용하면 훨씬 간단해질 수 있습니다 .
다음 코드가 뷰 컨트롤러에 있고 교차 디졸브하려는 UIImageView가 속성을 통해 주소를 지정할 수있는 self.view의 하위 뷰라고 가정 self.imageView
하면 필요한 것은 다음과 같습니다.
UIImage * toImage = [UIImage imageNamed:@"myname.png"];
[UIView transitionWithView:self.imageView
duration:5.0f
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
self.imageView.image = toImage;
} completion:nil]
끝난.
그리고 Swift에서 수행하려면 다음과 같이하십시오.
let toImage = UIImage(named:"myname.png")
UIView.transitionWithView(self.imageView,
duration:5,
options: UIViewAnimationOptions.TransitionCrossDissolve,
animations: { self.imageView.image = toImage },
completion: nil)
스위프트 3, 4 및 5
let toImage = UIImage(named:"myname.png")
UIView.transition(with: self.imageView,
duration: 0.3,
options: .transitionCrossDissolve,
animations: {
self.imageView.image = toImage
},
completion: nil)
스위프트 3.0.1 :
UIView.transition(with: self.imageView,
duration:0.5,
options: .transitionCrossDissolve,
animations: { self.imageView.image = newImage },
completion: nil)
그렇습니다. 당신이 말하는 것은 절대적으로 정확하며 그렇게하는 방법입니다. 나는이 방법을 썼고 항상 이것을 내 이미지에서 페이드로 사용합니다. 나는 이것을 처리 CALayer
합니다. 이를 위해 Core Animation을 가져와야합니다.
+ (void)fadeInLayer:(CALayer *)l
{
CABasicAnimation *fadeInAnimate = [CABasicAnimation animationWithKeyPath:@"opacity"];
fadeInAnimate.duration = 0.5;
fadeInAnimate.repeatCount = 1;
fadeInAnimate.autoreverses = NO;
fadeInAnimate.fromValue = [NSNumber numberWithFloat:0.0];
fadeInAnimate.toValue = [NSNumber numberWithFloat:1.0];
fadeInAnimate.removedOnCompletion = YES;
[l addAnimation:fadeInAnimate forKey:@"animateOpacity"];
return;
}
이미지 페이드 아웃에 대해 반대 작업을 수행 할 수 있습니다. 사라진 후. 당신은 그것을 superview (즉 UIImageView
) 에서 제거합니다 . [imageView removeFromSuperview]
.
페이드 인 기능을 서브 클래스에 패키지하여 다음 예제와 같이 공통 UIImageView로 사용할 수 있습니다.
IMMFadeImageView *fiv=[[IMMFadeImageView alloc] initWithFrame:CGRectMake(10, 10, 50, 50)];
[self.view addSubview:fiv];
fiv.image=[UIImage imageNamed:@"initialImage.png"];
fiv.image=[UIImage imageNamed:@"fadeinImage.png"]; // fades in
가능한 구현은 다음과 같습니다.
참고 : setImage:
함수 에서 페이드 인을 실제로 구현하는 방식 은 변경 될 수 있으며이 질문에 대한 다른 답변에서 설명하는 다른 훌륭한 예 중 하나 UIImageView
일 수 있습니다. 특정 상황에서 용납 할 수없는 오버 헤드가되어야합니다 .
IMMFadeImageView.h :
#import <UIKit/UIKit.h>
@interface IMMFadeImageView : UIImageView
@property (nonatomic,assign) float fadeDuration;
@end
IMMFadeImageView.m :
#import "IMMFadeImageView.h"
@implementation IMMFadeImageView
@synthesize fadeDuration;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.fadeDuration=1;
}
return self;
}
-(void)setImage:(UIImage *)newImage{
if(!self.image||self.fadeDuration<=0){
super.image=newImage;
} else {
UIImageView *iv=[[UIImageView alloc] initWithFrame:self.bounds];
iv.contentMode=self.contentMode;
iv.image=super.image;
iv.alpha=1;
[self addSubview:iv];
super.image=newImage;
[UIView animateWithDuration:self.fadeDuration delay:0 options:UIViewAnimationCurveEaseInOut animations:^{
iv.alpha=0;
} completion:^(BOOL finished) {
[iv removeFromSuperview];
}];
}
}
위의 코드는 XCode 프로젝트에서 활성화 된 ARC를 포함한 몇 가지 가정에 의존하며 개념 증명의 목적으로 만 사용되며 명확성과 초점을 위해 중요한 관련없는 코드를 생략하여 관련성을 유지합니다. 맹목적으로 복사하여 붙여 넣지 마십시오.
무기한 반복하려면 전환이 필요했습니다. 이것은 많은 시행 착오를 겪었지만 마침내 내가 찾은 최종 결과를 얻었습니다. UITableViewCell의 UIImageView에 이미지 애니메이션을 추가하기위한 코드 스 니펫입니다.
관련 코드는 다음과 같습니다.
@interface SomeViewController ()
@property(nonatomic, strong) NSMutableArray *imagesArray;
@property(nonatomic, assign) NSInteger varietyImageAnimationIndex;
@property(nonatomic, assign) BOOL varietyImagesAnimated;
@end
@implementation SomeViewController
@synthesize imagesArray;
@synthesize varietyImageAnimationIndex;
@synthesize varietyImagesAnimated;
...
// NOTE: Initialize the array of images in perhaps viewDidLoad method.
-(void)animateImages
{
varietyImageAnimationIndex++;
[UIView transitionWithView:varietyImageView
duration:2.0f
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
varietyImageView.image = [imagesArray objectAtIndex:varietyImageAnimationIndex % [imagesArray count]];
} completion:^(BOOL finished) {
[self animateImages];
}];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
[cell.imageView setImage:[imagesArray objectAtIndex:0]];
[self setVarietyImageView:cell.imageView];
if (! varietyImagesAnimated)
{
varietyImagesAnimated = YES;
[self animateImages];
}
...
return cell;
}
장난하고 옵션으로 UIView.transition()
문제가 발생한 후 .transitionCrossDissolve
(하나의 UIImageView 내에서 변경되는 이미지에 애니메이션을 적용하려고 시도했지만 애니메이션없이 즉시 전환이 발생했습니다) 뷰 내에서 속성 변경을 애니메이션으로 만들 수있는 옵션을 하나 더 추가해야한다는 것을 알았습니다 ( 스위프트 4.2 ) :
UIView.transition(with: self.imageView,
duration: 1,
options: [.allowAnimatedContent, .transitionCrossDissolve],
animations: { self.imageView.image = newImage },
completion: nil)
또한 : imageView에 하위보기가 있으면 다시 그려지며 애니메이션을 막을 수 있습니다. 예를 들어, imageView에서 흐림 효과가있는 하위보기가 있는데이 경우 애니메이션이 작동하지 않습니다. 그래서 방금 뷰 계층을 변경하고 블러를 자체 뷰로 옮기고 imageView 위에 올려 놓았습니다.
highlightedImage
이 속성 을 사용하면 좀 더 간단하게 만들 수 있습니다. 다음은 Swift 3의 예입니다. 먼저 일반 이미지와 강조 표시된 이미지를 모두 설정하십시오.
let imageView = UIImageView(image: UIImage(named: "image"), highlightedImage: UIImage(named: "highlightedImage"))
그리고 당신이 그 애니메이션 사이를 바꾸고 싶을 때 :
UIView.transition(with: imageView, duration: 0.3, options: .transitionCrossDissolve, animations: { self.imageView.isHighlighted = !self.imageView.isHighlighted}, completion: .none)