Swift 如何实现手势识别 【已翻译100%】

在这次IOS应用开发教程中,我们打算实现手势识别。正如你所知道的,IOS支持大量的手势操作,它们能提供了很好的应用控制和出色用户体验。

让我们开始吧!

首先需要在Xcode中创建一个新的Single View Application:

然后点击Next,弹出的窗口要求你填写项目设置。在第一栏 (“Product name”) 中填入项目名称后,点击Next.

确保语言选择的是 “Swift”.

设计界面
点击 “Main.storyboard” 文件,拖出6个 UIViews放到视图中.把视图排列成如图所示的样子.当你排列UIViews时,在每个view下面添加一个UILabel并依图设定文本值。

我们开始写代码吧.

是时候编辑实现文件了 (在我们的案例 “ViewController.swift” ).

为了声明一些我们将会用到的变量,要在 “class ViewController: UIViewController “块中添加如下代码.

class ViewController: UIViewController {
    @IBOutlet var tapView: UIView
    @IBOutlet var swipeView: UIView
    @IBOutlet var longPressView: UIView
    @IBOutlet var pinchView: UIView
    @IBOutlet var rotateView: UIView
    @IBOutlet var panView: UIView
    var lastRotation = CGFloat()
    let tapRec = UITapGestureRecognizer()
    let pinchRec = UIPinchGestureRecognizer()
    let swipeRec = UISwipeGestureRecognizer()
    let longPressRec = UILongPressGestureRecognizer()
    let rotateRec = UIRotationGestureRecognizer()
    let panRec = UIPanGestureRecognizer()
}

在第2 – 7行,我们声明了在之前界面里排列过的 UIViews.

在第8行,我们声明了实现旋转手势要用到的变量(lastRotation).

在第 9 – 14行,我们为每个view声明了一个手势识别对象.

注意: 在 Swift中,我们用let关键字声明常量,这意味着它的值在程序运行时不可改变。关键字var则声明普通变量。

当声明完应用需要的主要变量后,在viewDidLoad 方法中添加如下代码.

override func viewDidLoad() {
    super.viewDidLoad()
    tapRec.addTarget(self, action: "tappedView")
    pinchRec.addTarget(self, action: "pinchedView:")
    swipeRec.addTarget(self, action: "swipedView")
    longPressRec.addTarget(self, action: "longPressedView")
    rotateRec.addTarget(self, action: "rotatedView:")
    panRec.addTarget(self, action: "draggedView:")
    tapView.addGestureRecognizer(tapRec)
    swipeView.addGestureRecognizer(swipeRec)
    pinchView.addGestureRecognizer(pinchRec)
    longPressView.addGestureRecognizer(longPressRec)
    rotateView.addGestureRecognizer(rotateRec)
    panView.addGestureRecognizer(panRec)
    rotateView.userInteractionEnabled = true
    rotateView.multipleTouchEnabled = true
    pinchView.userInteractionEnabled = true
    pinchView.multipleTouchEnabled = true
    tapView.userInteractionEnabled = true
    swipeView.userInteractionEnabled = true
    longPressView.userInteractionEnabled = true
    panView.userInteractionEnabled = true
}

第 3 – 8行,为每个视图设定手势识别的目标。所谓的目标,就是每个view中的手势完成后要调用的方法。

第 9 -14行,把手势识别添加到视图中.

第15 – 22行,把每个视图的 userInteractionEnabled 属性设为ture,并把拥有需要多点触控(rotateView and pinchView)的手势所在的视图的multipleTouchEnabled 属性设为true.

现在,我们编写每个手势识别器要调用的方法 (第3 – 8行设置的目标方法 ).

添加如下代码:

func tappedView(){
    let tapAlert = UIAlertController(title: "Tapped", message: "You just tapped the tap view", preferredStyle: UIAlertControllerStyle.Alert)
    tapAlert.addAction(UIAlertAction(title: "OK", style: .Destructive, handler: nil))
    self.presentViewController(tapAlert, animated: true, completion: nil)
}

func swipedView(){
    let tapAlert = UIAlertController(title: "Swiped", message: "You just swiped the swipe view", preferredStyle: UIAlertControllerStyle.Alert)
    tapAlert.addAction(UIAlertAction(title: "OK", style: .Destructive, handler: nil))
    self.presentViewController(tapAlert, animated: true, completion: nil)
}

func longPressedView(){
    let tapAlert = UIAlertController(title: "Long Pressed", message: "You just long pressed the long press view", preferredStyle: UIAlertControllerStyle.Alert)
    tapAlert.addAction(UIAlertAction(title: "OK", style: .Destructive, handler: nil))
    self.presentViewController(tapAlert, animated: true, completion: nil)
}

