顺便说一句,我注意到您在问题结束时提出了第二个问题,即如何将图像视图拖出容器。
假设您已按照问题中的建议完成了约束,并且瓷砖位于以主视图为中心的容器视图中(请参阅我的其他答案的选项 1)。您可能会编写一个手势识别器处理程序,当您开始拖动时,它会从容器的列表中删除磁贴,tiles
然后相应地为约束的更新设置动画:
- (void)handlePan:(UIPanGestureRecognizer *)gesture
{
static CGPoint originalCenter;
if (gesture.state == UIGestureRecognizerStateBegan)
{
// move the gesture.view out of its container, and up to the self.view, so that as the container
// resizes, this view we're dragging doesn't move in the process, too
originalCenter = [self.view convertPoint:gesture.view.center fromView:gesture.view.superview];
[self.view addSubview:gesture.view];
gesture.view.center = originalCenter;
// now update the constraints for the views still left in the container
[self removeContainerTileConstraints];
[self.tiles removeObject:gesture.view];
[self createContainerTileConstraints];
[UIView animateWithDuration:0.5 animations:^{
[self.containerView layoutIfNeeded];
}];
}
CGPoint translate = [gesture translationInView:gesture.view];
gesture.view.center = CGPointMake(originalCenter.x + translate.x, originalCenter.y + translate.y);
if (gesture.state == UIGestureRecognizerStateEnded)
{
// do whatever you want when you drop your tile, presumably changing
// the superview of the tile to be whatever view you dropped it on
// and then adding whatever constraints you need to make sure it's
// placed in the right location.
}
}
这将优雅地为磁贴(以及不可见的容器视图)设置动画,以反映您将磁贴拖出容器。
就上下文而言,我将向您展示我是如何创建容器和与上述手势识别器处理程序一起使用的图块。假设您的容器内有一个NSMutableArray
名为的拼字游戏风格的瓷砖。tiles
然后,您可以创建容器、磁贴,并将手势识别器附加到每个磁贴,如下所示:
// create the container
UIView *containerView = [[UIView alloc] init];
containerView.backgroundColor = [UIColor lightGrayColor];
containerView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:containerView];
self.containerView = containerView; // save this for future reference
// center the container (change this to place it whereever you want it)
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:containerView
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:containerView.superview
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:containerView
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:containerView.superview
attribute:NSLayoutAttributeCenterY
multiplier:1.0
constant:0]];
// create the tiles (in my case, three random images), populating an array of `tiles` that
// will specify which tiles the container will have constraints added
self.tiles = [NSMutableArray array];
NSArray *imageNames = @[@"1.png", @"2.png", @"3.png"];
for (NSString *imageName in imageNames)
{
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:imageName]];
imageView.translatesAutoresizingMaskIntoConstraints = NO;
[containerView addSubview:imageView];
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
[imageView addGestureRecognizer:pan];
imageView.userInteractionEnabled = YES;
[self.tiles addObject:imageView];
}
// add the tile constraints
[self createContainerTileConstraints];
你显然需要这些实用方法:
- (void)removeContainerTileConstraints
{
NSMutableArray *constraintsToRemove = [NSMutableArray array];
// build an array of constraints associated with the tiles
for (NSLayoutConstraint *constraint in self.containerView.constraints)
{
if ([self.tiles indexOfObject:constraint.firstItem] != NSNotFound ||
[self.tiles indexOfObject:constraint.secondItem] != NSNotFound)
{
[constraintsToRemove addObject:constraint];
}
}
// now remove them
[self.containerView removeConstraints:constraintsToRemove];
}
- (void)createContainerTileConstraints
{
[self.tiles enumerateObjectsUsingBlock:^(UIView *tile, NSUInteger idx, BOOL *stop) {
// set leading constraint
if (idx == 0)
{
// if first tile, set the leading constraint to its superview
[tile.superview addConstraint:[NSLayoutConstraint constraintWithItem:tile
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:tile.superview
attribute:NSLayoutAttributeLeading
multiplier:1.0
constant:0.0]];
}
else
{
// if not first tile, set the leading constraint to the prior tile
[tile.superview addConstraint:[NSLayoutConstraint constraintWithItem:tile
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:self.tiles[idx - 1]
attribute:NSLayoutAttributeTrailing
multiplier:1.0
constant:10.0]];
}
// set vertical constraints
NSDictionary *views = NSDictionaryOfVariableBindings(tile);
[tile.superview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[tile]|" options:0 metrics:nil views:views]];
}];
// set the last tile's trailing constraint to its superview
UIView *tile = [self.tiles lastObject];
[tile.superview addConstraint:[NSLayoutConstraint constraintWithItem:tile
attribute:NSLayoutAttributeTrailing
relatedBy:NSLayoutRelationEqual
toItem:tile.superview
attribute:NSLayoutAttributeTrailing
multiplier:1.0
constant:0.0]];
}