iOS之3D Touch

一、前言

3D Touch 是一種立體觸控技術(shù),被蘋果稱為新一代多點(diǎn)觸控技術(shù),是在Apple Watch 上采用的 Force Touch,屏幕可感應(yīng)不同的感壓力度觸控。 3D Touch,蘋果 iPhone 6s 的新功能,看起來類似 PC 上的右鍵。有 PeekPop 兩種新手勢。此功能的發(fā)布將手機(jī)屏幕的的操作坐標(biāo)由 xy 軸擴(kuò)大至 z 軸,增加了整整一個(gè)維度(即相對(duì)于多點(diǎn)觸摸在平面二維空間的操作,3D Touch 技術(shù)增加了對(duì)力度和手指面積的感知,可以通過長按快速預(yù)覽/查看你想要的短信/圖片/超鏈接等內(nèi)容,PeekPop 手勢的響應(yīng)時(shí)間可迅捷到 10ms15ms),這在屏幕時(shí)代屬于非常偉大的創(chuàng)新。

demo地址

二、蘋果的3D Touch主要呈現(xiàn)方式

2.1、按功能劃分,有三種:
  • 主屏交互(Home Screen Interaction);
  • 預(yù)覽和跳轉(zhuǎn)(Peek and Pop);
  • LivePhoto;

注:本文主要介紹一下前兩種用法。

2.2、按3D Touch功能使用的位置劃分,有兩種:
  • 手機(jī)桌面,效果圖如下:

    微信

    京東

  • 應(yīng)用內(nèi),效果圖如下:

    微信

三、使用

3.1、主屏交互(Home Screen Interaction);

所謂的主屏交互也就是在手機(jī)的桌面,用手指按壓應(yīng)用圖標(biāo),生成的幾個(gè)快捷操作按鈕的,效果圖如下:


主屏交互的按鈕有指定的模型類:UIApplicationShortcutItem,添加 UIApplicationShortcutItem 有兩種方式:靜態(tài)添加和動(dòng)態(tài)添加。

靜態(tài)添加動(dòng)態(tài)添加區(qū)別:靜態(tài)設(shè)置是在應(yīng)用安裝的時(shí)候完成加載的,而動(dòng)態(tài)設(shè)置需要在運(yùn)行到對(duì)應(yīng)代碼時(shí)(runtime) 才加載,所以同時(shí)有靜態(tài)加載的 Item 和動(dòng)態(tài)加載的 Item時(shí),靜態(tài)加載的 Item 會(huì)排在前面。

3.1.1、靜態(tài)添加UIApplicationShortcutItem

靜態(tài)添加 UIApplicationShortcutItem 方式主要是在工程的 info.plist 文件中添加相關(guān)的屬性,如下圖:

// 數(shù)組中的元素就是上圖中的快捷選項(xiàng)標(biāo)簽
UIApplicationShortcutItems

// 標(biāo)簽標(biāo)題(必填)
UIApplicationShortcutItemTitle

// 標(biāo)簽的唯一標(biāo)識(shí) (必填)
UIApplicationShortcutItemType

// 使用系統(tǒng)圖標(biāo)的類型,如搜索、定位、home等(可選)
UIApplicationShortcutItemIconType

// 使用項(xiàng)目中的圖片作為標(biāo)簽圖標(biāo) (可選)
UIApplicationShortcutItemIconFile

// 標(biāo)簽副標(biāo)題 (可選)
UIApplicationShortcutItemSubtitle

// 字典信息,如傳值使用 (可選)
UIApplicationShortcutItemUserInfo
3.1.2、動(dòng)態(tài)添加UIApplicationShortcutItem

UIApplicationShortcutItem 可以看作是 3D Touch 點(diǎn)擊后,彈出菜單每行對(duì)應(yīng)的模型,一行對(duì)應(yīng)一個(gè) UIApplicationShortcutItem 對(duì)象。

