我有两个视图,一个是UIImageView
,用于显示用户选择的照片,另一个是MKMapKitView
,用于显示用户选择的对象位置。在休息时,视图的排列如下:
当用户点击视图2时,我希望两者改变位置。反之亦然。两个视图都有约束条件。所以我可以做一个动画,我首先获取两组约束,然后清除它们,然后按翻转顺序应用它们,但是z顺序不会切换。无论哪种观点都在"小"模式应该远远超过另一个。
我真的希望能够设置它的动画,以便交换显而易见。不知何故,通过执行以下操作使其显示为旋转:
实现这一目标的最简单方法是什么?我尝试了以下方法:
- (IBAction)swapPreview {
NSArray *photoConstraints = self.photoView.constraints;
NSArray *mapConstraints = self.mapView.constraints;
[self.photoView removeConstraints: photoConstraints];
[self.mapView removeConstraints: mapConstraints];
NSLog(@"photoConstraints %@", photoConstraints);
NSLog(@"mapConstraints %@", mapConstraints);
CGRect biggerFrame = CGRectUnion(self.photoView.frame, self.mapView.frame);
CGRect upperFrame = CGRectOffset(RectCenterScaled(biggerFrame, 0.5), 0, biggerFrame.size.height / -4);
CGRect lowerFrame = CGRectOffset(upperFrame, 0, upperFrame.size.height);
[UIView animateWithDuration: 0.4 delay: 0 options: UIViewAnimationOptionCurveLinear animations:^{
self.photoView.frame = upperFrame;
self.mapView.frame = lowerFrame;
} completion:^(BOOL finished) {
UIView *container = self.photoView.superview;
[self.photoView addConstraints: mapConstraints];
[self.mapView addConstraints: photoConstraints];
[container exchangeSubviewAtIndex: [container.subviews indexOfObject: self.photoView] withSubviewAtIndex:[container.subviews indexOfObject: self.mapView]];
[UIView animateWithDuration: 0.4 delay: 0 options: UIViewAnimationOptionCurveLinear animations:^{
[container updateConstraints];
} completion:^(BOOL finished) {
}];
}];
}
但是当我尝试交换约束时,这会破坏第二个动画块。那么更好的方法是什么?我可以遍历视图层次结构中的所有约束,交换任何引用这两个视图的firstItem / secondItems。但是较小视图的局部约束需要改变局部性。
我开始怀疑自己是不是应该制作一个有两个孩子的自定义UIView子类并直接进行布局,而不是搞乱约束。
答案 0 :(得分:1)
我制作了符合你想要的测试项目和课程:
@interface ViewController ()
//initial constants values
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *view1Top;//0
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *view2Top;//20
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *view1Left;//0
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *view2Left;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *view1Height;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *view2Height;//100
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *view1Width;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *view2Width;//50
@property (weak, nonatomic) IBOutlet UIView *view1;
@property (weak, nonatomic) IBOutlet UIView *view2;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewWillAppear:(BOOL)animated{
//setting initial values for constraints related to view size
self.view1Width.constant = self.self.view.frame.size.width;
self.view1Height.constant = self.self.view.frame.size.height;
self.view2Left.constant = self.view.frame.size.width - 20 - self.view2Width.constant;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)animate:(id)sender {
CGFloat gap = 20.0;
CGFloat height = (self.view.frame.size.height - 3*gap)/2; //height of views in the middle of animation
CGFloat width = self.view.frame.size.width - 40; //width of views in the middle of animation
self.view1Top.constant = gap;
self.view1Height.constant = height;
self.view2Top.constant = height + 2*gap;
self.view2Height.constant = height;
self.view1Left.constant = self.view2Left.constant = gap;
self.view1Width.constant = self.view2Width.constant = width;
[UIView animateWithDuration:4.0 delay:0 options:0 animations:^{
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
[self.view exchangeSubviewAtIndex: [self.view.subviews indexOfObject: self.view1] withSubviewAtIndex:[self.view.subviews indexOfObject: self.view2]];
self.view2Top.constant = 0;
self.view2Left.constant = 0;
self.view2Height.constant = self.view.frame.size.height;
self.view2Width.constant = self.view.frame.size.width;
self.view1Top.constant = gap;
self.view1Width.constant = 50;
self.view1Height.constant = 100;
self.view1Left.constant = self.view.frame.size.width - self.view1Width.constant - gap;
[UIView animateWithDuration:4.0 animations:^{
[self.view layoutIfNeeded];
}];
}];
}
@end
view1 是红色视图, view2 是蓝色视图。
animate 是我的案例中由按钮点按启动的一个动作。
关键不是仅仅为动画常量属性移除约束。
答案 1 :(得分:0)
UIView
提供以下内容:
- (void)bringSubviewToFront:(UIView *)view;
- (void)sendSubviewToBack:(UIView *)view;
控制视图的Z顺序。
使用其中一个动画的完成块。这样做的好时机是观点不重叠。