SwiftCafe 快报 - 3D Touch 之 Peek & Pop 操作

Peek Pop

在前面几期快报中,我们介绍了 3D Touch 的基本内容,以及如何创建 3D Touch 桌面快捷菜单。这次咱们来讨论 3D Touch 的另外一个内容 - Peek & Pop 操作。

所谓 Peek & Pop 其实就是 iOS 9 中为我们提供的一种预览功能,通过 3D Touch 来激发它的调用。比如我们在看短信或者邮件等信息的时候,通过按压列表中得内容,我们就能够得到一个预览视图。然后再继续用力按压,我们就可以从预览界面直接进入到内容页面。

Peek & Pop 操作,也是 WWDC 中演示 3D Touch 的主要方面。它的实现其实也并不复杂,我们自己的 APP 中可以通过新的 API 很轻易的实现这个功能。

下面咱们就来看看吧,首先我们定义一个 UIViewController:

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIViewControllerPreviewingDelegate {

  let tableView = UITableView()

  let news = ["SwiftCafe 快报 - 3D Touch 实践之桌面快捷方式第二篇","SwiftCafe 快报 - TIOBE 10月编程语言排行 Swift 即将超越 Objective-C","SwiftCafe 快报 - iOS 9 新特性之 3D Touch"]

  override func viewDidLoad() {
      super.viewDidLoad()


  }

}

这个 ViewController 实现了三个 Protocol - UITableViewDelegate, UITableViewDataSource, UIViewControllerPreviewingDelegate

前两个相信大家都比较熟悉了,都和 UITable 相关,用于我们展示列表信息。而最后一个 Protocol - UIViewControllerPreviewingDelegate 就比较重要了。它是实现 Peek & Pop 操作的关键。

当然,我们还定义了两个属性 tableViewnews,它们只是用于信息展示。

接着就是 UITableView 相关的代理方法的实现,都比较熟悉,大家一带而过即可:

// MARK: TableView Delegate
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return news.count

}

func numberOfSectionsInTableView(tableView: UITableView) -> Int {

    return 1

}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cellIdentifier = "cellIdentifier"

    var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier)

    if cell == nil {

        cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: cellIdentifier)

    }

    cell?.textLabel?.text = news[indexPath.row]

    return cell!

}

无非是确定如何显示 UItableView 相关的信息。

然后我们实现 viewDidLoad 方法,对整个控制器进行初始化工作:

override func viewDidLoad() {
    super.viewDidLoad()

    self.title = "3D Touch - Peek & Pop 示例"
    self.navigationItem.backBarButtonItem?.title = "返回"
    tableView.dataSource = self
    tableView.delegate = self

    self.navigationController?.navigationBar.translucent = false

    tableView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)
    self.view.addSubview(tableView)

    if traitCollection.forceTouchCapability == UIForceTouchCapability.Available {

        registerForPreviewingWithDelegate(self, sourceView: view)

    }

}

这个方法的前半部分,也基本都是一些 UI 元素的初始化工作。比较重要的是这个方法的后半部分,也就是:

if traitCollection.forceTouchCapability == UIForceTouchCapability.Available {

    registerForPreviewingWithDelegate(self, sourceView: view)

}

这个判断的作用是检测当前设备是否支持 3D Touch,如果支持,就调用 registerForPreviewingWithDelegate(self, sourceView: view) 方法,将视图控制器的主视图注册为 3D Touch Peek & Pop 的主体。

这时我们运行程序,就可以看到列表内容的展现了:

UI 列表界面

Peek Pop

在前面几期快报中,我们介绍了 3D Touch 的基本内容,以及如何创建 3D Touch 桌面快捷菜单。这次咱们来讨论 3D Touch 的另外一个内容 - Peek & Pop 操作。

所谓 Peek & Pop 其实就是 iOS 9 中为我们提供的一种预览功能,通过 3D Touch 来激发它的调用。比如我们在看短信或者邮件等信息的时候,通过按压列表中得内容,我们就能够得到一个预览视图。然后再继续用力按压,我们就可以从预览界面直接进入到内容页面。

Peek & Pop 操作,也是 WWDC 中演示 3D Touch 的主要方面。它的实现其实也并不复杂,我们自己的 APP 中可以通过新的 API 很轻易的实现这个功能。