動(dòng)態(tài)添加時(shí)就是我們可以通過生成 UIApplicationShortcutItem 對(duì)象數(shù)組,添加給 UIApplication 單例對(duì)象。

UIApplicationShortcutItem 初始方法如下:

/**
 @param type item的唯一標(biāo)識(shí)(必填)
 @param localizedTitle 是item的標(biāo)題(必填)
 @param localizedSubtitle 是item的副標(biāo)題(可選)
 @param icon 是item的圖標(biāo)(可選)
 @param userInfo 是item所包含的信息,類型是字典(可選)
 */
- (instancetype)initWithType:(NSString *)type 
              localizedTitle:(NSString *)localizedTitle 
           localizedSubtitle:(nullable NSString *)localizedSubtitle 
                        icon:(nullable UIApplicationShortcutIcon *)icon
                    userInfo:(nullable NSDictionary<NSString *, id <NSSecureCoding>> *)userInfo;

初始化生成 UIApplicationShortcutItem 對(duì)象這一步操作一般都是在 AppDelegate 類的方法里處理的,方法如下:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;

動(dòng)態(tài)添加時(shí),首先要判斷手機(jī)是否支持 3D Touch,代碼如下:

if (self.window.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) {
// TODO - 創(chuàng)建3DTouch模型
}

生成 UIApplicationShortcutItem 對(duì)象數(shù)組,添加給 UIApplication 單例對(duì)象,示例代碼如下:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // 首先判斷是否支持3D Touch
    if (self.window.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) {
        // 創(chuàng)建3D Touch模型
        [self setup3DTouch];
    }
    
    return YES;
}

- (void)setup3DTouch {
    NSMutableArray *shortcutItems = (NSMutableArray *)[UIApplication sharedApplication].shortcutItems;
    
    UIApplicationShortcutItem *shoreItem1 = [[UIApplicationShortcutItem alloc] initWithType:@"com.xw.test1" localizedTitle:@"test1" localizedSubtitle:@"sub test1" icon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeAdd] userInfo:nil];
    UIApplicationShortcutItem *shortItem2 = [[UIApplicationShortcutItem alloc] initWithType:@"com.xw.test2" localizedTitle:@"test2" localizedSubtitle:@"sub test2" icon:[UIApplicationShortcutIcon iconWithTemplateImageName:@"like"] userInfo:nil];

    [shortcutItems addObject:shoreItem1];
    [shortcutItems addObject:shortItem2];
    
    [UIApplication sharedApplication].shortcutItems = shortcutItems;
}

在使用動(dòng)態(tài)添加 UIApplicationShortcutItem 時(shí),可以使用自定義的圖標(biāo)(官方推薦一倍圖使用 35x35 ),也可以使用系統(tǒng)圖標(biāo),如下:

