制作一个可拖动的UIView,可以捕捉iOS中的边缘

时间:2014-06-07 12:44:22

标签: ios uiview draggable

我正在尝试制作一个可以在屏幕上拖动的UIView,并且当释放时会捕捉到最近的边缘。

我已经整理了拖动 - 我正在使用UILongPressGestureRecognizer,当状态结束时,我正在调用以下方法,其中point是longPressGestureRecognizer的locationInView,而rect是包含gesturerecognizer和的姿势的UIView。可拖动的UIView。这个方法返回一个CGPoint,然后我将其设置为可拖动的UIView的中心。

- (CGPoint)closestPointForPoint:(CGPoint)point toSnapToInRect:(CGRect)rect {

CGPoint closestPoint = point;

/// Left/Right

if ((point.x - rect.origin.x) > (rect.size.width - point.x)) {

    /// Point is closer to right side of frame, update the closestPoint's x.

    closestPoint.x = rect.size.width - (self.draggableView.frame.size.width / 2) - draggableViewMargin;
}
else {
    /// Point is closer to left side of frame, update the closestPoint's x.
    closestPoint.x = rect.origin.x + (self.draggableView.frame.size.width / 2) + draggableViewMargin;
}


/// Top/Bottom

if ((point.y - rect.origin.y) > (rect.size.height - point.y)) {
    /// Point is closer to top of frame, update the closestPoint's y.

    closestPoint.y = rect.size.height - (self.draggableView.frame.size.height / 2) - draggableViewMargin;
}
else {

    /// Point is closer to bottom of frame, update the closestPoint's y.
    closestPoint.y = rect.origin.y + (self.draggableView.frame.size.height / 2) + draggableViewMargin;

}

return closestPoint;

}

除了当我放开视图时,它会捕捉到最近的角落。这很好,但不是我想要的。我希望它能够捕捉到最近的边缘,所以例如如果我放开视图时它的点是x:50 y:100(在1136 x 640的超视图中)我希望它对齐到左侧(如x值较小但是向下100像素而不是角落。

有人可以告诉我该怎么做吗?

由于

3 个答案:

答案 0 :(得分:3)

您的问题是您并查找是向左或向右捕捉以及是向上还是向下捕捉。您正在寻找的是一种算法,可以决定对齐,向左,向上或向下捕捉。

这是我的解决方案:

//put all of the distances between the point and rect edges in an array.
NSArray *values = @[@(point.x - rect.origin.x), @(rect.size.width - point.x), @(point.y - rect.origin.y), @(rect.size.height - point.y)];

//Find the smallest distance.
NSNumber *minimumValue = [NSNumber numberWithInteger:NSIntegerMax];
for(NSNumber *value in values){
    if([value intValue] < [minimumValue intValue]){
        minimumValue = value;
    }
}

if([minimumValue intValue] == point.x - rect.origin.x){
    //snap to the left
}
if([minimumValue intValue] == rect.size.width - point.x){
    //snap to the right
}
if([minimumValue intValue] == point.y - rect.origin.y){
    //snap to the top
}
if([minimumValue intValue] == rect.size.height - point.y){
    //snap to the bottom
}

它将所有值(上边距,右边距......)放在一个数组中,并迭代查找最小值。您可以编写if语句的实现。我已经为你评论了每个人。我希望这能够帮到你。

修改:

我已更新代码并修复了一些错误。当我测试它时,它对我有用。

答案 1 :(得分:1)

您应该尝试仅针对一个方向应用捕捉,x或y;也许这样的事情可以奏效:

- (CGPoint)closestPointForPoint:(CGPoint)point toSnapToInRect:(CGRect)rect {

CGPoint closestPoint = point;

/// Left/Right

if (MIN(point.x - rect.origin.x, rect.size.width - point.x) < MIN(point.y - rect.origin.y, rect.size.height - point.y)) {

  if ((point.x - rect.origin.x) > (rect.size.width - point.x)) {

    /// Point is closer to right side of frame, update the closestPoint's x.

    closestPoint.x = rect.size.width - (self.draggableView.frame.size.width / 2) - draggableViewMargin;
  }
  else {
    /// Point is closer to left side of frame, update the closestPoint's x.
    closestPoint.x = rect.origin.x + (self.draggableView.frame.size.width / 2) + draggableViewMargin;
  }

} else {
/// Top/Bottom

  if ((point.y - rect.origin.y) > (rect.size.height - point.y)) {
    /// Point is closer to top of frame, update the closestPoint's y.

    closestPoint.y = rect.size.height - (self.draggableView.frame.size.height / 2) - draggableViewMargin;
  }
  else {

    /// Point is closer to bottom of frame, update the closestPoint's y.
    closestPoint.y = rect.origin.y + (self.draggableView.frame.size.height / 2) + draggableViewMargin;

  }
}

return closestPoint;
}

答案 2 :(得分:1)

这个答案对我不起作用,也许我会混淆rectpoint

我有另一个解决方案,它不需要循环,只需要一些方程式检查。

  1. 首先,将屏幕划分为四个区域。由于缺乏声誉,我现在无法发布图片,脚本文件在这里:http://i.stack.imgur.com/40Mos.jpg

  2. 然后,记下尺寸坐标系中线条的公式

  3. 最后,列出每个区域的方程式,现在你可以用方程式x y替换方程式中的x y。

    CGPoint endPoint = [recognizer locationInView:self.view];
    CGFloat k = self.view.bounds.size.height / self.view.bounds.size.width;
    CGFloat b = self.view.bounds.size.height;
    
    if (endPoint.y < k * endPoint.x && endPoint.y < -1 * k * endPoint.x + b) {
        NSLog(@"top edge");
    } else if (endPoint.y <= k * endPoint.x && endPoint.y >= -1 * k * endPoint.x + b) {
        NSLog(@"right edge");
    } else if (endPoint.y > k * endPoint.x && endPoint.y > -1 * k * endPoint.x + b) {
        NSLog(@"bottom edge");
    } else if (endPoint.y > k * endPoint.x && endPoint.y < -1 * k * endPoint.x + b) {
        NSLog(@"left edge");
    }