下面咱们就来看看吧,首先我们定义一个 UIViewController:

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIViewControllerPreviewingDelegate {

  let tableView = UITableView()

  let news = ["SwiftCafe 快报 - 3D Touch 实践之桌面快捷方式第二篇","SwiftCafe 快报 - TIOBE 10月编程语言排行 Swift 即将超越 Objective-C","SwiftCafe 快报 - iOS 9 新特性之 3D Touch"]

  override func viewDidLoad() {
      super.viewDidLoad()


  }

}

这个 ViewController 实现了三个 Protocol - UITableViewDelegate, UITableViewDataSource, UIViewControllerPreviewingDelegate

前两个相信大家都比较熟悉了,都和 UITable 相关,用于我们展示列表信息。而最后一个 Protocol - UIViewControllerPreviewingDelegate 就比较重要了。它是实现 Peek & Pop 操作的关键。

当然,我们还定义了两个属性 tableViewnews,它们只是用于信息展示。

接着就是 UITableView 相关的代理方法的实现,都比较熟悉,大家一带而过即可:

// MARK: TableView Delegate
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return news.count

}

func numberOfSectionsInTableView(tableView: UITableView) -> Int {

    return 1

}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cellIdentifier = "cellIdentifier"

    var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier)

    if cell == nil {

        cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: cellIdentifier)

    }

    cell?.textLabel?.text = news[indexPath.row]

    return cell!

}

无非是确定如何显示 UItableView 相关的信息。

然后我们实现 viewDidLoad 方法,对整个控制器进行初始化工作:

override func viewDidLoad() {
    super.viewDidLoad()

    self.title = "3D Touch - Peek & Pop 示例"
    self.navigationItem.backBarButtonItem?.title = "返回"
    tableView.dataSource = self
    tableView.delegate = self

    self.navigationController?.navigationBar.translucent = false

    tableView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)
    self.view.addSubview(tableView)

    if traitCollection.forceTouchCapability == UIForceTouchCapability.Available {

        registerForPreviewingWithDelegate(self, sourceView: view)

    }

}

这个方法的前半部分,也基本都是一些 UI 元素的初始化工作。比较重要的是这个方法的后半部分,也就是:

if traitCollection.forceTouchCapability == UIForceTouchCapability.Available {

    registerForPreviewingWithDelegate(self, sourceView: view)

}

这个判断的作用是检测当前设备是否支持 3D Touch,如果支持,就调用 registerForPreviewingWithDelegate(self, sourceView: view) 方法,将视图控制器的主视图注册为 3D Touch Peek & Pop 的主体。

这时我们运行程序,就可以看到列表内容的展现了:

peek-1.jpg

怎么样,列表出现了,但这是我们用力按压列表项上的内容,并没有出现预料的结果。

接下来,我们继续实现 3D Touch 操作处理部分,还记得我们前面提到的 UIViewControllerPreviewingDelegate 么,关键就在于这个 Protocol 中的两个方法:

func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {

    guard let indexPath = tableView.indexPathForRowAtPoint(location),
    cell = tableView.cellForRowAtIndexPath(indexPath)
        else {return nil}

    let detailViewController = DetailViewController()
    detailViewController.text = cell.textLabel!.text!
    return detailViewController
}

func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController) {
    showViewController(viewControllerToCommit, sender: self)
}

这两个方法中,第一个方法 func previewingContext(previewingContext: viewControllerForLocation:) 是用于相应轻度按压后出现预览窗口的。当我们轻度按压主列表的条目时,我们就会创建一个 DetailViewController 并用它来展示预览内容。

而第二个方法 func previewingContext(previewingContext: commitViewController:) 用于,当用户已经通过轻度按压激发出预览界面的时候,继续用力按压后,正式的进入详情页面。我们调用 showViewController 方法,来进入详情页面。

实现完这两个方法,我们就可以像 WWDC 演示的那样,在我们自己的 APP 中响应 3D Touch 预览事件啦。有没有感觉很酷~

而详细界面控制器的实现也需要我们做一些操作,我们来看一下 DetailViewController 的实现:

class DetailViewController: UIViewController {

    var text:String = ""

    override func viewDidLoad() {
        super.viewDidLoad()

        self.title = "SwiftCafe 快报"
        self.navigationItem.backBarButtonItem?.title = "返回"

        let textView = UITextView(frame: CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height))
        textView.font = UIFont.systemFontOfSize(24)
        textView.text = text
        self.view.addSubview(textView)

    }

    override func previewActionItems() -> [UIPreviewActionItem] {

        let itemShare = UIPreviewAction(title: "分享", style: UIPreviewActionStyle.Default) {
            previewAction, viewController in

            let alertView = UIAlertView(title: "分享", message: "分享内容", delegate: nil, cancelButtonTitle: "确定")
            alertView.show()

        }

        return [itemShare]

    }

}

