tom知识总结

iOS 3D Touch开发(完整、详细版)

2017-02-28  本文已影响455人  小道萧兮

一、3D Touch 简介

在iOS 9中,新 iPhone 将第三维度添加到了用户界面。

Home Screen Quick Actions

本文主要讲解 3D Touch 各种场景下的开发方法,开发主屏幕应用 icon 上的快捷选项标签(Home Screen Quick Actions),静态设置 UIApplicationShortcutItem ,动态添加 UIApplicationShortcutItem,以及 Peek 和 Pop 的实现。

二、Home Screen Quick Actions

添加Home Screen Quick Actions有两种方式:
1、通过Plist文件静态设置;
2、通过代码动态添加。

两种方法的区别在于:通过Plist设置无需运行程序,也就是说在下载App后,不需要打开应用,就可以即可唤出Home Screen Quick Actions;而通过代码动态添加的,必须在第一次下载后打开App,才能出现Home Screen Quick Actions。

1. 通过Plist文件静态设置

在应用的 Info.plist 文件中添加UIApplicationShortcutItems数组。
数组中添加字典,如下图所示:

Info.plist文件配置

其中,字典的Key有以下选项:

名称 说明 是否必须
UIApplicationShortcutItemTitle 标签的标题 必填
UIApplicationShortcutItemType 标签的唯一标识 必填
UIApplicationShortcutItemIconType 使用系统图标的类型,如搜索、定位、home等 可选
UIApplicationShortcutItemIconFile 使用项目中的图片作为标签图标 可选
UIApplicationShortcutItemSubtitle 标签副标题 可选
UIApplicationShortcutItemUserInfo 字典信息,如传值使用 可选

第一个图片使用系统自带的,第二个是使用Assets.xcassets文件夹中的图片,当完成设置后,效果如下:

通过Plist文件静态设置
2. 通过代码动态添加
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        
     let item1 = UIApplicationShortcutItem(type: "2", localizedTitle: "code add item1", localizedSubtitle: "code add subtitle", icon: UIApplicationShortcutIcon(templateImageName: "shortcut_scorecard"), userInfo: nil)
     let item2 = UIApplicationShortcutItem(type: "3", localizedTitle: "code add item2", localizedSubtitle: nil, icon: UIApplicationShortcutIcon(type: .add), userInfo: nil)
        
     application.shortcutItems = [item1, item2]
     return true
}

效果如下:

通过代码动态添加
注意:目前Home Screen Quick Actions最多只能添加4个。
无论用哪种方式添加,当点击item后,都会调用AppDelegate中的application(_:performActionFor:completionHandler:)方法:
func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
     print(shortcutItem.type) // 通过type来判断是点击了哪一个按钮
}

三、Peek and Pop(预览与跳转)

实现步骤:

  1. 注册预览代理
// Registers a view controller to participate with 3D Touch preview (peek) and commit (pop).
@available(iOS 9.0, *)
// 第一个参数:代理
// 第二个参数:哪个view执行Peek
open func registerForPreviewing(with delegate: UIViewControllerPreviewingDelegate, sourceView: UIView) -> UIViewControllerPreviewing
  1. 遵守协议:UIViewControllerPreviewingDelegate
  2. 实现协议方法
// If you return nil, a preview presentation will not be performed
@available(iOS 9.0, *)
public func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController?
@available(iOS 9.0, *)
public func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController)

接下来用一个tableView的例子🌰来说明,实现以下效果:



代码如下:

import UIKit

class ViewController: UIViewController {
    
    fileprivate lazy var array = [String]()
    @IBOutlet weak var tableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        for i in 0...20 { array.append("第\(i)行") }
        // 注册Cell
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
        // 判断系统版本,必须iOS 9及以上,同时检测是否支持触摸力度识别
        if #available(iOS 9.0, *), traitCollection.forceTouchCapability == .available {
            // 注册预览代理,self监听,tableview执行Peek
            registerForPreviewing(with: self, sourceView: tableView)
        }
    }
}

// MARK: - UITableViewDataSource
extension ViewController: UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return array.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
        cell.textLabel?.text = array[indexPath.row]
        return cell
    }
}

// MARK: - UIViewControllerPreviewingDelegate
@available(iOS 9.0, *)
extension ViewController: UIViewControllerPreviewingDelegate {
    
    func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
        // 模态弹出需要展现的控制器
        showDetailViewController(viewControllerToCommit, sender: nil)
        // 通过导航栏push需要展现的控制器
        // show(viewControllerToCommit, sender: nil)
    }
    
    func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
        // 获取indexPath和cell
        guard let indexPath = tableView.indexPathForRow(at: location), let cell = tableView.cellForRow(at: indexPath) else { return nil }
        // 设置Peek视图突出显示的frame
        previewingContext.sourceRect = cell.frame
        let vc = DetalViewController()
        // 返回需要弹出的控制权
        return vc
    }
}

在实际开发中,你可能会用到 UIView中的坐标转换 的几个方法(可跳过不看):

// 将像素point由point所在视图转换到目标视图view中,返回在目标视图view中的像素值
open func convert(_ point: CGPoint, to view: UIView?) -> CGPoint
// 例如:point2 = view1.convert(point1, toView: view2):把point1从view1的坐标系中,转换到view2的坐标系中

// 将像素point从view中转换到当前视图中,返回在当前视图中的像素值
open func convert(_ point: CGPoint, from view: UIView?) -> CGPoint
// 例如:point2 = view1.convert(point1, from: view2):把point1从view2的坐标系中,转换到view1的坐标系中

// 将rect由rect所在视图转换到目标视图view中,返回在目标视图view中的rect
open func convert(_ rect: CGRect, to view: UIView?) -> CGRect
// 例如:rect2 = view1.convert(rect1, toView: view2):把rect1从view1的坐标系中,转换到view2的坐标系中

// 将rect从view中转换到当前视图中,返回在当前视图中的rect
open func convert(_ rect: CGRect, from view: UIView?) -> CGRect
// 例如:rect2 = view1.convert(rect1, toView: view2):把rect1从view2的坐标系中,转换到view1的坐标系中

四、Peek快速选项

如果用户一直保持触摸,可以向上滑动Peek视图,系统会展示出你预先设置和peek关联的peek快速选项。
每一项peek快速选项都是你应用中的深度链接。当peek快速选项出现后,用户可以停止触摸而且peek会停留在屏幕中。用户可点击一个快速选项,唤出相关链接。


在本例中,实现以上效果,只需要在DetalViewController中添加以下代码即可:
import UIKit

class DetalViewController: UIViewController {
    
    @available(iOS 9.0, *)
    lazy var previewActions: [UIPreviewActionItem] = {
        let a = UIPreviewAction(title: "这是一个default按钮", style: .default, handler: { (action, vc) in
            // 这里实现点击按钮事件处理
        })
        let b = UIPreviewAction(title: "这是一个destructive按钮", style: .destructive, handler: { (action, vc) in
            // 这里实现点击按钮事件处理
        })
        return [a, b]
    }()
    
    @available(iOS 9.0, *)
    override var previewActionItems: [UIPreviewActionItem] {
        return previewActions
    }
}

最后注意:以上全部功能必须要求为 iPhone 6s 及以上机型,并且是 iOS 9 及以上,才有效果,模拟器可以看到效果,不需要安装任何插件,但必须要有触摸盘才行,在触摸盘上的点击就是3D Touch。

上一篇下一篇

猜你喜欢

热点阅读