Home 提升使用者體驗,現在就為您的 iOS APP 加上 3D TOUCH 功能(Swift)
Post
Cancel

提升使用者體驗,現在就為您的 iOS APP 加上 3D TOUCH 功能(Swift)

[TL;DR]提升使用者體驗,現在就為您的 iOS APP 加上 3D TOUCH 功能(Swift)

iOS 3D TOUCH 應用

[TL;DR] 2020/06/14

iPhone 11 以上版本已取消 3D Touch 功能;改用 Haptic Touch 取代,實作方式也有所不同。

前陣子在專案開發閒暇之時,探索了許多 iOS 的有趣功能: CoreMLVisionNotification Service Extension 、Notification Content Extension、Today Extension、Core Spotlight、Share Extension、SiriKit (部分已整理成文章、其他項目敬請期待🤣)

其中還有今日的主角: 3D Touch功能

這個早在 iOS 9/iPhone 7之後 就開始支援的功能,直到我自己從iPhone 6換到iPhone 8 後才體會到它的好用之處!

3D Touch能在APP中實做兩個項目,如下:

1. Preview ViewController 預覽功能 — [結婚吧APP](https://itunes.apple.com/tw/app/%E7%B5%90%E5%A9%9A%E5%90%A7-%E4%B8%8D%E6%89%BE%E6%9C%80%E8%B2%B4-%E5%8F%AA%E6%89%BE%E6%9C%80%E5%B0%8D/id1356057329?ls=1&mt=8){:target="_blank"}

1. Preview ViewController 預覽功能 — 結婚吧APP

2. 3D Touch Shortcut APP 捷徑啟動功能

2. 3D Touch Shortcut APP 捷徑啟動功能

其中第一項是應用最廣且效果最好的 (Facebook:動態消息內容預覽、Line:偷看訊息),第二項 APP 捷徑啟動 目前看數據是鮮少人使用所以放最後在講。

1. Preview ViewController 預覽功能:

功能展示如上圖1所示,ViewController 預覽功能支援

  • 3D Touch重壓時背景虛化
  • 3D Touch重壓住時跳出ViewController預覽視窗
  • 3D Touch重壓住時跳出ViewController預覽視窗,往上滑可在下方加入選項選單
  • 3D Touch重壓放開返回視窗
  • 3D Touch重壓後再用力進入目標ViewController

這裡將分 A:列表視窗B:目標視窗 個別列出要實作的程式碼:

由於在 B中 沒有方式能判斷當前是預覽還是真的進入此視窗,所以我們先建立一個Protocol傳遞值,用來判斷

1
2
protocol UIViewControllerPreviewable {
    var is3DTouchPreview:Bool {get set}

這樣我們就能在 B中 做以下判斷:

1
2
3
4
class BViewController:UIViewController, UIViewControllerPreviewable {
     var is3DTouchPreview:Bool = false
     override func viewDidLoad() {
     super.viewDidLoad()

A:列表視窗,可以是 UITableView 或 UICollectionView:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class AViewController:UIViewController {
    //註冊能3D Touch 的 View
    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)
        if traitCollection.forceTouchCapability == .available {
            //TableView:
            registerForPreviewing(with: self, sourceView: self.TableView)
            //CollectionView:
            registerForPreviewing(with: self, sourceView: self.CollectionView)
        }
    }   
}
extension AViewController: UIViewControllerPreviewingDelegate {
    //3D Touch放開後,要做的處理
    func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
        
        //現在要直接跳轉的該頁面了,所以將ViewController的預覽模式參數取消:
        if var viewControllerToCommit = viewControllerToCommit as? UIViewControllerPreviewable {
            viewControllerToCommit.is3DTouchPreview = false
        }
        self.navigationController?.pushViewController(viewControllerToCommit, animated: true)
    }
    
    //控制3D Touch的Cell位置,欲顯示的ViewController
    func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
        
        //取得當前點的indexPath/cell實體
        //TableView:
        guard let indexPath = TableView.indexPathForRow(at: location),let cell = TableView.cellForRow(at: indexPath) else { return nil }
        //CollectionView:
        guard let indexPath = CollectionView.indexPathForItem(at: location),let cell = CollectionView.cellForItem(at: indexPath) else { return nil }
      
        //欲顯示的ViewController
        let targetViewController = UIStoryboard(name: "StoryboardName", bundle: nil).instantiateViewController(withIdentifier: "ViewControllerIdentifier")
        
        //背景虛化時保留區域(一般為點擊位置),附圖1
        previewingContext.sourceRect = cell.frame
        
        //3D Touch視窗大小,預設為自適應,不需更改
        //要修改請用:targetViewController.preferredContentSize = CGSize(width: 0.0, height: 0.0)
        
        //告知預覽的ViewController目前為預覽模式:
        if var targetViewController = targetViewController as? UIViewControllerPreviewable {
            targetViewController.is3DTouchPreview = true
        }
        
        //回傳nil則無任何作用
        return nil
    }
}

