本节书摘来自异步社区《iOS 6核心开发手册(第4版)》一书中的第1章,第1.3节秘诀:添加平移姿势识别器,作者 【美】Erica Sadun,更多章节内容可以访问云栖社区“异步社区”公众号查看
1.3 秘诀:添加平移姿势识别器
iOS 6核心开发手册(第4版)
利用姿势识别器,可以实现秘诀1-1中所示的相同类型的交互,但是不会如此直接地使用触摸处理程序。平移姿势识别器将会检测拖动姿势,无论何时iOS感觉到平移,它们都允许指定一个要触发的回调。
秘诀1-2模仿了秘诀1-1的行为,当视图第一次初始化时给它添加一个识别器。当iOS检测到用户在DragView实例上拖动时,handlePan:回调将更新视图的中心,以匹配拖动的距离。
这段代码使用一种似乎很怪异的方式计算距离。它在一个实例变量(previousLocation)中存储原始的视图位置,然后每次视图利用平移检测回调进行更新时都会计算距离那个位置的偏移量。这允许使用仿射变换或者应用setTranslation:inView:方法;你通常不会移动视图的中心,就像这里所做的那样。这个秘诀创建一个dx/dy偏移量对,并把该偏移量应用于视图的中心,改变视图的实际框架。
与简单的偏移量不同,仿射变换允许有意义地同时处理旋转、缩放和平移。为了支持变换,姿势识别器提供了坐标值的绝对变化,而不是相对变化。UIPanGestureRecognizer不会发送迭代式的偏移矢量,而是返回单独一个矢量,表示相对于某个视图的坐标系统的平移,该坐标系统通常是所操作的视图的父视图的坐标系统。这种矢量平移使自身适合于简单的仿射变换计算,并且可以在数学上与其他变化结合起来,以产生一种统一的变换,表示同时应用的所有改变。
下面显示了handlePan:方法,它使用直接变换,并且没有存储的状态。
- (void) handlePan: (UIPanGestureRecognizer *) uigr
{
if (uigr.state == UIGestureRecognizerStateEnded)
{
CGPoint newCenter = CGPointMake(
self.center.x + self.transform.tx,
self.center.y + self.transform.ty);
self.center = newCenter;
CGAffineTransform theTransform = self.transform;
theTransform.tx = 0.0f;
theTransform.ty = 0.0f;
self.transform = theTransform;
return;
}
CGPoint translation = [uigr translationInView:self.superview];
CGAffineTransform theTransform = self.transform;
theTransform.tx = translation.x;
theTransform.ty = translation.y;
self.transform = theTransform;
}
注意识别器如何检查交互的结束,然后更新视图的位置,并且重置变换的平移。这种修改无须本地存储,并将消除对touchesBegan:withEvent:方法的需要。如果没有这些修改,秘诀1-2将不得不存储以前的状态。