我试图在我的ViewController中有一个可拖动的UIView,最终这个UIView将成为一个可点击的按钮但是现在,当它被拖动到屏幕上时,我仍然坚持更新该视图的约束。代码如下。
- (void)viewDidLoad
{
[super viewDidLoad];
self.anotherView = [[UIView alloc]init];
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(dragging:)];
[self.anotherView addGestureRecognizer:panRecognizer];
[self.anotherView setBackgroundColor: [UIColor blueColor]];
self.anotherView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview: self.anotherView];
[self.view bringSubviewToFront:self.anotherView];
NSDictionary *views = @{@"subview" : self.anotherView, @"superview" : self.view};
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.anotherView
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationLessThanOrEqual
toItem:self.view
attribute:NSLayoutAttributeLeft
multiplier:1.0
constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.anotherView
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationLessThanOrEqual
toItem:self.view
attribute:NSLayoutAttributeCenterY
multiplier:1.0
constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.anotherView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:Nil
attribute:NSLayoutAttributeWidth
multiplier:1.0
constant:20]];
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"V:[subview(40)]"
options:0
metrics:nil
views:views]];
// add horizontal constraints
/*[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[subview(==20)]|" options:0 metrics:nil views:views]];
// set the height of the offscreen subview to be the same as its superview
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[subview(==40)]" options:0 metrics:nil views:views]];
// set the location of the subview to be just off screen below the current view
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self.anotherView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationLessThanOrEqual toItem:self.view attribute:NSLayoutAttributeHeight multiplier:1.0 constant:self.view.bounds.size.height];
[self.view addConstraint:constraint];*/
//[self.anotherView pinEdges:JRTViewPinLeftEdge toSameEdgesOfView:self.view];
// Do any additional setup after loading the view, typically from a nib.
self.navigationItem.leftBarButtonItem = self.editButtonItem;
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(insertNewObject:)];
self.navigationItem.rightBarButtonItem = addButton;
self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
}
以上代码是我在ViewController中设置UIView的方法。预计尺寸为20x45。拖动代码如下:
-(void)dragging:(UIPanGestureRecognizer *)gesture
{
if(gesture.state == UIGestureRecognizerStateBegan)
{
//NSLog(@"Received a pan gesture");
self.panCoord = [gesture locationInView:gesture.view];
[self.tableView setScrollEnabled:NO];
}
CGPoint newCoord = [gesture locationInView:gesture.view];
float dX = newCoord.x-self.panCoord.x;
float dY = newCoord.y-self.panCoord.y;
CGFloat newXPoint;
CGFloat newYPoint;
gesture.view.frame = CGRectMake(gesture.view.frame.origin.x+dX, gesture.view.frame.origin.y+dY, gesture.view.frame.size.width, gesture.view.frame.size.height);
if (gesture.state == UIGestureRecognizerStateEnded) {
newYPoint = gesture.view.frame.origin.y+dY;
if (gesture.view.frame.origin.x+dX<(self.view.frame.size.width/2)) {
newXPoint = 0;
}
else {
newXPoint = self.view.frame.size.width - gesture.view.frame.size.width;
//The below is just an attempt to remove and re-add constraints so the view will stick to the right side of the screen. It is not working :(
[self.view removeConstraint:[NSLayoutConstraint constraintWithItem:self.anotherView
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationLessThanOrEqual
toItem:self.view
attribute:NSLayoutAttributeLeft
multiplier:1.0
constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.anotherView
attribute:NSLayoutAttributeRight
relatedBy:NSLayoutRelationLessThanOrEqual
toItem:self.view
attribute:NSLayoutAttributeRight
multiplier:1.0
constant:0]];
}
// self.draggedViewCoordinate = gesture.view.frame.origin;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.70];
[UIView setAnimationDelay:0.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[self.anotherView layoutIfNeeded];
[UIView commitAnimations];
[self.tableView setScrollEnabled:YES];
}
}
我没有得到如何更新约束,因此视图将坚持新的拖动位置。任何人都可以帮忙吗?
答案 0 :(得分:9)
接受的答案不正确。 UI添加/删除约束的操作非常昂贵。 正确的解决方案将会改变
self.yCoordinate.constant
和
self.xCoordinate.constant
基于dX和dY的属性。
答案 1 :(得分:2)
好的,我用下面的代码解决了它!
-(void)dragging:(UIPanGestureRecognizer *)gesture
{
if(gesture.state == UIGestureRecognizerStateBegan)
{
//NSLog(@"Received a pan gesture");
self.panCoord = [gesture locationInView:gesture.view];
[self.tableView setScrollEnabled:NO];
}
CGPoint newCoord = [gesture locationInView:gesture.view];
float dX = newCoord.x-self.panCoord.x;
float dY = newCoord.y-self.panCoord.y;
CGFloat newXPoint;
CGFloat newYPoint;
gesture.view.frame = CGRectMake(gesture.view.frame.origin.x+dX, gesture.view.frame.origin.y+dY, gesture.view.frame.size.width, gesture.view.frame.size.height);
if (gesture.state == UIGestureRecognizerStateEnded) {
newYPoint = gesture.view.frame.origin.y+dY;
CGFloat newYPosition = (self.view.frame.size.height/2) - newYPoint - 20;
if (gesture.view.frame.origin.x+dX<(self.view.frame.size.width/2)) {
[self.view removeConstraint:self.xCoordinate];
[self.view removeConstraint:self.yCoordinate];
self.xCoordinate = [NSLayoutConstraint constraintWithItem:self.anotherView
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationLessThanOrEqual
toItem:self.view
attribute:NSLayoutAttributeLeft
multiplier:1.0
constant:0];
[self.view addConstraint:self.xCoordinate];
self.anotherView.translatesAutoresizingMaskIntoConstraints = NO;
self.yCoordinate = [NSLayoutConstraint constraintWithItem:self.anotherView
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterY
multiplier:1.0
constant:-newYPosition];
[self.view addConstraint:self.yCoordinate];
}
else {
newXPoint = self.view.frame.size.width - gesture.view.frame.size.width;
[self.view removeConstraint:self.xCoordinate];
[self.view removeConstraint:self.yCoordinate];
self.xCoordinate = [NSLayoutConstraint constraintWithItem:self.anotherView
attribute:NSLayoutAttributeRight
relatedBy:NSLayoutRelationLessThanOrEqual
toItem:self.view
attribute:NSLayoutAttributeRight
multiplier:1.0
constant:0];
[self.view addConstraint:self.xCoordinate];
self.anotherView.translatesAutoresizingMaskIntoConstraints = NO;
self.yCoordinate = [NSLayoutConstraint constraintWithItem:self.anotherView
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterY
multiplier:1.0
constant:-newYPosition];
[self.view addConstraint:self.yCoordinate];
}
// self.draggedViewCoordinate = gesture.view.frame.origin;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.70];
[UIView setAnimationDelay:0.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[self.anotherView layoutIfNeeded];
// gesture.view.frame = CGRectMake(newXPoint, newYPoint, gesture.view.frame.size.width, gesture.view.frame.size.height);
[UIView commitAnimations];
[self.tableView setScrollEnabled:YES];
}
}
基本上,我保留了对约束的引用。这有助于我根据拖动视图的位置删除/重新添加约束。
答案 2 :(得分:1)
这个简化版本在向下和向下拖动时为我解决了:
@implementation SomeController
{
float beginDragPointY;
NSLayoutConstraint someConstraint;
}
- (void) viewDidLoad
{
// Define someConstraint
}
- (void) onDragGesture: (id) sender
{
UIPanGestureRecognizer* recognizer = (UIPanGestureRecognizer*)sender;
UIGestureRecognizerState state = recognizer.state;
CGPoint translation = [sender translationInView:self.view];
switch(state)
{
case UIGestureRecognizerStateBegan:
NSLog(@"Translation began %f %f", translation.x, translation.y);
beginDragPointY = translation.y;
break;
case UIGestureRecognizerStateChanged:
showBasicEventAnnotationConstraint.constant += translation.y - beginDragPointY;
beginDragPointY = translation.y;
[self.view setNeedsLayout];
break;
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateCancelled:
case UIGestureRecognizerStateFailed:
case UIGestureRecognizerStatePossible:
default:
break;
}
[self.view layoutIfNeeded];
}