之前在玩手機的時候,無意間長摁去年的前年的軟件時,竟然不支持3DTouch,于是想著有空學(xué)學(xué)3DTouch。在這篇文章中,我將參照官方API來整理一下3DTouch的一些使用方法和注意事項。
3D Touch簡介:
3D Touch是一種立體觸控技術(shù),被蘋果稱為新一代多點觸控技術(shù),是在Apple Watch上采用的Force Touch,屏幕可感應(yīng)不同的感壓力度觸控。3D Touch,蘋果iPhone 6s上的新功能,看起來類似 PC 上的右鍵。有Peek Pop 兩種新手勢。
2015年9月10日,蘋果在新品發(fā)布會上宣布了3D-Touch功能。 2016年6月13日,蘋果開發(fā)者大會WWDC在舊金山召開,會議宣布可以在待機畫面用3D Touch操作通知。
在官方文檔中,介紹了一下三點:
- Home screen quick action
- Peek and pop
- UITouch force properties
接下來我們將逐一學(xué)習(xí):
1.Home screen quick action
其實現(xiàn)方式可以分為Static quick actions
和Dynamic quick actions
;
1.1 Static quick actions
Static quick actions--靜態(tài)添加快捷菜單,通過操作plist文件來實現(xiàn):在plist文件中添加相對應(yīng)的key-value鍵值對(由于3DTuch功能不是APP的剛性需求,所以系統(tǒng)的plist文件并沒有附帶);
首先在plist文件中添加一個
UIApplicationShortcutItem
數(shù)組,在該數(shù)組中添加字典,字典內(nèi)鍵值對如下:
-UIApplicationShortcutItemType
必填! type為string類型,決定了點擊菜單后跳段到哪一個界面;
-UIApplicationShortcutItemTitle
必填! title為string類型,菜單的標(biāo)題
-UIApplicationShortcutItemSubtitle
subtitle為string類型,菜單的副標(biāo)題
-UIApplicationShortcutItemIconType
菜單左側(cè)的icon系統(tǒng)類型,系統(tǒng)內(nèi)有29種樣式,枚舉的前6種是通用的,后邊的23種是iOS9.1之后新增的;詳見API文檔
-UIApplicationShortcutItemIconFile
如果系統(tǒng)的29種icon樣式不能滿足我們的需求,我們也可以自定義icon樣式。添加UI提供的icon,填寫icon的名字即可;
下面通過兩張截圖來對比鍵值對添加之前和添加之后的plist文件:
未添加鍵值對的plist文件截圖如下:
已添加鍵值對的plist文件截圖如下:
1.2 Dynamic quick actions
Dynamic quick actions--動態(tài)添加快捷菜單。在了解了Static quick actions之后Dynamic quick actions就簡單了,Dynamic quick actions就是我們通過代碼來添加快捷菜單:
//在`didFinishLaunchingWithOptions`方法內(nèi)部添加代碼
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
/**
* 添加快捷菜單
*/
UIApplicationShortcutItem *item0 = [[UIApplicationShortcutItem alloc]initWithType:@"" localizedTitle:@"列表0"];
UIApplicationShortcutIcon *icon1 = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeShare];
UIApplicationShortcutItem *item1 = [[UIApplicationShortcutItem alloc]initWithType:@"" localizedTitle:@"列表1" localizedSubtitle:@"列表1-副標(biāo)題" icon:icon1 userInfo:nil];
UIApplicationShortcutIcon *icon2 = [UIApplicationShortcutIcon iconWithTemplateImageName:@"scan"];
UIApplicationShortcutItem *item2 = [[UIApplicationShortcutItem alloc]initWithType:@"" localizedTitle:@"列表2"localizedSubtitle:@"列表2-副標(biāo)題" icon:icon2 userInfo:nil];
[UIApplication sharedApplication].shortcutItems = @[item0,item1,item2];
return YES;
}
添加完畢之后長摁APP的效果圖如下:
寫到這里有心的同學(xué)可能注意到type的值是空的,那么點擊了“列表0”或者“列表1”之后會觸發(fā)什么響應(yīng)呢?以及響應(yīng)的方法是哪個呢?不要急靜靜的往下看:
/**
* 動態(tài)添加菜單列表
*/
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UIApplicationShortcutIcon *icon1 = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeShare];
UIApplicationShortcutItem *item1 = [[UIApplicationShortcutItem alloc]initWithType:@"share" localizedTitle:@"分享" localizedSubtitle:@"列表1-副標(biāo)題" icon:icon1 userInfo:nil];
UIApplicationShortcutIcon *icon2 = [UIApplicationShortcutIcon iconWithTemplateImageName:@"scan"];
UIApplicationShortcutItem *item2 = [[UIApplicationShortcutItem alloc]initWithType:@"scan" localizedTitle:@"掃一掃"localizedSubtitle:@"列表2-副標(biāo)題" icon:icon2 userInfo:nil];
[UIApplication sharedApplication].shortcutItems = @[item1,item2];
return YES;
}
/**
* 菜單item被點擊時,會觸發(fā)下面的方法
*/
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler
{
UITabBarController *tabVC = (UITabBarController *)self.window.rootViewController;
//為item指定跳轉(zhuǎn)界面(通過type值或者title值來綁定界面)
if ([shortcutItem.type isEqualToString:@"share"])
{
tabVC.selectedIndex = 0;//分享界面
}
else
{
tabVC.selectedIndex = 1;//掃一掃界面
}
}
注意點(如何應(yīng)對重度強迫癥的產(chǎn)品經(jīng)理):
- 快捷菜單彈出方向:當(dāng)你的APP圖標(biāo)位于手機桌面的上半部分,快捷菜單是向下彈出的;同理APP圖標(biāo)位于下半部分則快捷菜單是向上彈出的;
- 菜單的Icon位置:當(dāng)你的APP圖標(biāo)位于手機桌面的左半部分,icon圖標(biāo)位于菜單最左側(cè);同理APP圖標(biāo)位于右半部分則icon圖標(biāo)位于菜單最右側(cè);
2.Peek and pop
2.1 peek--輕摁預(yù)覽
在微信的聊天列表里,我們輕摁與某一個朋友的聊天(PS:6s之前的手機屏幕摁破別打我),在屏幕上就會彈出一個呈現(xiàn)聊天內(nèi)容的界面----這個場景就是官方所說的peek的一個應(yīng)用場景;
在講解之前我們先來思考下面的幾個問題:
- Q1.cell輕摁可以彈出預(yù)覽界面,那么在配置cell的cellForRow方法內(nèi)部是不是有所不同?
- Q2.輕摁cell彈出的預(yù)覽界面,是不是應(yīng)該寫在didSelectedRow方法內(nèi)部呢?
- Q3.輕摁cell彈出的預(yù)覽界面被向上或向下拖拽之后,觸發(fā)的“標(biāo)為未讀”、”“刪除”是在當(dāng)前界面配置還是在預(yù)覽界面配置呢?
下面通過一個小demo結(jié)合代碼來講解:
demo功能:在tableView頁面上有一個網(wǎng)址的列表,輕摁之后彈出網(wǎng)址預(yù)覽界面;彈出預(yù)覽界面之后重摁則跳轉(zhuǎn)到詳情界面;
基礎(chǔ)界面tableView的搭建代碼就省略了,直接上關(guān)鍵點:
第一步:要讓cell有按壓效果,需要在cellForRow方法內(nèi)部注冊cell支持預(yù)覽的協(xié)議:UIViewControllerPreviewingDelegate
(自然TableviewController
要遵守該協(xié)議)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
......
/**
* 關(guān)鍵語句:告知系統(tǒng)該cell按壓有peek效果
*/
[self registerForPreviewingWithDelegate:self sourceView:cell];
return cell;
}
第二步:cell支持按壓,那么按壓之后呈現(xiàn)什么控制器呢?UIViewControllerPreviewingDelegate
的第一個方法
- (nullable UIViewController *)previewingContext:(id <UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location
就是解決這個問題(方法的返回值為UIViewController
)
- (nullable UIViewController *)previewingContext:(id <UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location
{
WebViewController *webVC = [[WebViewController alloc]init];
//根據(jù)location來獲取到當(dāng)前所點擊的cell的row
location = [self.tableView convertPoint:location fromView:[previewingContext sourceView]];//轉(zhuǎn)換參考系
NSIndexPath *path = [self.tableView indexPathForRowAtPoint:location];
webVC.url = self.dataArray[path.row][@"html"];
return webVC;
}
注意點:上邊方法中的location是以cell為sourceView-參考系得到的坐標(biāo),而我們所需要的是以tableView為參考系的坐標(biāo),所以要對location進行轉(zhuǎn)換;--下接2.2
2.2 pop--重摁跳轉(zhuǎn)
第三步:在預(yù)覽界面已呈現(xiàn)之后,大力摁壓跳轉(zhuǎn)到詳情界面是在UIViewControllerPreviewingDelegate
的另一個方法內(nèi)實現(xiàn)
- (void)previewingContext:(id <UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit
- {
viewControllerToCommit.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:viewControllerToCommit animated:YES];
}
接下來,拖拽預(yù)覽界面觸發(fā)響應(yīng)的代碼是要在詳情控制器里來書寫;
- (NSArray<id<UIPreviewActionItem>> *)previewActionItems
{
//創(chuàng)建贊操作
UIPreviewAction *item0 = [UIPreviewAction actionWithTitle:@"贊" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
//此處block代碼塊為點擊“贊”操作的響應(yīng)代碼
NSLog(@"點贊---------------------");
}];
//創(chuàng)建舉報操作
UIPreviewAction *item1 = [UIPreviewAction actionWithTitle:@"舉報" style:UIPreviewActionStyleSelected handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"舉報=====================");
}];
return @[item0,item1];
}
下面附上效果圖:
3.UITouch force properties
Force properties是在iOS 9.0之后UITouch新增的一個屬性,簡單來說系統(tǒng)可以撲捉到手指在屏幕的壓力值(開個腦洞:會不會有哪個土豪搞n多個6s來測體重?)
關(guān)于Force properties比較簡單,但是通常會和貝賽爾曲線結(jié)合起來做一些涂鴉畫板之類的APP,這里就不再贅述了。我只是檢測了一下壓力的峰值:
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
UITouch *touch = touches.anyObject;
NSLog(@"壓力值為:%f",touch.force);
}
OK,關(guān)于3D Touch就這么多了附上官方文檔,有什么不對的希望指出來,共同進步。