稍后添加子视图以与superview一起制作动画

时间:2015-10-28 19:01:23

标签: ios uiview calayer uiviewanimation

我有一个容器视图 - 我们称之为套接字视图 - 它有一个子视图,它是内容视图 - 让我们称之为插件视图。该插件视图可以是nil,即套接字视图当前是空的。如果它确实包含一个插件视图,它将占用整个套接字的空间,即它的框架是套接字的边界。从外观来看,你甚至不应该知道实际上有两个视图,因为插件视图总是与套接字完全一致。

我正在努力让动画正常工作:如果插件视图存在并且在动画之前布局,一切都按预期工作。但是,如果仅在动画已经运行时设置套接字的插件视图,则会产生不良影响:

插件视图布局到动画结束时的位置,并且不会在其插槽旁边进行动画处理。我希望它看起来像是一直存在但只是刚才可见,即插件视图(及其子视图)应该在套接字旁边动画,即使我在动画进行过程中添加它。

我该如何实现这种行为?

我的想法:显然,插件视图必须布置两次:一次用于最终位置,再一次用于套接字视图开始动画或添加位置的位置。我可以计算这个帧,在没有动画的情况下应用它,并在新的动画块中动画到最终帧。为了使动画定时保持一致,我需要具有相同的曲线和持续时间,但过去开始动画或以某种方式转发动画。这可能吗?是否有其他方法让插件视图始终为全宽

作为Rob回答的后续内容,以下是我正在寻找的更多细节:

  • 套接字视图是动画的,因为它的所有者的绑定大小已更改。您可以将其视为表格视图中的全宽度单元格。

  • 插件视图可能包含其自身的子视图,如图像视图,标签等。这些也应该加入到套接字视图的动画中,就像动画开始以来它们一直存在一样。

  • 虽然理论上可以在已经运行的情况下启动新动画,但我并不介意此边缘情况下的行为。

  • 在动画运行时,用户无需与插件视图进行交互。无论如何,最有可能在接口方向更改期间发生这种情况。

  • 插件视图可能决定在动画时由于异步模型更新而更改其内容,但这又是一个边缘情况,我不介意动画在这种情况下看起来不完美。但是,它的大小不会改变 - 它总是与插件视图的大小相同。

2 个答案:

答案 0 :(得分:1)

我用这种方式修改了Rob mayoff代码。这对你有帮助吗?

重要的变化是实际使用CADisplayLink来更新plugView的框架,我添加了一个带有插件约束的子视图。还改变了添加plugView并更新其框架的方式。

检查一下这是否适用于你。您应该能够在项目中替换此代码而不会出现任何问题。

#import "ViewController.h"

@interface UIView (recursiveDescription)
- (NSString *)recursiveDescription;
@end

@interface ViewController ()

@property (strong, nonatomic) IBOutlet NSLayoutConstraint *socketWidthConstraint;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *socketHeightConstraint;
@property (strong, nonatomic) IBOutlet UIView *socketView;
@property (strong, nonatomic) IBOutlet UIImageView *plugView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    UIView *extraView = [[UIView alloc] init];
    extraView.translatesAutoresizingMaskIntoConstraints = NO;
    extraView.backgroundColor = [UIColor blackColor];
    [self.plugView addSubview:extraView];
    NSLayoutConstraint *c1 = [NSLayoutConstraint constraintWithItem:extraView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.plugView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
    NSLayoutConstraint *c2 = [NSLayoutConstraint constraintWithItem:extraView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.plugView attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0];
    NSLayoutConstraint *c3 = [NSLayoutConstraint constraintWithItem:extraView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.plugView attribute:NSLayoutAttributeWidth multiplier:0.5 constant:0];
    NSLayoutConstraint *c4 = [NSLayoutConstraint constraintWithItem:extraView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.plugView attribute:NSLayoutAttributeHeight multiplier:0.5 constant:0];
    [self.plugView addConstraints:@[c1, c2, c3, c4]];

}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkDidFire:)];
    [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}

- (void)displayLinkDidFire:(CADisplayLink *)link {
    CGSize size = [self.socketView.layer.presentationLayer frame].size;
    self.plugView.frame = CGRectMake(0, 0, size.width, size.height);
    [self.plugView layoutIfNeeded];
}

- (IBAction)plugWasTapped:(id)sender {
    if (self.plugView.superview) {
        [self.plugView removeFromSuperview];
        return;
    }

    CGSize size = [self.socketView.layer.presentationLayer frame].size;
    self.plugView.frame = CGRectMake(0, 0, size.width, size.height);
    [self.socketView addSubview:self.plugView];
}
- (IBAction)bigButtonWasTapped:(id)sender {
    [UIView animateWithDuration:10 animations:^{
        self.socketWidthConstraint.constant = 320;
        self.socketHeightConstraint.constant = 320;
        [self.view layoutIfNeeded];
    }];
}

- (IBAction)smallButtonWasTapped:(id)sender {
    [UIView animateWithDuration:5 animations:^{
        self.socketWidthConstraint.constant = 160;
        self.socketHeightConstraint.constant = 160;
        [self.view layoutIfNeeded];
    }];
}


@end

答案 1 :(得分:0)

为什么不让插件视图始终作为套接字视图的子视图存在,而是设置hidden = YES?或者您可以使用alpha = 0。然后,当您想要显示它时,只需将其设置为隐藏= hidden = NOalpha = 1

通过这种方式,您的插件视图将始终伴随着#34;当您为套接字视图设置动画时。

顺便说一下,你的术语让我们这些使用TCP套接字的人迷惑了。 ("插座?什么?")