具有边界限制和动画的平移手势
Pan gesture with boundaries limits & animations
根据此答案实施此代码时:
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 达到其边界时,它不能只是 "stop"。
示例:
假设可以将 TextField 拖动到相对于根视图的每个方向大约 10%。手指离 TextField 越近,TextField 的 "freedom" 越多。当将文本字段移动到非常靠近其原始位置时,TextField 应该移动得比手指远离 TextFields 原始位置时移动得更多。因此,当手指移动到最右上角并按住 TextField 时(假设 TextField 在中间居中),TextField 仍然有响应,但移动得很少。当手指松开 TextField 时,它应该弹回到原来的位置。
希望大家能理解我。如果没有,我也许可以提供另一个例子。谢谢。
编辑:
就像拉松紧带一样。一开始拖动很顺利,但是你越是拉动或拖动到边界,TextField 正在移动,但速度很慢。我添加了一张图片。也许我说的听起来很难理解,但它确实很简单...Click Here(图 1 显示 TextField 可以在每个方向移动 10%。)
好的,所以你想使用手势识别器的翻译,而不是位置,否则如果用户没有"grab"中间的视图,你会跳转:
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 .)
如果你能更好地定义你希望这条曲线如何工作,也许我能提供更多帮助?
根据此答案实施此代码时:
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 达到其边界时,它不能只是 "stop"。
示例: 假设可以将 TextField 拖动到相对于根视图的每个方向大约 10%。手指离 TextField 越近,TextField 的 "freedom" 越多。当将文本字段移动到非常靠近其原始位置时,TextField 应该移动得比手指远离 TextFields 原始位置时移动得更多。因此,当手指移动到最右上角并按住 TextField 时(假设 TextField 在中间居中),TextField 仍然有响应,但移动得很少。当手指松开 TextField 时,它应该弹回到原来的位置。
希望大家能理解我。如果没有,我也许可以提供另一个例子。谢谢。
编辑:
就像拉松紧带一样。一开始拖动很顺利,但是你越是拉动或拖动到边界,TextField 正在移动,但速度很慢。我添加了一张图片。也许我说的听起来很难理解,但它确实很简单...Click Here(图 1 显示 TextField 可以在每个方向移动 10%。)
好的,所以你想使用手势识别器的翻译,而不是位置,否则如果用户没有"grab"中间的视图,你会跳转:
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 .)
如果你能更好地定义你希望这条曲线如何工作,也许我能提供更多帮助?