請注意!其中的註冊能3D Touch 的 View 這塊要放在 traitCollectionDidChange 之中而非 “viewDidLoad” ( 請參考此篇內容 )

關於要加放在哪裡這塊我踩了許多雷,網路有些資料寫viewDidLoad、有的寫在cellforItem中,但這兩個地方都會出現偶爾失效或部分cell失效的問題。

附圖1 背景虛化保留區示意圖

附圖1 背景虛化保留區示意圖

如果您需要上滑後在下方加入選項選單請在 B 之中加入,是B 是B 是B哦!

1
2
3
4
5
6
override var previewActionItems: [UIPreviewActionItem] {
  let profileAction = UIPreviewAction(title: "查看商家資訊", style: .default) { (action, viewController) -> Void in
    //點擊後的操作
  }
  return [profileAction]
}

回傳空陣列表示不使用此功能。

完成!

2. APP 捷徑啟動

第一步

在 info.plist 中加入 UIApplicationShortcutItems 參數,類型 Array

並在其中新增選單項目(Dictionary),其中Key-Value的設定對應如下:

  • [必填] UIApplicationShortcutItemType : 識別字串,在AppDelegate中做判斷使用
  • [必填] UIApplicationShortcutItemTitle : 選項標題
  • UIApplicationShortcutItemSubtitle : 選項子標題

  • UIApplicationShortcutItemIconType : 使用系統圖標

參考自 [此篇文章](https://qiita.com/kusumotoa/items/f33c89f150cd0937d003){:target="_blank"}

參考自 此篇文章

  • UIApplicationShortcutItemIconFile : 使用自定義圖標(size:35x35,單色),與UIApplicationShortcutItemIconType擇ㄧ使用
  • UIApplicationShortcutItemUserInfo : 更多附加資訊EX: [id:1]

我的設定如上圖

我的設定如上圖

第二步

在AppDelegate中新增處理的Function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
    var info = shortcutItem.userInfo
  
    switch shortcutItem.type {
    case "searchShop":
      //
    case "topicList":
      //
    case "likeWorksPic":
      //
    case "marrybarList":
      //
    default:
        break
    }
    completionHandler(true)
}

完成!

結語

在APP中加入 3D Touch的功能並不難,對使用者來說也會覺得很貼心❤;可以搭配設計操作增加使用者體驗;但目前就只有上述兩個功能可做在加上iPhone 6s以下/iPad/iPhone XR都不支援3D Touch所以實際能做的功能又更少了,只能以輔助、增加體驗為主。

p.s.

如果你測的夠細會發現以上效果,在CollectionView滑動中圖有部分已經滑出畫面這時按壓就會出現以上情況😅

如果你測的夠細會發現以上效果,在CollectionView滑動中圖有部分已經滑出畫面這時按壓就會出現以上情況😅

===

本文首次發表於 Medium ➡️ 前往查看

This post is licensed under CC BY 4.0 by the author.

嚐鮮 iOS 12 CoreML — 使用機器學習自動預測文章分類,連模型也自己訓練!

iOS UUID 的那些事 (Swift/iOS ≥ 6)

Comments powered by Disqus.