安装: 在一个UIViewController
中,有一个屏幕上的containerView
(为简单起见,假设containerView
占据整个屏幕)。
问题: 创建并将overlayView
作为子视图添加到containerView
中,并动画地显示出来,以响应用户操作,使其从右侧动画进入位置。
UIView *overlayView = [[UIView alloc] initWithFrame:containerView.frame];
overlayView.translatesAutoresizingMaskIntoConstraints = NO;
[containerView addSubview:overlayView]; // Can't add constraints before inserting into view hierarchy
做法: 使用约束将overlayView
的前沿与containerView
的前沿绑定,并命名约束为overlayLeadingConstraint
。将overlayLeadingConstraint.constant
设置为containerView
的宽度,这样它最初就会被定位到右侧屏幕外。
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|[overlayView(width)]" options:0 metrics:metrics views:views];
[containerView addConstraints:constraints];
NSLayoutConstraint *overlayViewLeadingConstraint = [constraints objectAtIndex:0];
overlayViewLeadingConstraint.constant = containerView.frame.size.width;
// Height constraint not shown for simplicity
动画:现在进入真正的问题;从右侧将overlayView
动画地移到正确位置。第一种方法大概是这样的:
overlayViewLeadingConstraint.constant = 0.0;
[UIView animateWithDuration:1.0 animations:^{ [containerView layoutIfNeeded];
}];
但是这种方法行不通,因为以上所有代码都将在同一个运行循环中执行,所以只会显示最终结果。
第二种方法:尝试将动画延迟到未来的运行循环中,直到在addSubview:之后已经完成了初始布局。
dispatch_async(dispatch_get_main_queue(), ^{
overlayViewLeadingConstraint.constant = 0.0;
[UIView animateWithDuration:1.0 animations:^{
[containerView layoutIfNeeded];
}];
});
这也不起作用,它暗示着addSubview:
和约束设置可能会占用多个运行循环。
第三种方法:尝试将动画进一步延迟:几个运行循环之后再进行。
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
overlayViewLeadingConstraint.constant = 0.0;
[UIView animateWithDuration:1.0 animations:^{
[containerView layoutIfNeeded];
}];
}];
时间延迟很小,但它可以让几个运行循环在动画之前完成,从而实现所需的效果。
问题:
上述方法似乎是一个解决方法而不是真正的解决方案。所以我想知道是否有更好的方法。我考虑使用托管viewController
的viewDidLayoutSubviews
方法来了解何时放置overlayView
并启动动画,但文档明确建议不要这样做:
但是,调用此方法并不表示视图的子视图的各个布局已被调整。每个子视图负责调整自己的布局。
我开始认为苹果的想法是在初始化时添加所有子视图,并隐藏那些您不需要立即使用的子视图。因此,当到达动画子视图的时间时,它将已经成为具有约束的视图层次结构的成员。
你会怎么做呢?非常感谢任何意见。
layoutIfNeeded
是解决我的问题的关键。有趣的是,现在你已经展示了它,它变得非常合理,但我从未想过这样做。再次感谢! - kadamobjectAtIndex:
方法不安全的问题,你说得没错。但是视觉格式更能传达想法,所以为了例子的完整性,它更符合我的目的。不过在最终版本中我会替换掉视觉格式。 - kadam