iOS 3D Touch浅谈

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/freedom12354/article/details/52792262

一、什么是3D Touch?

3D Touch是iPhone 6s推出的一种可以让你与手机进行互动的全新方式。除了轻点、轻扫、双指开合这些熟悉的 Multi‑Touch 手势之外,3D Touch 还带来 Peek 和 Pop,为 iPhone 的使用体验开拓出全新的维度。而且,当你使用 3D Touch 时,iPhone 将回以轻微的触感,让你不仅能够看到按下屏幕的操作效果,还能感觉得到。

二、3D Touch开发

1、Quick Actions(主屏幕快速选项)

用户通过按压屏幕上应用的icon,可以获得一系列的快捷选项,用户选取一个选项后,将会启动或加载应用,而应用的delegate会接受快捷选项的消息。

主屏幕快速选项

对于主屏幕快速选项我们有两种设置方式:静态,动态。

(1)、静态标签

静态标签是在项目的info.plist里面配置,用户安装应用后就可以使用,并且排在动态标签的前面。

配置info.plist文件

info.plist文件中添加如下键值

先添加了一个UIApplicationShortcutItems的数组,这个数组中添加的元素就是对应的静态标签,在每个标签中我们需要添加一些设置的键值:

必填项(下面两个键值是必须设置的):

UIApplicationShortcutItemType  这个键值设置一个快捷通道类型的字符串
UIApplicationShortcutItemTitle  这个键值设置标签的标题

选填项(下面这些键值不是必须设置的) :

UIApplicationShortcutItemSubtitle  设置标签的副标题
UIApplicationShortcutItemIconType  设置标签Icon类型(value在这个类中查看)
UIApplicationShortcutItemIconFile   设置标签的Icon文件(不想用系统的,自定义)
UIApplicationShortcutItemUserInfo  设置信息字典(用于传值)

效果如下:

静态标签

(2)、动态标签

动态标签是在应用需要的时候,用代码添加的,相关的类有:

    UIApplicationShortcutItem  创建3DTouch标签的类
    UIMutableApplicationShortcutItem  创建可变3DTouch标签的类
    UIApplicationShortcutIcon 创建标签中图片Icon的类

创建一个UIApplicationShortcutItem:

// 创建快捷方式的icon
let shortCutIcon: UIApplicationShortcutIcon = UIApplicationShortcutIcon(templateImageName: "icon_pass") // 自定义

//let shortCutIcon: UIApplicationShortcutIcon = UIApplicationShortcutIcon(type: .play) // 系统

// 创建快捷方式item
let shortchuItem: UIApplicationShortcutItem = UIApplicationShortcutItem(type: "Second", localizedTitle: "这是第二个", localizedSubtitle: "Second", icon: shortCutIcon, userInfo: nil)

// 添加
UIApplication.shared.shortcutItems = [shortchuItem]

效果如下:

动态标签

修改某个shortchuItem

// 获取应用单前所有的动态标签标签,无法获取静态的
let application: UIApplication = UIApplication.shared
var shortcutItems: [UIApplicationShortcutItem]? = application.shortcutItems

// 修改应用当前的某个shortcutItems
let newShortcutItem: UIMutableApplicationShortcutItem = shortcutItems?[0].mutableCopy() as! UIMutableApplicationShortcutItem

newShortcutItem.localizedTitle = "第二个修改";
newShortcutItem.icon = UIApplicationShortcutIcon(type: .search)

// 重新添加
shortcutItems?[0] = newShortcutItem
application.shortcutItems = shortcutItems;

效果图如下:
修改某个shortchuItem

(3)、响应标签行为

当我们点击标签进入应用时,我们要做一些操作,而我们可以看见在applocation中有这样一个方法:

func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void)

当我们点击标签进入应用时,就会响应这个方法,在这个方法里面我们根据shortcutItem处理相应的操作。

而在App的入口方法:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        if launchOptions?[.shortcutItem] != nil {

//            return false
        }

        return true
    }