typedef NS_ENUM(NSInteger, UIApplicationShortcutIconType) {
    UIApplicationShortcutIconTypeCompose,
    UIApplicationShortcutIconTypePlay,
    UIApplicationShortcutIconTypePause,
    UIApplicationShortcutIconTypeAdd,
    UIApplicationShortcutIconTypeLocation,
    UIApplicationShortcutIconTypeSearch,
    UIApplicationShortcutIconTypeShare,
    UIApplicationShortcutIconTypeProhibit       NS_ENUM_AVAILABLE_IOS(9_1),
    UIApplicationShortcutIconTypeContact        NS_ENUM_AVAILABLE_IOS(9_1),
    UIApplicationShortcutIconTypeHome           NS_ENUM_AVAILABLE_IOS(9_1),
    UIApplicationShortcutIconTypeMarkLocation   NS_ENUM_AVAILABLE_IOS(9_1),
    UIApplicationShortcutIconTypeFavorite       NS_ENUM_AVAILABLE_IOS(9_1),
    UIApplicationShortcutIconTypeLove           NS_ENUM_AVAILABLE_IOS(9_1),
    UIApplicationShortcutIconTypeCloud          NS_ENUM_AVAILABLE_IOS(9_1),
    UIApplicationShortcutIconTypeInvitation     NS_ENUM_AVAILABLE_IOS(9_1),
    UIApplicationShortcutIconTypeConfirmation   NS_ENUM_AVAILABLE_IOS(9_1),
    UIApplicationShortcutIconTypeMail           NS_ENUM_AVAILABLE_IOS(9_1),
    UIApplicationShortcutIconTypeMessage        NS_ENUM_AVAILABLE_IOS(9_1),
    UIApplicationShortcutIconTypeDate           NS_ENUM_AVAILABLE_IOS(9_1),
    UIApplicationShortcutIconTypeTime           NS_ENUM_AVAILABLE_IOS(9_1),
    UIApplicationShortcutIconTypeCapturePhoto   NS_ENUM_AVAILABLE_IOS(9_1),
    UIApplicationShortcutIconTypeCaptureVideo   NS_ENUM_AVAILABLE_IOS(9_1),
    UIApplicationShortcutIconTypeTask           NS_ENUM_AVAILABLE_IOS(9_1),
    UIApplicationShortcutIconTypeTaskCompleted  NS_ENUM_AVAILABLE_IOS(9_1),
    UIApplicationShortcutIconTypeAlarm          NS_ENUM_AVAILABLE_IOS(9_1),
    UIApplicationShortcutIconTypeBookmark       NS_ENUM_AVAILABLE_IOS(9_1),
    UIApplicationShortcutIconTypeShuffle        NS_ENUM_AVAILABLE_IOS(9_1),
    UIApplicationShortcutIconTypeAudio          NS_ENUM_AVAILABLE_IOS(9_1),
    UIApplicationShortcutIconTypeUpdate         NS_ENUM_AVAILABLE_IOS(9_1)
} API_AVAILABLE(ios(9.0)) API_UNAVAILABLE(tvos) API_UNAVAILABLE(macos);
3.1.3、監(jiān)聽主屏交互按鈕的點(diǎn)擊事件

設(shè)置好主屏交互的 item 后,我們剩下要做的就是在 app 內(nèi)監(jiān)聽 item 的點(diǎn)擊事件,此時(shí)需要用到之前設(shè)置 UIApplicationShortcutItemType 的唯一標(biāo)示符,通過唯一標(biāo)示符來判斷用戶點(diǎn)擊了哪個(gè) item,代碼如下:

- (void)application:(UIApplication *)application 
performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem 
completionHandler:(void (^)(BOOL))completionHandler {
    // 不管APP在后臺(tái)還是進(jìn)程被殺死,只要通過主屏快捷操作進(jìn)來的,都會(huì)調(diào)用這個(gè)方法
    NSLog(@"\n\r localizedTitle:%@ \n\r type:%@", shortcutItem.localizedTitle, shortcutItem.type);
}

3.2、預(yù)覽和跳轉(zhuǎn)

Peek and Pop 在操作上是使用一定力度按壓屏幕,觸發(fā) Peek 操作;在 Peek 狀態(tài)下,上劃喚出 Peek 快速操作( UIPreviewAction );Peek 狀態(tài)下,再次用更大力度按壓屏幕,轉(zhuǎn)場到預(yù)覽的控制器,效果如下圖:

3.2.1、Peek and Pop使用的相關(guān)說明
  • UIViewControllerPreviewingDelegate:觸發(fā) 3D Touch 的類,需要遵循該協(xié)議,并要實(shí)現(xiàn)協(xié)議中的方法;
  • UIPreviewActionPeek 狀態(tài)下,上劃喚出快速操作選項(xiàng)實(shí)例;
  • previewActionItemsPeek 狀態(tài)下,上劃喚出快速操作選項(xiàng)實(shí)例數(shù)組。在要被 Pop 出的控制器中覆寫 get 方法,返回一個(gè) UIPreviewAction 數(shù)組。
3.2.2、Peek and Pop使用步驟

3.2.2.1、遵循協(xié)議,并注冊代理
遵循 UIViewControllerPreviewingDelegate 協(xié)議,并在遵循 UIViewControllerPreviewingDelegate 協(xié)議的控制器中調(diào)用方法,方法如下:

