CALayer 动画缩放,中心固定在 iOS7
CALayer Animation Scale with fixed centre on iOS7
我一直在为我认为会很容易的事情而苦思冥想。一个脉冲圈,SO上有几个例子,但我仍然无法解决最后一件事。
使用下面的代码,我确实有一个可以很好地扩展和收缩的圆,但是在收缩期间,缩放是从 CGRect 的图层框架(左上角)完成的。扩展工作正常,expansion/contraction 在 iOS8 上工作正常。问题只发生在 iOS7.
我试过设置锚点,在展开时平移视图……似乎没有任何效果……我做错了什么,我不知道是什么。
如果有人想尝试使用下面的代码,您只需要一个 UIViewController、一个标签和一个按钮,连接到下面的 IBOutlets。
这是我在将我的应用程序提交到 App Store 之前的最后一个已知错误...:\
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *label;
@property (weak, nonatomic) IBOutlet UIButton *button;
@property (nonatomic) BOOL isExpanded;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.isExpanded = YES;
self.label.layer.cornerRadius = self.label.frame.size.width/2;
self.label.layer.masksToBounds = YES;
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
}
- (IBAction)ExpandOrCollapse:(id)sender {
[self.button setEnabled:NO];
CGFloat animationDuration = 0.30f; // Your duration
CGFloat animationDelay = 0.0f; // Your delay (if any)
if (self.isExpanded) {
CGAffineTransform t = CGAffineTransformMakeScale(.17f, .17f);
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
scaleAnimation.duration = animationDuration;
scaleAnimation.fromValue = [NSNumber numberWithFloat:1.0f];
scaleAnimation.toValue = [NSNumber numberWithFloat:0.17f];
[self.label.layer addAnimation:scaleAnimation forKey:@"scale"];
[UIView animateWithDuration:animationDuration
delay:animationDelay
options: UIViewAnimationOptionCurveEaseIn
animations:^{
}
completion:^(BOOL finished){
self.isExpanded = NO;
[self.label setTransform:t];
[self.button setEnabled:YES];
}];
}else{
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
scaleAnimation.duration = animationDuration;
scaleAnimation.fromValue = [NSNumber numberWithFloat:0.17f];
scaleAnimation.toValue = [NSNumber numberWithFloat:1.0f];
[self.label.layer addAnimation:scaleAnimation forKey:@"scale"];
[UIView animateWithDuration:0.3
delay:0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
}
completion:^(BOOL finished){
[self.button setEnabled:YES];
[self.label setTransform:CGAffineTransformMakeScale(1.0, 1.0f)];
self.isExpanded = YES;
}];
}
}
@end
编辑
对于 eiran,这是他修改后的代码。不幸的是问题仍然存在..
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *label;
@property (weak, nonatomic) IBOutlet UIButton *button;
@property (nonatomic) BOOL isExpanded;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.isExpanded = YES;
self.label.layer.cornerRadius = self.label.frame.size.width/2;
self.label.layer.masksToBounds = YES;
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
}
- (IBAction)ExpandOrCollapse:(id)sender {
[self.button setEnabled:NO];
CGFloat animationDuration = 0.30f; // Your duration
CGFloat animationDelay = 0.0f; // Your delay (if any)
if (self.isExpanded) {
[UIView animateWithDuration:animationDuration
delay:animationDelay
options: UIViewAnimationOptionCurveEaseIn
animations:^{
[self.label setTransform:CGAffineTransformScale(CGAffineTransformIdentity, 0.17f, 0.17f)];
}
completion:^(BOOL finished){
self.isExpanded = NO;
[self.button setEnabled:YES];
}];
}else{
[UIView animateWithDuration:0.3
delay:0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
[self.label setTransform:CGAffineTransformScale(CGAffineTransformIdentity, 1.0f, 1.0f)];
}
completion:^(BOOL finished){
[self.button setEnabled:YES];
self.isExpanded = YES;
}];
}
}
这似乎对我有用:
[UIView animateWithDuration:0.75
delay:0
options:UIViewAnimationOptionRepeat|UIViewAnimationOptionAutoreverse|UIViewAnimationOptionAllowUserInteraction
animations:^{
self.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.95, 0.95);
}completion:^(BOOL b){
}];
这是一个重复缩放动画。
编辑:
那么好吧:)苹果以神秘的方式工作。
我已经为您找到了解决方案,但我不确定问题出在哪里。
在 ios 7.1 中,如果您使用情节提要,缩放会按您所说的进行。
但是,如果您动态添加组件,则动画效果很好。将此添加到您的代码中并查看:
- (void)viewDidLoad {
[super viewDidLoad];
self.isExpanded = YES;
UIButton* b = [UIButton buttonWithType:UIButtonTypeCustom];
[b setFrame:CGRectMake(100, 400, 120, 40)];
[b addTarget:self action:@selector(expand:) forControlEvents:UIControlEventTouchUpInside];
[b setBackgroundColor:[UIColor blueColor]];
[b setTitle:@"added dynamically" forState:UIControlStateNormal];
[self.view addSubview:b];
}
-(void)expand:(UIButton*)sender{
CGFloat animationDuration = 0.30f; // Your duration
CGFloat animationDelay = 0.0f; // Your delay (if any)
if (self.isExpanded) {
[UIView animateWithDuration:animationDuration
delay:animationDelay
options: UIViewAnimationOptionCurveEaseIn
animations:^{
[sender setTransform:CGAffineTransformScale(CGAffineTransformIdentity, 0.8f, 0.8f)];
}
completion:^(BOOL finished){
self.isExpanded = NO;
}];
}else{
[UIView animateWithDuration:0.3
delay:0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
[sender setTransform:CGAffineTransformScale(CGAffineTransformIdentity, 1.0f, 1.0f)];
}
completion:^(BOOL finished){
self.isExpanded = YES;
}];
}
}
正如你所说,它固定在 ios 8。
我认为这可能与约束有关,但看起来没有。
在此处添加了一个演示此测试的项目:
the test
希望对你有帮助,英兰。
我一直在为我认为会很容易的事情而苦思冥想。一个脉冲圈,SO上有几个例子,但我仍然无法解决最后一件事。
使用下面的代码,我确实有一个可以很好地扩展和收缩的圆,但是在收缩期间,缩放是从 CGRect 的图层框架(左上角)完成的。扩展工作正常,expansion/contraction 在 iOS8 上工作正常。问题只发生在 iOS7.
我试过设置锚点,在展开时平移视图……似乎没有任何效果……我做错了什么,我不知道是什么。
如果有人想尝试使用下面的代码,您只需要一个 UIViewController、一个标签和一个按钮,连接到下面的 IBOutlets。
这是我在将我的应用程序提交到 App Store 之前的最后一个已知错误...:\
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *label;
@property (weak, nonatomic) IBOutlet UIButton *button;
@property (nonatomic) BOOL isExpanded;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.isExpanded = YES;
self.label.layer.cornerRadius = self.label.frame.size.width/2;
self.label.layer.masksToBounds = YES;
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
}
- (IBAction)ExpandOrCollapse:(id)sender {
[self.button setEnabled:NO];
CGFloat animationDuration = 0.30f; // Your duration
CGFloat animationDelay = 0.0f; // Your delay (if any)
if (self.isExpanded) {
CGAffineTransform t = CGAffineTransformMakeScale(.17f, .17f);
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
scaleAnimation.duration = animationDuration;
scaleAnimation.fromValue = [NSNumber numberWithFloat:1.0f];
scaleAnimation.toValue = [NSNumber numberWithFloat:0.17f];
[self.label.layer addAnimation:scaleAnimation forKey:@"scale"];
[UIView animateWithDuration:animationDuration
delay:animationDelay
options: UIViewAnimationOptionCurveEaseIn
animations:^{
}
completion:^(BOOL finished){
self.isExpanded = NO;
[self.label setTransform:t];
[self.button setEnabled:YES];
}];
}else{
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
scaleAnimation.duration = animationDuration;
scaleAnimation.fromValue = [NSNumber numberWithFloat:0.17f];
scaleAnimation.toValue = [NSNumber numberWithFloat:1.0f];
[self.label.layer addAnimation:scaleAnimation forKey:@"scale"];
[UIView animateWithDuration:0.3
delay:0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
}
completion:^(BOOL finished){
[self.button setEnabled:YES];
[self.label setTransform:CGAffineTransformMakeScale(1.0, 1.0f)];
self.isExpanded = YES;
}];
}
}
@end
编辑
对于 eiran,这是他修改后的代码。不幸的是问题仍然存在..
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *label;
@property (weak, nonatomic) IBOutlet UIButton *button;
@property (nonatomic) BOOL isExpanded;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.isExpanded = YES;
self.label.layer.cornerRadius = self.label.frame.size.width/2;
self.label.layer.masksToBounds = YES;
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
}
- (IBAction)ExpandOrCollapse:(id)sender {
[self.button setEnabled:NO];
CGFloat animationDuration = 0.30f; // Your duration
CGFloat animationDelay = 0.0f; // Your delay (if any)
if (self.isExpanded) {
[UIView animateWithDuration:animationDuration
delay:animationDelay
options: UIViewAnimationOptionCurveEaseIn
animations:^{
[self.label setTransform:CGAffineTransformScale(CGAffineTransformIdentity, 0.17f, 0.17f)];
}
completion:^(BOOL finished){
self.isExpanded = NO;
[self.button setEnabled:YES];
}];
}else{
[UIView animateWithDuration:0.3
delay:0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
[self.label setTransform:CGAffineTransformScale(CGAffineTransformIdentity, 1.0f, 1.0f)];
}
completion:^(BOOL finished){
[self.button setEnabled:YES];
self.isExpanded = YES;
}];
}
}
这似乎对我有用:
[UIView animateWithDuration:0.75
delay:0
options:UIViewAnimationOptionRepeat|UIViewAnimationOptionAutoreverse|UIViewAnimationOptionAllowUserInteraction
animations:^{
self.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.95, 0.95);
}completion:^(BOOL b){
}];
这是一个重复缩放动画。
编辑: 那么好吧:)苹果以神秘的方式工作。 我已经为您找到了解决方案,但我不确定问题出在哪里。 在 ios 7.1 中,如果您使用情节提要,缩放会按您所说的进行。 但是,如果您动态添加组件,则动画效果很好。将此添加到您的代码中并查看:
- (void)viewDidLoad {
[super viewDidLoad];
self.isExpanded = YES;
UIButton* b = [UIButton buttonWithType:UIButtonTypeCustom];
[b setFrame:CGRectMake(100, 400, 120, 40)];
[b addTarget:self action:@selector(expand:) forControlEvents:UIControlEventTouchUpInside];
[b setBackgroundColor:[UIColor blueColor]];
[b setTitle:@"added dynamically" forState:UIControlStateNormal];
[self.view addSubview:b];
}
-(void)expand:(UIButton*)sender{
CGFloat animationDuration = 0.30f; // Your duration
CGFloat animationDelay = 0.0f; // Your delay (if any)
if (self.isExpanded) {
[UIView animateWithDuration:animationDuration
delay:animationDelay
options: UIViewAnimationOptionCurveEaseIn
animations:^{
[sender setTransform:CGAffineTransformScale(CGAffineTransformIdentity, 0.8f, 0.8f)];
}
completion:^(BOOL finished){
self.isExpanded = NO;
}];
}else{
[UIView animateWithDuration:0.3
delay:0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
[sender setTransform:CGAffineTransformScale(CGAffineTransformIdentity, 1.0f, 1.0f)];
}
completion:^(BOOL finished){
self.isExpanded = YES;
}];
}
}
正如你所说,它固定在 ios 8。 我认为这可能与约束有关,但看起来没有。
在此处添加了一个演示此测试的项目: the test
希望对你有帮助,英兰。