ところで、質問の最後に 2 番目の質問、つまりコンテナーから画像ビューをドラッグする方法を尋ねたことに気付きました。
質問で提案したように、メイン ビューの中心にあるコンテナー ビューにタイルを配置して、制約を実行したと仮定しましょう (他の回答のオプション 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]];
}