- (id <UIViewControllerPreviewing>)registerForPreviewingWithDelegate:(id<UIViewControllerPreviewingDelegate>)delegate sourceView:(UIView *)sourceView;
  • 遵循協(xié)議
@interface ViewController () <UIViewControllerPreviewingDelegate>
@end
  • 注冊代理,并傳入響應(yīng) 3D Touch 的視圖,下面是部分代碼:
// 判斷是否支持3D Touch
    if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) {
        // 注冊代理,并傳入響應(yīng)3D Touch的視圖
        [self registerForPreviewingWithDelegate:self sourceView:cell];
    }

3.2.2.2、 實(shí)現(xiàn)UIViewControllerPreviewingDelegate協(xié)議的兩個(gè)方法

  • 當(dāng)系統(tǒng)檢測到 3D Touch 時(shí),它會(huì)調(diào)用 previewingContext:viewControllerForLocation 代理方法,傳遞一個(gè)符合 UIViewControllerPreviewing 協(xié)議的 previewingContext 對(duì)象。使用此方法配置并返回一個(gè)視圖控制器以進(jìn)行預(yù)覽。
- (nullable UIViewController *)previewingContext:(nonnull id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location {
    NSLog(@"%@", NSStringFromCGPoint(location));
    
    UITableViewCell *cell = (UITableViewCell *)previewingContext.sourceView;
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    
    XWTestViewController *vc = [[XWTestViewController alloc] init];
    vc.index = (indexPath.row % 2 == 0 ? 0 : 1);
    
    // 調(diào)整不被虛化的范圍,按壓的那個(gè)cell不被虛化(輕輕按壓時(shí)周邊會(huì)被虛化,再少用力展示預(yù)覽,再加力跳頁至設(shè)定界面)
//    CGRect rect = CGRectMake(0, 0, self.view.frame.size.width,200);
//    previewingContext.sourceRect = rect;
    return vc;
}
  • 當(dāng)系統(tǒng)察覺到足夠的壓力可以觸發(fā) 3D TouchPopViewController 時(shí),會(huì)調(diào)用 previewingContext:commitViewController: 代理方法:
- (void)previewingContext:(id<UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit {
    NSLog(@"%s", __func__);
    
    [self showViewController:viewControllerToCommit sender:self];
//    [self.navigationController pushViewController:viewControllerToCommit animated:YES];
}

3.2.2.3、 添加Peek狀態(tài)下,上劃時(shí)的快速操作
如果我們想在預(yù)覽的時(shí)候,想做一些操作,那我們可以在 Peek 狀態(tài)下,添加一些 Action 或者 Group,以提供快速操作。要添加快速操作,需要在預(yù)覽控制器中重寫 - (NSArray<id<UIPreviewActionItem>> *)previewActionItems 方法,示例代碼如下:

- (NSArray<id<UIPreviewActionItem>> *)previewActionItems {
    UIPreviewAction *action1 = [UIPreviewAction actionWithTitle:@"收藏" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
        NSLog(@"收藏");
    }];
    
    UIPreviewAction *action2 = [UIPreviewAction actionWithTitle:@"分享" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
        NSLog(@"分享");
    }];
    
    NSArray *actions = @[action1,action2];
    
    return actions;
}

至此,3D Touch 關(guān)于 主屏交互、預(yù)覽和跳轉(zhuǎn)(Peek and Pop) 的內(nèi)容就到此結(jié)束,LivePhoto的內(nèi)容開發(fā)中很少用到,所以就略去了,后續(xù)有時(shí)間的話,會(huì)專門寫一篇關(guān)于 LivePhoto 的文章補(bǔ)上。

四、Author

如果你有什么建議,可以關(guān)注我,直接留言,留言必回。

五、參考

iOS-3DTouch學(xué)習(xí)二:Peek & Pop
iOS開發(fā)之3D Touch詳解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容