泛手势与边界限制&动画

时间:2017-03-15 13:43:11

标签: ios iphone uitextfield uigesturerecognizer

从此答案实施此代码时:https://stackoverflow.com/a/31487087

override func viewDidLoad() {
    super.viewDidLoad()


    var gesture = UIPanGestureRecognizer(target: self, action: Selector("userDragged:"))
    bottomTextField.addGestureRecognizer(gesture)
    bottomTextField.userInteractionEnabled = true
}

func userDragged(gesture: UIPanGestureRecognizer){
    var loc = gesture.locationInView(self.view)
    self.bottomTextField.center = loc

}

可以在该区域拖动TextField。但是我想要更多的东西。首先,我想为可以拖动TextField的区域设置边界,因此无法在整个视图中拖动TextField。其次它应该有一个很好的动画。对于用户体验,它不能只是停止"当TextField达到他的界限时。

实施例: 让我们说TextField可以相对于根视图向每个方向拖动10%左右。手指离TextField越近,自由度越高" TextField有。当文本字段移动到非常接近其原始位置时,TextField应该比手指远离TextFields原件位置移动更多。因此,当手指向右上方移动时,按住TextField(假设TextField位于中间),TextField仍然会响应,但移动很少。当手指释放TextField时,它应该弹回原来的位置。

我希望你们能理解我。如果不是,我可以提供另一个例子。谢谢。

编辑:

它就像拉一个弹性。在开始时拖动变得平滑,但是你越是拉动或拖动到边界,TextField IS移动,但非常慢。我添加了一张图片。也许我觉得它听起来很难理解,但它确实很简单... Click Here(图1显示TextField每个方向可以达到10%。)

1 个答案:

答案 0 :(得分:2)

好的,所以你想要使用手势识别器的翻译,而不是位置,否则你会得到一个跳跃,如果用户没有"抓住"中间的观点:

var startPosition: CGPoint?
func userDragged(gesture: UIPanGestureRecognizer){
    if gesture.state == .began {
        startPosition = bottomTextField.center
    } else if gesture.state == .changed {
        let translation = gesture.translationInView(self.view)
        guard let start = self.startPosition else { return }
        let newCenter = CGPoint(x: start.x + translation.x, y: x.y + translation.y)
        bottomTextField.center = newCenter
    } else {
        startPosition = nil
    }
}

这应该解决第一个问题,视图在手势开始时跳到手指。

然后,您希望仔细查看let newCenter = CGPoint(x: start.x + translation.x, y: x.y + translation.y),以便对拖动视图的位置应用一些限制。

假设您不希望视图在任何方向上可拖动超过50pts(或超视图大小的10%),您只需使用:

let newCenter = CGPoint(x: start.x + min(translation.x, 50), y: x.y + min(translation.y, 50))

其中只检查哪个更小,平移或值为50,并使用两者中较小的一个。 [注意:这为您提供了一个围绕起点的方形极限,而不是径向极限]

然后你想看看这个变得有点复杂,让改变的距离成为翻译的一个函数,这样你就可以在接近极限时逐渐减少运动:

let normX = max(min(translation.x / 150, 1), -1)
let deltaX = 50 * sin(normX) // add custom function here
let normY = max(min(translation.y / 150, 1), -1)
let deltaY = 50 * sin(normY) // add custom function here
let newCenter = CGPoint(x: start.x + min(deltaX, 50), y: x.y + min(deltaY, 50))

这不是你想要使用的变换,但是表明如何实现改变翻译的效果而不仅仅是线性移动视图,你将希望在你自己的翻译功能中产生基于增量的增量在你想要的任何弹性曲线上......

(提供的函数将在150pts的拖动距离上对1和-1之间的平移进行归一化,然后将其映射到正弦曲线上以逐渐减小用于移动视图的增量,将最大增量限制为50pts。)

如果你能更好地定义你希望这条曲线如何工作,或许我可以提供更多帮助?