一、3D Touch 簡介
1.什么是3D Touch?
3D Touch是一種立體觸控技術,被蘋果稱為新一代多點觸控技術,是在Apple Watch上采用的Force Touch,屏幕可感應不同的感壓力度觸控。目前支持3D Touch的蘋果設備有很多,如果iPhone6s或以上,iOS9或以上等。
2.3D Touch主要有什么功能?
(1)創(chuàng)建喚醒應用某個功能的捷徑
(2)提供了peek預覽和pop跳轉新手勢
(3)檢測壓力值等。
二、給自己的應用添加3D Touch功能
1.創(chuàng)建喚醒應用某個功能的捷徑
給主屏幕應用的Icon添加快捷選項卡,我自己測試了一下最多只顯示4個快捷選項卡,但是我測試了一下樂視視屏app有5個快捷選項卡,其實不必在意這個,一般四個已經能夠滿足大多數(shù)的應用了,
添加快捷選項卡的方法有兩種:
(1)使用plist文件添加,添加如下項

UIApplicationShortcutItems:數(shù)組中的元素就是我們的那些快捷選項標簽。
UIApplicationShortcutItemTitle:標簽標題(必填)
UIApplicationShortcutItemType:標簽的唯一標識(必填)
UIApplicationShortcutItemIconType:使用系統(tǒng)圖標的類型,如搜索、定位、home等(可選)
UIApplicationShortcutItemIconFile:使用項目中的圖片作為標簽圖標(可選)
UIApplicationShortcutItemSubtitle:標簽副標題(可選)
UIApplicationShortcutItemUserInfo:字典信息,如傳值使用(可選)
(2)代碼添加,在
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 方法中創(chuàng)建快捷選項卡
/**
創(chuàng)建icon上的3D touch快捷選項
*/
-(void)createShortcutItem:(UIApplication *)application
{
//創(chuàng)建系統(tǒng)風格的icon
UIApplicationShortcutIcon *systemIcon = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeShare];
//創(chuàng)建快捷選項Item,type是用來區(qū)分選項卡的
UIApplicationShortcutItem *item1 = [[UIApplicationShortcutItem alloc]initWithType:tShareType localizedTitle:@"分享" localizedSubtitle:@"分享微信" icon:systemIcon userInfo:nil];
//創(chuàng)建自定義圖片的icon
UIApplicationShortcutIcon *customIcon = [UIApplicationShortcutIcon iconWithTemplateImageName:@"1.png"];
UIApplicationShortcutItem *item2 = [[UIApplicationShortcutItem alloc]initWithType:tSearchType localizedTitle:@"搜索" localizedSubtitle:@"搜索啥呢" icon:customIcon userInfo:nil];
//添加到快捷選項數(shù)組
application.shortcutItems = @[item1,item2];
}
目前我們達到的效果是:
創(chuàng)建快捷選項卡之后,我們如何監(jiān)聽用戶的點擊事件呢?
不管程序是在后臺還是被殺死,當用戶點擊我們創(chuàng)建的快捷選項卡之后都會觸發(fā)方法
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler?
那么我們只需要在這個方法處理點擊事件就可以了。
區(qū)分具體是哪個快捷選項卡是根據shortcutItem的type屬性,
現(xiàn)在來實現(xiàn)這里的邏輯
UINavigationController *nav = (UINavigationController *)self.window.rootViewController ;
if ([shortcutItem.type isEqualToString:tShareType]) {
//點擊了分享
[nav pushViewController:[ShareViewController new] animated:YES];
}else if ([shortcutItem.type isEqualToString:tSearchType])
{
//點擊了搜索
[nav pushViewController:[SearchViewController new] animated:YES];
}
if (completionHandler) {
completionHandler(YES);
}
到這里快捷選項卡創(chuàng)建和邏輯處理就結束了,讀者可以自己體驗下效果。
那么如果動態(tài)的修改這些選項卡的屬性呢?
以修改標題為例,在任何你想修改的地方添加以下代碼即可
UIApplication *application = [UIApplication sharedApplication];
//要修改的那個Item
UIApplicationShortcutItem *item = application.shortcutItems[0];
//可變復制Item
UIMutableApplicationShortcutItem *mutableItem = [item mutableCopy];
//修改可變Item的屬性
[mutableItem setLocalizedTitle:@"要修改的標題"];
//可變復制Item數(shù)組
NSMutableArray *items = [application.shortcutItems mutableCopy];
//替換原來的Item
[items replaceObjectAtIndex:0 withObject:mutableItem];
//重置application的items
application.shortcutItems = items;
2.peek預覽和pop跳轉
這里以給表格的單元格添加此功能為例,首先給cell注冊3DTouch的peek(預覽)和pop功能
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:tCellReuserId];
cell.textLabel.text = [NSString stringWithFormat:@"%ld-%ld",(long)indexPath.section,(long)indexPath.row];
//給cell注冊3D Touch的peek和pop功能
if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
{
[self registerForPreviewingWithDelegate:self sourceView:cell];
}else
{
NSLog(@"3D Touch 不可用");
}
return cell;
}
需要實現(xiàn)UIViewControllerPreviewingDelegate的代理方法
/** UIViewControllerPreviewingDelegate方法 peek預覽 @param previewingContext 預覽上下文 @param location location @return vc */ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? -(nullable UIViewController *)previewingContext:(id)previewingContext viewControllerForLocation:(CGPoint)location{ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //獲取按壓的cell ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?UITableViewCell *cell = (UITableViewCell *)[previewingContext sourceView];? ? NSIndexPath *indexPath = [_tableView indexPathForCell:cell]; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //設定預覽界面 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? SearchViewController *searchVc = [[SearchViewController alloc]init];? ? searchVc.preferredContentSize = CGSizeMake(0, 500); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?searchVc.index = [NSString stringWithFormat:@"%ld,用力按一下進來",(long)indexPath.row]; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //調整不被虛化的范圍,按壓的那個cell不被虛化(輕輕按壓時周邊會被虛化,再少用力展示預覽,再加力跳頁至設定界面) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? CGRect rect = CGRectMake(0, 0, self.view.frame.size.width,44);? ? previewingContext.sourceRect = rect; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //返回預覽界面 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return searchVc;} ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /** 進入預覽vc @param previewingContext 預覽上下文 @param viewControllerToCommit 進入的vc */ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? -(void)previewingContext:(id)previewingContext commitViewController:(UIViewController *)viewControllerToCommit
{
[self showViewController:viewControllerToCommit sender:self];
}
實現(xiàn)的效果:
當用戶按下時cell周邊會虛化,增加壓力達到一定值會彈出設定的預覽界面,繼續(xù)增加力按壓會跳頁至預覽界面,并把值傳遞過去
如果我們在預覽視圖中添加如下代碼
//當彈出本預覽時,上滑預覽視圖,出現(xiàn)預覽視圖中快捷選項- (NSArray> *)previewActionItems {
// setup a list of preview actions
UIPreviewAction *action1 = [UIPreviewAction actionWithTitle:@"Aciton1" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"Aciton1");
}];
UIPreviewAction *action2 = [UIPreviewAction actionWithTitle:@"Aciton2" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"Aciton2");
}];
UIPreviewAction *action3 = [UIPreviewAction actionWithTitle:@"Aciton3" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"Aciton3");
}];
NSArray *actions = @[action1,action2,action3];
// and return them (return the array of actions instead to see all items ungrouped)
return actions;
}
那么當彈出預覽時,上滑預覽視圖,出現(xiàn)預覽視圖中快捷選項。
3.檢測壓力值
//按住移動or壓力值改變時的回調
-(void)touchesMoved:(NSSet*)touches withEvent:(UIEvent *)event {
NSArray *arrayTouch = [touches allObjects];
UITouch *touch = (UITouch *)[arrayTouch lastObject];
//紅色背景的label顯示壓力值
_label.text = [NSString stringWithFormat:@"壓力%f",touch.force];
//紅色背景的label.y=壓力值*100
_label.frame = CGRectMake(100, touch.force * 100, 300, 40);
}
按壓屏幕,隨著壓力值的變化紅色的label會上下移動,并顯示當前壓力值。