使用动画创建自定义视图

Posted

技术标签:

【中文标题】使用动画创建自定义视图【英文标题】:Creating a custom view with an animation 【发布时间】:2013-10-14 12:04:36 【问题描述】:

我正在尝试制作一个自定义视图,其中一个元素(UILabel)具有动画,当点击自定义视图的按钮时,标签应该展开然后收缩。动画的第一部分正确发生,但第二部分不正确。我正在使用这种方法。

[UIView animateWithDuration:1.3 animations:^
    CGRect frame = CGRectMake(50, 15, 140, 20);
    [labelFav setFrame:frame];
 completion:^(BOOL finished) 
    //[labelFav setHidden:YES];
    [UIView animateWithDuration:1.3 animations:^
        CGRect frame = CGRectMake(50, 15, 0, 20);
        [labelFav setFrame:frame];
    ];

];

我认为 Refresh 和 LayoutSubviews 方法的实现方式存在问题。 我是按照本教程完成的,ray wenderlinch

问题是在第一个动画被调用之后,LayoutSubviews被调用,所以所有的项目都被设置到初始位置,当第一个动画完成时,第二个动画开始但项目被设置为原始状态,所以我相信动画不会发生,因为动画之间发生了变化。

我想知道如何正确实现这个,你能帮帮我吗?

谢谢。

PS:这是第二个关于同一个问题但角度不同的问题。my previous question

[更新]

这是我的 LayoutSubviews 代码:

- (void)layoutSubviews 
[super layoutSubviews];

if(_idEvent == 0) return;

_buttonFav = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 40, 40)];
[_buttonFav setImage:[UIImage imageNamed:@"fav.png"] forState:UIControlStateNormal];
[_buttonFav addTarget:self action:@selector(pressedFavButton:) forControlEvents:UIControlEventTouchDown];

_labelButton = [[UILabel alloc]initWithFrame:CGRectMake(0, 45, 0, 20)];
_labelButton.text = @"LABEL";

[self addSubview:_labelButton];
[self addSubview:_buttonFav];

在第二个动画之前调用。我的刷新方法是:

- (void)refresh 
if(selected)

    [_buttonFav setImage:[UIImage imageNamed:@"fav_sel.png"] forState:UIControlStateNormal];

else
    [_buttonFav setImage:[UIImage imageNamed:@"fav.png"] forState:UIControlStateNormal];

我只是根据让我知道按钮是否被点击的属性设置按钮的图像。

【问题讨论】:

只是为了确认:这个项目中没有使用自动布局? 我愿意,那么如何用自动布局制作动画呢?使用新的 XCode,您无法选择禁用它。 【参考方案1】:

我愿意,那么如何使用自动布局制作动画呢?随着新 XCode 你没有禁用它的选项。

为标签添加宽度约束。然后在你的实现文件中为这个约束创建IBOutlet(如果你不知道怎么做,请参阅the section 3. here),让我们这样说:

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

然后你可以这样动画它:

[UIView animateWithDuration:1.3 animations:^
    self.buttonWidthConstraint.constant = 140;
    [self.view layoutIfNeeded];
 completion:^(BOOL finished) 

    [UIView animateWithDuration:1.3 animations:^
        self.buttonWidthConstraint.constant = 0;
        [self.view layoutIfNeeded];
    ];

];

【讨论】:

我不相信这是一个自动布局问题,因为我试图将动画更改为“淡入”“淡出”动画和事件,尽管它确实淡出它不是动画,我认为这是因为在调用第二个布局之前调用了 LayoutSubview。我将向您展示 LayoutSubviews 的代码 这是一个自动布局问题。使用自动布局时不应手动设置框架。只是谷歌:自动布局更改框架。 Here's a video of how my code works(按钮标题隐藏,但这是另一个问题:))。 我会尝试,但我不是通过 Interface Builder 而是通过代码设置我的 UIView,如何通过代码设置 NSLayoutConstraint?感谢您的帮助 [NSLayoutConstraint constraintWithItem:self.label attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:40]; 我应该把这个放在哪里?我把它放在 LayoutSubviews labelConstraint = [NSLayoutConstraint constraintWithItem:_labelButton attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:40]; [自我添加约束:标签约束];添加后再次调用LayoutSubview,因此发生无限循环。【参考方案2】:

使用 SetTransform 和 CGAffineTransform

试试这个

[UIView animateWithDuration:1.3 animations:^

    [labelFav setTransform:CGAffineTransformMakeScale(0.5,0.5)];
 completion:^(BOOL finished) 

    [UIView animateWithDuration:1.3 animations:^

        [labelFav setTransform:CGAffineTransformMakeScale(1.0,1.0)];
    ];

];

【讨论】:

【参考方案3】:

尝试将 UILabel 封装到 UIView 中并为该视图设置动画。

UIView *auxView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 100.0)];
[auxView addSubview:labelFav];
[UIView animateWithDuration:1.3 animations:^
    CGRect frame = CGRectMake(50, 15, 140, 20);
    [auxView setFrame:frame];
 completion:^(BOOL finished) 
    //[labelFav setHidden:YES];
        [UIView animateWithDuration:1.3 animations:^
            CGRect frame = CGRectMake(50, 15, 10, 20);
            [auxView setFrame:frame];
        ];
];

【讨论】:

以上是关于使用动画创建自定义视图的主要内容,如果未能解决你的问题,请参考以下文章

创建自定义视图控制器动画

关闭自定义模式视图控制器

在自定义视图中制作 2 个动画

UICollectionViewCell 与自定义 UICollectionViewLayout 仅在一个子视图上创建视差动画

如何在 Swift 3 中加载/删除带有动画的自定义视图

自定义视图切换效果