我们可以判断launchOptions中shortcutItem(Object-C中为UIApplicationLaunchOptionsShortcutItemKey)这个键值是否为空,从而判断是否是从快捷标签进入应用的。有时候我们可能要处理这两种情况:

1、应用处于后台,点击标签进入应用
2、应用未运行,点击标签进入应用

如果这两种状态下的情况不一样,就需要在这里判断一下是不是上面两种中的情况2,如果是,则在App的入口方法中返回false,这样就不会走响应标签行为的那个方法。

标签最多可以创建4个,包括静态和动态。

2、Peek and Pop

1、检测3DTouch是否可用

// 检测3DTouch可不可用
    func detection3DTouchIsAvailable() -> Bool {
        return self.traitCollection.forceTouchCapability == .available ? true : false
    }

如果可用,注册

self.registerForPreviewing(with: self, sourceView: view)

2、实现UIViewControllerPreviewingDelegate

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

        let previewingVC: UIViewController = UIViewController()
        return previewingVC
    }

    // Pop
    func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
        print(#function)

        self.show(viewControllerToCommit, sender: self)
    }

以上是整个view都响应3DTouch,你也可以指定某个视图。
在实际情况中我们可能遇到一个界面上有较多的地方需要响应3DTouch(像微信中的朋友圈)。这种情况我们不可能每个视图都去注册,而我的处理方式为(以tableview为例):

把tableview做为sourceView注册

self.registerForPreviewing(with: self, sourceView: tableView)

在peek方法中做处理:
(1)、判断location在那个cell上

open func indexPathForRow(at point: CGPoint) -> IndexPath?

(2)、转换坐标系(一直转换到你要处理的视图的父视图上)

public func convert(_ point: CGPoint, to coordinateSpace: UICoordinateSpace) -> CGPoint

(3)、判断转换后的点是否在某个视图上

public func contains(_ point: CGPoint) -> Bool

(4)、如果点有在某个视图上,做相应处理,否则返回nil

详见—— demo的PeekAndPopViewController

3、添加底部菜单,在对应的控制器里面重写

open var previewActionItems: [UIPreviewActionItem] { get }

示例如下:

// MARK: -- 添加底部菜单
    override var previewActionItems: [UIPreviewActionItem] {

        let action1: UIPreviewAction = UIPreviewAction(title: "action1", style: .default) { (action, viewController) in

            // 处理操作

        }

        let action2: UIPreviewAction = UIPreviewAction(title: "action2", style: .destructive) { (action, viewController) in

        }

        let action3: UIPreviewAction = UIPreviewAction(title: "action3", style: .selected) { (action, viewController) in

        }

        return [action1,action2,action3]
    }

4、Web View Peek and Pop
显示网页有三种方法:
(1)、openUrl离开应用进入safari打开网页
(2)、UIWebView或者WKWebView自定义视图在应用内打开网页
(3)、在iOS9.0后新增SFSafariViewController类,用于显示web网页。并通过SFSafariViewControllerDelegate的以下方法实现回到应用操作。

func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
        controller.dismiss(animated: true, completion: nil)
    }

方法1不能实现3D Touch。
使用方法2实现3D Touch时,要设置webView属性 allowsLinkPreview 为true(默认是false)。

3、 UITouch Force Properties

在UITouch这个类中有force,maximumPossibleForce这两个属性,当按压屏幕越重时force就越大。

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch: UITouch = touches.first!

        print("force = \(touch.force)\n,max = \(touch.maximumPossibleForce)\n,scale = \(touch.force/touch.maximumPossibleForce)")

        let scale = 1.0-touch.force/touch.maximumPossibleForce

        view.backgroundColor = UIColor(red: 1.0, green: scale, blue: scale, alpha: 1.0)
    }

我的——demo

三、参考链接

[iOS]iOS9 3DTouch、ShortcutItem、Peek And Pop技术一览

浅谈3D Touch(2) – UITouch && Peek && Pop

Adopting 3D Touch on iPhone

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页