DetailViewControllerviewDidLoad 方法实现对 UI 进行了一些基本初始化操作,比较简单,不多赘述。

previewActionItems 方法,大家可以稍加关注。

我们在通过按压列表条目后,会弹出类似这样的预览视图:

Peek 预览
Peek 预览

而这个预览视图,我们出来继续按压,进而打开真正的详情视图以外,我们还可以通过向上滑动手指,打开这个预览视图的操作界面,这样我们就可以不真正的进入详情页面,来对该条目进行一些特定的操作了,比如分享,删除,等等。

我们这里实现的 previewActionItems 方法,正是为预览视图提供这些操作选项用的。每一个操作选项,都是一个 UIPreviewAction 类。

接下来,我们可以运行这个示例,并按压后向上滑动,就可以打开预览视图的操作选项界面了:

Peek 操作
Peek 操作

关于 3D Touch 的更多内容,还可以参看往期快报:

怎么样,列表出现了,但这是我们用力按压列表项上的内容,并没有出现预料的结果。

接下来,我们继续实现 3D Touch 操作处理部分,还记得我们前面提到的 UIViewControllerPreviewingDelegate 么,关键就在于这个 Protocol 中的两个方法:

func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {

    guard let indexPath = tableView.indexPathForRowAtPoint(location),
    cell = tableView.cellForRowAtIndexPath(indexPath)
        else {return nil}

    let detailViewController = DetailViewController()
    detailViewController.text = cell.textLabel!.text!
    return detailViewController
}

func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController) {
    showViewController(viewControllerToCommit, sender: self)
}

这两个方法中,第一个方法 func previewingContext(previewingContext: viewControllerForLocation:) 是用于相应轻度按压后出现预览窗口的。当我们轻度按压主列表的条目时,我们就会创建一个 DetailViewController 并用它来展示预览内容。

而第二个方法 func previewingContext(previewingContext: commitViewController:) 用于,当用户已经通过轻度按压激发出预览界面的时候,继续用力按压后,正式的进入详情页面。我们调用 showViewController 方法,来进入详情页面。

实现完这两个方法,我们就可以像 WWDC 演示的那样,在我们自己的 APP 中响应 3D Touch 预览事件啦。有没有感觉很酷~

而详细界面控制器的实现也需要我们做一些操作,我们来看一下 DetailViewController 的实现:

class DetailViewController: UIViewController {

    var text:String = ""

    override func viewDidLoad() {
        super.viewDidLoad()

        self.title = "SwiftCafe 快报"
        self.navigationItem.backBarButtonItem?.title = "返回"

        let textView = UITextView(frame: CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height))
        textView.font = UIFont.systemFontOfSize(24)
        textView.text = text
        self.view.addSubview(textView)

    }

    override func previewActionItems() -> [UIPreviewActionItem] {

        let itemShare = UIPreviewAction(title: "分享", style: UIPreviewActionStyle.Default) {
            previewAction, viewController in

            let alertView = UIAlertView(title: "分享", message: "分享内容", delegate: nil, cancelButtonTitle: "确定")
            alertView.show()

        }

        return [itemShare]

    }

}

DetailViewControllerviewDidLoad 方法实现对 UI 进行了一些基本初始化操作,比较简单,不多赘述。

previewActionItems 方法,大家可以稍加关注。

我们在通过按压列表条目后,会弹出类似这样的预览视图:

Peek 预览

而这个预览视图,我们出来继续按压,进而打开真正的详情视图以外,我们还可以通过向上滑动手指,打开这个预览视图的操作界面,这样我们就可以不真正的进入详情页面,来对该条目进行一些特定的操作了,比如分享,删除,等等。

我们这里实现的 previewActionItems 方法,正是为预览视图提供这些操作选项用的。每一个操作选项,都是一个 UIPreviewAction 类。

接下来,我们可以运行这个示例,并按压后向上滑动,就可以打开预览视图的操作选项界面了:

Peek 操作

关于 3D Touch 的更多内容,还可以参看往期快报:

更多精彩内容可关注微信公众号:
swift-cafe

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容