这三种方法都很好地完成同一件事.每次在手势在相应的视图中完成后,每种方法都弹出一个对话框.

所以 tappedView() 方法在用户滑动视图时弹出一个对话框,swipedView() 方法在用户触摸滑动 swipe视图时弹出对话框,而longPressedView() 方法则在用户长按long press view时弹出对话框.

另两种手势 (rotate and pinch ) 的代码稍微有点复杂.

为旋转手势添加如下代码:

func rotatedView(sender:UIRotationGestureRecognizer){
    var lastRotation = CGFloat()
    self.view.bringSubviewToFront(rotateView)
    if(sender.state == UIGestureRecognizerState.Ended){
    lastRotation = 0.0;
    }
    rotation = 0.0 - (lastRotation - sender.rotation)
    var point = rotateRec.locationInView(rotateView)
    var currentTrans = sender.view.transform
    var newTrans = CGAffineTransformRotate(currentTrans, rotation)
    sender.view.transform = newTrans
    lastRotation = sender.rotation
}

这个方法包含 sender:UIRotationGestureRecognizer 参数. sender 参数( UIRotationGestureRecognizer 类型) 含有这个方法(在这个案例中是rotateRec)调用的手势识别器的值.

第2行声明了 lastRotation.

第3行我们把 rotateView放到前面.

接下来,在 if语句中,我们检查手势是否完成,如果没有完成,我们就将视图旋转。

第 8 – 10行,我们计算rotate view的旋转程度,第10行,我们设置rotate view的旋转程度。

On line 12 we set the lastRotation 作为旋转手势识别器的当前旋转.

现在我们添加pinch 手势的代码:

func pinchedView(sender:UIPinchGestureRecognizer){
    self.view.bringSubviewToFront(pinchView)
    sender.view.transform = CGAffineTransformScale(sender.view.transform, sender.scale, sender.scale)
    sender.scale = 1.0
}

在之前方法的第1行中,我们把pinch视图放到了顶端。然后设置每个pinch视图的transform,并把pinchRec的scale设为1.

然后是实现 pan (drag) 手势. 添加如下代码:

func draggedView(sender:UIPanGestureRecognizer){
    self.view.bringSubviewToFront(sender.view)
    var translation = sender.translationInView(self.view)
    sender.view.center = CGPointMake(sender.view.center.x + translation.x, sender.view.center.y + translation.y)
    sender.setTranslation(CGPointZero, inView: self.view)
}

第2行,我们把 drag视图放到顶端 (和前面的方法一样).

然后我们声明变量translation,并用 sender.translationInView(self.view)的值给它赋值。 完成后,把sender.view object (panRec) 的center属性设为计算出来的新center ( 通过CGPointMake(sender.view.center.x + translation.x, sender.view.center.y + translation.y) 计算) 并把translation 设为 sender (panRec).

现在,代码部分算是完成了!

回到界面设计.

现在我们回到 “Main.storyboard” 文件. 选择视图控制器并把声明的每个UIView连接到相应的视图,如下图所示.

完工

现在你可以在模拟器或你的设备上运行该应用并测试手势。

后记

我希望这篇教程对你有所帮助。你可以在下载完整源代码,另外如果有什么问题,可以通过 Twitter 联系我.

最后,请在psdapps.gr上试用我的IOS应用.

时间: 2024-08-31 06:30:33

Swift 如何实现手势识别 【已翻译100%】的相关文章

从 Objective-C 到 Swift —— Swift 糖果 【已翻译100%】

