简介
iPhone 6s开始添加压力传感器和Taptic Engine线性震动器实现了 3D Touch功能(iPhone 6机器可通过越狱安装插件的方式也能模拟3D Touch功能)。
在iPhone 6s以上iOS 9系统中利用不同力度按下主屏中的icon图标时可弹出应用程序提供的功能,在应用程序中用户可以点击视图时可以看到更多内容预览和获得加速访问方法。
功能实现
第一部分(主屏快捷方式)
通过3D Touch手势点击主屏幕上的应用Icon处,可以快速进入对应的功能模块。
*iOS9为我们提供了两种屏幕标签(
每个App最多显示4个
),分别是静态标签
和动态标签
支持动态和静态标签同时存在并不会冲突,给UIApplication的shortcutItems数组赋值时不会覆盖静态标签
。
静态标签
需要在你app的Info.plist中添加UIApplicationShortcutItems数组,这个数组添加的每个元素对应静态标签,在每个标签中添加设置项。
必填项
UIApplicationShortcutItemType 这个键值设置一个快捷通道类型的字符串
UIApplicationShortcutItemTitle 这个键值设置标签的标题
选填项
UIApplicationShortcutItemSubtitle 设置标签的子标题、在title下方以小文字显示
UIApplicationShortcutItemIconType 设置标签图标枚举、系统的样式
typedef NS_ENUM(NSInteger, UIApplicationShortcutIconType) {
UIApplicationShortcutIconTypeCompose,//编辑的图标
UIApplicationShortcutIconTypePlay,//播放图标
UIApplicationShortcutIconTypePause,//暂停图标
UIApplicationShortcutIconTypeAdd,//添加图标
UIApplicationShortcutIconTypeLocation,//定位图标
UIApplicationShortcutIconTypeSearch,//搜索图标
UIApplicationShortcutIconTypeShare//分享图标
} NS_ENUM_AVAILABLE_IOS(9_0);
UIApplicationShortcutItemIconFile 设置自定义标签图标、大小为 35*35 的单一颜色样式呈现、 如果设置此项 UIApplicationShortcutItemIconType 将会失效
UIApplicationShortcutItemUserInfo 设置信息字典的形式 key : value(用于传值)
动态标签
动态标签与之相关的类主要有三个:
UIApplicationShortcutItem 创建3D Touch标签
UIMutableApplicationShortcutItem 创建可变的3D Touch标签
UIApplicationShortcutIcon 创建标签中图片icon
动态添加方法:
动态添加标签需要在 application didFinishLachingWithOption: 方法中实现
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//设置动态标签
UIApplicationShortcutItem * item = [[UIApplicationShortcutItem alloc] initWithType:@"Home" localizedTitle:@"动态标签" localizedSubtitle:nil icon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeHome] userInfo:nil];
[UIApplication sharedApplication].shortcutItems = @[item];
return YES;
}```
###设置快速进入
AppDelegate中新加的一个代理方法来处理用户点击item后的操作
pragma mark 3D Touch
- (void)application:(UIApplication *)application performActionForShortcutItem:(nonnull UIApplicationShortcutItem *)shortcutItem completionHandler:(nonnull void (^)(BOOL))completionHandler{
//照相type
if ([shortcutItem.type isEqualToString:@"Camera"]) {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self.window.rootViewController presentViewController:picker animated:YES completion:nil];
}
}```
第二部分(Peek and Pop)
通过3D Touch手势操作View时可以快速预览加载信息,可提高app交互性,使用起来更高效。
Peek and Pop是一套全新的用户交互机制,在使用3D Touch时ViewController中会有如下三个交互阶段:
-
提示用户这里有3D Touch的交互,会使交互控件周围模糊
-
继续深按,会出现预览视图
-
通过视图上的交互控件进行进一步交互
在iOS9中添加了UIForceTouchCapability
UIForceTouchCapabilityUnknown //3D Touch检测失败
UIForceTouchCapabilityUnavailable //3D Touch不可用
UIForceTouchCapabilityAvailable //3D Touch可用
#pragma mark 检测3D Touch
- (void)check3DTouch {
if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) {
//在self下创建一个新的3D Touch预览功能
[self registerForPreviewingWithDelegate:(id)self sourceView:_peekLB];
}
}```
如果用户有意修改了设备的3D Touch功能,请重新检测
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
[self check3DTouch];
}```
设置UIViewControllerPreviewingDelegate
#pragma mark - UIViewControllerPreviewingDelegate
- (nullable UIViewController *)previewingContext:(id <UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location{
//3D Touch防止重复加入
if ([self.presentedViewController isKindOfClass:[PHMPeekViewController class]]) {
return nil;
}else {
//触发预览功能时返回peekViewController
PHMPeekViewController *peekViewController = [[PHMPeekViewController alloc] init];
return peekViewController;
}
}
//深入点击后转入PHMPopViewController
- (void)previewingContext:(id <UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit {
PHMPopViewController *popViewController = [[PHMPopViewController alloc] init];
[self showDetailViewController:popViewController sender:self];
//Push Navigation
//[self showViewController:popViewController sender:self];
}```
在PHMPeekViewController视图上可以自定义添加交互控件(PreviewActionItem)
-
(NSArray<id<UIPreviewActionItem>> *)previewActionItems{
//生成UIPreviewAction
UIPreviewAction *action1 = [UIPreviewAction actionWithTitle:@"Action 1" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"Action 1 selected");
}];UIPreviewAction *action2 = [UIPreviewAction actionWithTitle:@"Action 2" style:UIPreviewActionStyleDestructive handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"Action 2 selected");
}];UIPreviewAction *tap = [UIPreviewAction actionWithTitle:@"Pop View" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
PHMPopViewController *popViewController = [[PHMPopViewController alloc] init];
[[UIApplication sharedApplication].delegate.window.rootViewController presentViewController:popViewController animated:YES completion:nil];
}];//生成Action Group
UIPreviewActionGroup *group1 = [UIPreviewActionGroup actionGroupWithTitle:@"Preview Action Group" style:UIPreviewActionStyleDefault actions:@[action1, action2]];//生成Action Group
return @[group1,tap];
}```
第三部分(触摸力度属性)
在iOS 9中UITouch类有两个新的属性(触摸力度force
及力度的最大值maximumPossibleForce
)来支持自定义实现app功能 。
force 范围:0~20/3
maximumPossibleForce 最大值:20/3
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
_peekLB.backgroundColor = [UIColor colorWithRed:0 green:0 blue:(touch.force / touch.maximumPossibleForce ) alpha:1];
}```
##第四部分 UIPreviewInteraction(iOS 10 新增)
>可以在类上添加UIPreviewInteractionDelegate 让其能反馈更真实的3D Touch数值,此功能开辟了新的可能性,让你的应用程序更加身临其境。
![UIPreviewInteraction](http://upload-images.jianshu.io/upload_images/2529977-c4401c492c1f53b5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
- (void)previewInteraction:(UIPreviewInteraction *)previewInteraction
didUpdatePreviewTransition:(CGFloat)transitionProgress
ended:(BOOL)ended UIKIT_AVAILABLE_IOS_ONLY(10_0) - (void)previewInteraction:(UIPreviewInteraction *)previewInteraction
didUpdateCommitTransition:(CGFloat)transitionProgress
ended:(BOOL)ended UIKIT_AVAILABLE_IOS_ONLY(10_0)```
这两个代理的区别联系如下图
上半部分为didUpdatePreviewTransition按压区域ended为YES时会跳转到didUpdateCommitTransition代理中继续执行,
下半部分为didUpdateCommitTransition按压区域ended为YES时会提交最终事务 。
previewInteraction的取值范围都是0到1之间。
3D Touch在delegate中的反馈如下
#pragma mark UIPreviewInteractionDelegate
//开始3D Touch交互
- (BOOL)previewInteractionShouldBegin:(UIPreviewInteraction *)previewInteraction UIKIT_AVAILABLE_IOS_ONLY(10_0){
return YES;
}
//transitionProgress 范围 0 - 1
- (void)previewInteraction:(UIPreviewInteraction *)previewInteraction
didUpdatePreviewTransition:(CGFloat)transitionProgress
ended:(BOOL)ended UIKIT_AVAILABLE_IOS_ONLY(10_0) {
if(ended){
NSLog(@"didUpdatePreviewended");
_popLB.backgroundColor = [UIColor colorWithRed:255 green:0 blue:0 alpha:1];
_popLB.textColor = [UIColor whiteColor];
}else{
_popLB.backgroundColor = [UIColor colorWithRed:255*transitionProgress/255 green:0 blue:0 alpha:1];
}
}
//transitionProgress 范围 0 - 1
- (void)previewInteraction:(UIPreviewInteraction *)previewInteraction
didUpdateCommitTransition:(CGFloat)transitionProgress
ended:(BOOL)ended UIKIT_AVAILABLE_IOS_ONLY(10_0){
if(ended){
NSLog(@"didUpdateCommitended");
_popLB.backgroundColor = [UIColor colorWithRed:255 green:255 blue:255 alpha:1];
_popLB.textColor = [UIColor blackColor];
}else{
_popLB.backgroundColor = [UIColor colorWithRed:255 green:0 blue:255*transitionProgress/255 alpha:1];
}
}
//取消3D Touch交互
- (void)previewInteractionDidCancel:(UIPreviewInteraction *)previewInteraction UIKIT_AVAILABLE_IOS_ONLY(10_0) {
_popLB.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1];
_popLB.textColor = [UIColor whiteColor];
}```
#测试Demo地址
---
[ForceTouch Demo](https://github.com/callhm/PHMDemo)
#官方链接地址
---
[人机界面指南](https://developer.apple.com/ios/human-interface-guidelines/interaction/3d-touch/)
[学习3D Touch](https://developer.apple.com/library/prerelease/content/documentation/UserExperience/Conceptual/Adopting3DTouchOniPhone/)