之前在玩手机的时候,无意间长摁去年的前年的软件时,竟然不支持3DTouch,于是想着有空学学3DTouch。在这篇文章中,我将参照官方API来整理一下3DTouch的一些使用方法和注意事项。
3D Touch简介:
3D Touch是一种立体触控技术,被苹果称为新一代多点触控技术,是在Apple Watch上采用的Force Touch,屏幕可感应不同的感压力度触控。3D Touch,苹果iPhone 6s上的新功能,看起来类似 PC 上的右键。有Peek Pop 两种新手势。
2015年9月10日,苹果在新品发布会上宣布了3D-Touch功能。 2016年6月13日,苹果开发者大会WWDC在旧金山召开,会议宣布可以在待机画面用3D Touch操作通知。
在官方文档中,介绍了一下三点:
- Home screen quick action
- Peek and pop
- UITouch force properties
接下来我们将逐一学习:
1.Home screen quick action
其实现方式可以分为Static quick actions
和Dynamic quick actions
;
1.1 Static quick actions
Static quick actions--静态添加快捷菜单,通过操作plist文件来实现:在plist文件中添加相对应的key-value键值对(由于3DTuch功能不是APP的刚性需求,所以系统的plist文件并没有附带);
首先在plist文件中添加一个
UIApplicationShortcutItem
数组,在该数组中添加字典,字典内键值对如下:
-UIApplicationShortcutItemType
必填! type为string类型,决定了点击菜单后跳段到哪一个界面;
-UIApplicationShortcutItemTitle
必填! title为string类型,菜单的标题
-UIApplicationShortcutItemSubtitle
subtitle为string类型,菜单的副标题
-UIApplicationShortcutItemIconType
菜单左侧的icon系统类型,系统内有29种样式,枚举的前6种是通用的,后边的23种是iOS9.1之后新增的;详见API文档
-UIApplicationShortcutItemIconFile
如果系统的29种icon样式不能满足我们的需求,我们也可以自定义icon样式。添加UI提供的icon,填写icon的名字即可;
下面通过两张截图来对比键值对添加之前和添加之后的plist文件:
未添加键值对的plist文件截图如下:
已添加键值对的plist文件截图如下:
已添加键值对
1.2 Dynamic quick actions
Dynamic quick actions--动态添加快捷菜单。在了解了Static quick actions之后Dynamic quick actions就简单了,Dynamic quick actions就是我们通过代码来添加快捷菜单:
//在`didFinishLaunchingWithOptions`方法内部添加代码
- (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-副标题" icon:icon1 userInfo:nil];
UIApplicationShortcutIcon *icon2 = [UIApplicationShortcutIcon iconWithTemplateImageName:@"scan"];
UIApplicationShortcutItem *item2 = [[UIApplicationShortcutItem alloc]initWithType:@"" localizedTitle:@"列表2"localizedSubtitle:@"列表2-副标题" icon:icon2 userInfo:nil];
[UIApplication sharedApplication].shortcutItems = @[item0,item1,item2];
return YES;
}
添加完毕之后长摁APP的效果图如下:
长摁效果图写到这里有心的同学可能注意到type的值是空的,那么点击了“列表0”或者“列表1”之后会触发什么响应呢?以及响应的方法是哪个呢?不要急静静的往下看:
/**
* 动态添加菜单列表
*/
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UIApplicationShortcutIcon *icon1 = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeShare];
UIApplicationShortcutItem *item1 = [[UIApplicationShortcutItem alloc]initWithType:@"share" localizedTitle:@"分享" localizedSubtitle:@"列表1-副标题" icon:icon1 userInfo:nil];
UIApplicationShortcutIcon *icon2 = [UIApplicationShortcutIcon iconWithTemplateImageName:@"scan"];
UIApplicationShortcutItem *item2 = [[UIApplicationShortcutItem alloc]initWithType:@"scan" localizedTitle:@"扫一扫"localizedSubtitle:@"列表2-副标题" icon:icon2 userInfo:nil];
[UIApplication sharedApplication].shortcutItems = @[item1,item2];
return YES;
}
/**
* 菜单item被点击时,会触发下面的方法
*/
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler
{
UITabBarController *tabVC = (UITabBarController *)self.window.rootViewController;
//为item指定跳转界面(通过type值或者title值来绑定界面)
if ([shortcutItem.type isEqualToString:@"share"])
{
tabVC.selectedIndex = 0;//分享界面
}
else
{
tabVC.selectedIndex = 1;//扫一扫界面
}
}
注意点(如何应对重度强迫症的产品经理):
- 快捷菜单弹出方向:当你的APP图标位于手机桌面的上半部分,快捷菜单是向下弹出的;同理APP图标位于下半部分则快捷菜单是向上弹出的;
- 菜单的Icon位置:当你的APP图标位于手机桌面的左半部分,icon图标位于菜单最左侧;同理APP图标位于右半部分则icon图标位于菜单最右侧;
2.Peek and pop
2.1 peek--轻摁预览
在微信的聊天列表里,我们轻摁与某一个朋友的聊天(PS:6s之前的手机屏幕摁破别打我),在屏幕上就会弹出一个呈现聊天内容的界面----这个场景就是官方所说的peek的一个应用场景;
在讲解之前我们先来思考下面的几个问题:
- Q1.cell轻摁可以弹出预览界面,那么在配置cell的cellForRow方法内部是不是有所不同?
- Q2.轻摁cell弹出的预览界面,是不是应该写在didSelectedRow方法内部呢?
- Q3.轻摁cell弹出的预览界面被向上或向下拖拽之后,触发的“标为未读”、”“删除”是在当前界面配置还是在预览界面配置呢?
下面通过一个小demo结合代码来讲解:
demo功能:在tableView页面上有一个网址的列表,轻摁之后弹出网址预览界面;弹出预览界面之后重摁则跳转到详情界面;
基础界面tableView的搭建代码就省略了,直接上关键点:
第一步:要让cell有按压效果,需要在cellForRow方法内部注册cell支持预览的协议:UIViewControllerPreviewingDelegate
(自然TableviewController
要遵守该协议)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
......
/**
* 关键语句:告知系统该cell按压有peek效果
*/
[self registerForPreviewingWithDelegate:self sourceView:cell];
return cell;
}
第二步:cell支持按压,那么按压之后呈现什么控制器呢?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];
//根据location来获取到当前所点击的cell的row
location = [self.tableView convertPoint:location fromView:[previewingContext sourceView]];//转换参考系
NSIndexPath *path = [self.tableView indexPathForRowAtPoint:location];
webVC.url = self.dataArray[path.row][@"html"];
return webVC;
}
注意点:上边方法中的location是以cell为sourceView-参考系得到的坐标,而我们所需要的是以tableView为参考系的坐标,所以要对location进行转换;--下接2.2
2.2 pop--重摁跳转
第三步:在预览界面已呈现之后,大力摁压跳转到详情界面是在UIViewControllerPreviewingDelegate
的另一个方法内实现
- (void)previewingContext:(id <UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit
- {
viewControllerToCommit.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:viewControllerToCommit animated:YES];
}
接下来,拖拽预览界面触发响应的代码是要在详情控制器里来书写;
- (NSArray<id<UIPreviewActionItem>> *)previewActionItems
{
//创建赞操作
UIPreviewAction *item0 = [UIPreviewAction actionWithTitle:@"赞" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
//此处block代码块为点击“赞”操作的响应代码
NSLog(@"点赞---------------------");
}];
//创建举报操作
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新增的一个属性,简单来说系统可以扑捉到手指在屏幕的压力值(开个脑洞:会不会有哪个土豪搞n多个6s来测体重?)
关于Force properties比较简单,但是通常会和贝赛尔曲线结合起来做一些涂鸦画板之类的APP,这里就不再赘述了。我只是检测了一下压力的峰值:
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
UITouch *touch = touches.anyObject;
NSLog(@"压力值为:%f",touch.force);
}
打印压力峰值
OK,关于3D Touch就这么多了附上官方文档,有什么不对的希望指出来,共同进步。
网友评论