Swift带来很多确实很棒的特性,使得很难再回到Objective-C.主要的特性是安全性,不过这也被看成是一种额外副作用. 带类型接口的强型别 Swift有强型别,这意味着除非你要求,不然Swift不会为你做类型之间的转换.所以,例如你无法把Int型赋给Double型.你不得不首先转换类型: let i: Int = 42 let d: Double = Double(i) 或者你必须给Double类扩展一个方法用来转换Int型: extension Double { func __conve

Swift 在对 Objective-C 改进的 6 个方面 【已翻译100%】

在 Atomic Object 的安娜堡办公室,我们做了一个观看2014年的WWDC主题演讲,毫不夸张地说,当Swift宣布的时候,我们感到十分激动.Swift,苹果正在推进的一个更现代的编程语言.我很高兴能获得先机并开始用它开发. 在这篇博文中,我将重点介绍Swift的几个语言特性,这将使开发者的工作更加轻松. Objective-C语言的问题 当一个开发者申请一个关于Atomic Object的新职位时,我们会给他填写一个(GTKY) Getting To Know You的表.这个表要求填

使用 Swift 构建一个 iOS 的邮件应用 【已翻译100%】

在前几个月内,我一直在做InboxKit的研究,它是关于Inbox平台的IOS SDK.Inbox为和邮件数据的交互提供高层API,使得你可以忽略IMAP,Exchange,MIME的解析以及thread探测(当然还有很多其他事情...),并使你致力于完成富有创意的APP的创作上.我们的目标很简单:尽可能地打造一个优雅的,跨提供商的邮件应用.毕竟,它很难. 在Objective-C中,InboxKit使得创建邮件体验变得很轻松,那么,Swift又如何呢?Swift在WWDC后已正式被IOS社区所

在终端中运行 Swift 程序 【已翻译100%】

在读完苹果开发者文档( Apple Developer Docs)后,我发现: "Xcode的调试器包括一个Swift语言的交互版本,叫做REPL(Read-Eval-Print-Loop)...可以通过Xcode的控制台或终端来访问" 不幸的是,它并没有告诉你怎样从终端访问.好在这也不是什么难事. 输入如下命令即可(无论你用哪个beta,换掉app的名字) alias swift="/Applications/Xcode6-Beta2.app/Contents/Develo

从 C++ 到 Objective-C 的快速指南 【已翻译100%】

**简介 ** 当我开始为iOS写代码的时候,我意识到,作为一个C++开发者,我必须花费更多的时间来弄清楚Objective-C中怪异的东西.这就是一个帮助C++专家的快速指南,能够使他们快速的掌握Apple的iOS语言. 请注意这绝不是一个完整的指南,但是它让你避免了阅读100页的手册.除此之外,我知道你喜欢我的写作风格. 背景 需要C++的技能,我会比较C++和Objective-C的东西.此外,COM编程也是有用的,因为Objective-C有类似于IUnkown的东西,因此基础的COM编

复制策略与复制的方式 【已翻译100%】(2/2)

服务器宕机意味着相关的日志变化部分会在尺度上增加,直到同伴节点再次运行起来,或者我们从复制目标中移除这个服务器条目. 到目前为止,这与你要组织 oplog 的方式非常相似.主要的不同是,组织需要记录的真实数据的方式.从 oplog 角度看,你准备向系统中写入发生的变化.并且,对之施行的唯一方式就是以它产生的相同顺序将其应用到 oplog 中.这会导致你只能一直拥有一个单主节点的系统.并且会引发在"大脑分裂"时数据丢失或需要手工合并的场景. 就多重可写组合而言,我们要保持足够的上下文(通

CentOS 6 到 CentOS 7 的升级过程【已翻译100%】

在红帽企业版7发布之后仅仅几周,centos7也发布了,并且包含了与红帽同样令人兴奋的功能.除了期待已久的systemd和当前热门的Docker,此次发布还使系统自动从版本6更新到版本7而不需要安装镜像文件成为可能.虽然升级还需要重启,因此不能算是一种live upgrade,但对于那些只能通过远程访问的服务器来说还是非常方便的. 红帽早已发布并且文档化了必要的更新工具.CentOS团队还来不及导入.测试和重新构建工具,但是开发人员早已经在做开始做了-而且他们提供了未测试的二进制文件. 请,注意

函数式编程和 J 编程语言 【已翻译100%】(3/3)

5.2.1 实验 考虑一个实验,评估工作站上执行fibonacci需要多长时间.先估计fib_work 100,尽管上面已经给出递归过程的定义,但有必要给出一个迭代过程的定义以便于评估.考虑下面的函数定义: fib_work_iter =: monad def 'fib_iter 1 1 , y.' fib_iter =: monad define ('a' ; 'b' ; 'count') =. y. if. count = 0 do. b else. fib_iter (1 + a + b)

50 个 jQuery 插件可将你的网站带到另外一个高度 【已翻译100%】

Web领域一直在发生变化并且其边界在过去的每一天都在发生变化(甚至不能以小时为计),随着其边界的扩展取得了许多新发展.在这些进步之中,开发者的不断工作创造了更大和更好的脚本,这些脚本以插件方式带来更好的终端用户体验,它们比原来更轻量级,还有更强的处理能力. 关键是这些新发展起来的脚本和插件是能构建响应式Web的,而且还不会丧失它们原有的功能特性--除了更优秀和更轻巧(就文件大小而言)之外,它们还不会增加页面加载的时间. 通过浏览文档,掌握JQuery的语法是很容易的.它可以支持选择DOM元素,创