3D Touch 详解

1,930 阅读5分钟

简介

3D TouchiPhone6s以上机型并且是iOS9及以上系统而引入的三维触控功能

作用:

  • 在主界面按主屏幕图标可以立即访问应用程序提供的功能
  • 在应用中,可以按视图查看其它内容得预览

开关设置:

在3D Touch设备上,可以在设置>通用>辅助功能>三维触控中选择开启或者关闭touch功能,以及设置灵敏度

主屏幕Touch

用户可以按住屏幕的应用图标启动touch提供的一组快速操作的功能,当用户选择其中某一项操作时,在appdelegate的应用委托中会收到回调响应的信息

目前最多支持应用显示四个主屏幕的快速操作,在限制的范围内,从菜单中的最顶部位置开始,系统首先显示静态快速操作。当添加了四个静态的快速操作后,即便添加动态快速操作也不会有任何响应。

有些应用中出现五项快捷操作。经过笔者的研究,分享应用的touch Item是上线后,系统统一为应用提供的功能,应用上线后系统为每一个应用提供了默认的分享touch功能

在应用首次启动之前,主屏幕仅显示程序的静态快捷操作,首次启动后,动态添加的操作也会显示。如果用户应用更新后尚未启动更新,则主屏幕的快捷操作会响应之前操作,这个时候UIApplicationShortcutItemUserInfo就起到了关键性的作用,因为该键中应定义应用版本的信息以响应不同版本的操作

设置Touch

设置静态的touch

实例:

item旗下支持的键:

  • UIApplicationShortcutItemType 描述启动项的秘钥(必填)
  • UIApplicationShortcutItemTitle item的名称(必填)
  • UIApplicationShortcutItemSubtitle item的辅助注释(选填)
  • UIApplicationShortcutItemIconType item中系统提供icon的选项(选填)
  • UIApplicationShortcutItemIconFile 指定项目的中资源icon文件(选填)大小为35x35 point
  • UIApplicationShortcutItemUserInfo 自定义的键值对(选填)

设置动态的touch

动态设置主要涉及一下两个类:
  • UIApplicationShortcutIcon
该类系统目前仅提供三个类方法
//使用系统定义的icon创建
+ (instancetype)iconWithType:(UIApplicationShortcutIconType)type;
//使用资源文件中的图片资源创建
+ (instancetype)iconWithTemplateImageName:(NSString *)templateImageName;
//使用联系人创建
+ (instancetype)iconWithContact:(CNContact *)contact;
  • UIApplicationShortcutItem
//仅定义启动项的秘钥以及名称
- (instancetype)initWithType:(NSString *)type localizedTitle:(NSString *)localizedTitle;

- (instancetype)initWithType:(NSString *)type 
              localizedTitle:(NSString *)localizedTitle 
           localizedSubtitle:(NSString *)localizedSubtitle 
                        icon:(UIApplicationShortcutIcon *)icon 
                    userInfo:(NSDictionary<NSString *,id<NSSecureCoding>> *)userInfo;
变换shortcutItem

可以通过UIApplicationShortcutItem设置可变的touch操作。动态设置的touch是可变的,apple中提供了变换Item的实例。

实例代码:

//该方法获取到的items其实是上次设置的项
NSArray <UIApplicationShortcutItem *> *existingShortcutItems = [[UIApplication sharedApplication] shortcutItems];

UIApplicationShortcutItem *existingShortcutItem = [existingShortcutItems firstObject];
NSMutableArray <UIApplicationShortcutItem *> *updatedShortcutItems = [existingShortcutItems mutableCopy];
UIMutableApplicationShortcutItem *mutableShortcutItem = [existingShortcutItem mutableCopy];
NSInteger index = [existingShortcutItems indexOfObject:existingShortcutItem];

[mutableShortcutItem setLocalizedTitle: @"New Title"];

[updatedShortcutItems replaceObjectAtIndex: index withObject: mutableShortcutItem];
[[UIApplication sharedApplication] setShortcutItems: updatedShortcutItems];

应用的响应操作

在Appdelegate中实现协议以驱动快捷操作的响应

- (void)application:(UIApplication *)application 
performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem 
  completionHandler:(void (^)(BOOL succeeded))completionHandler;
  
  完成操作后,应使用对应的布尔值完成处理程序

当应用程序未启动,此时通过快捷touch启动项目时:

系统会先回调- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions代理

然后再调用- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler的回调。

此种情况apple建议在didFinishLaunchingWithOptions中获取launchOptionsUIApplicationLaunchOptionsShortcutItemKey键值的相关信息以处理Touch的快捷启动,此时返回NO后,系统不会再回调- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler

快速预览

前期状态判断

在使用快速预览的时候,需要判断Touch的可用性,并且需要注意用在运行程序时关闭Touch功能

实例:

//遵守UITraitEnvironment协议

1.判断是否可用来决定的是否注册touch视图
if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) {
    //注册touch视图
}

2.监听Touch开关变化
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
    
}

相关API

  • UIViewController
//用户在Touch向上滑动时显示的快捷操作
@property(nonatomic, readonly) NSArray<id<UIPreviewActionItem>> *previewActionItems;

//注册视图参与Touch预览功能,指定源视图响应触摸
- (id<UIViewControllerPreviewing>)registerForPreviewingWithDelegate:(id<UIViewControllerPreviewingDelegate>)delegate 
                                                         sourceView:(UIView *)sourceView;

//取消注册的上下文标识
- (void)unregisterForPreviewingWithContext:(id<UIViewControllerPreviewing>)previewing;

  • UIViewControllerPreviewing
//sourceView的边界,动画启动的定位
@property(nonatomic) CGRect sourceRect;
//Touch手势
@property(nonatomic, readonly) UIGestureRecognizer *previewingGestureRecognizerForFailureRelationship;
//Delegate
@property(nonatomic, readonly) id<UIViewControllerPreviewingDelegate> delegate;
//源视图
@property(nonatomic, readonly) UIView *sourceView;
  • UIViewControllerPreviewingDelegate
/* 当用户在预览视图控制器中Touch的时候回调
 *
 *  previewingContext 预览视图控制器上下文对象
 *  location 触摸在源视图坐标系中的位置
 *  返回显示对应的控制器,可以通过返回nil,禁用预览
 */
- (UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext 
              viewControllerForLocation:(CGPoint)location;

//Touch响应点后的操作,一般推出需要显示的视图控制器
- (void)previewingContext:(id<UIViewControllerPreviewing>)previewingContext 
     commitViewController:(UIViewController *)viewControllerToCommit;

  • UIPreviewAction
/* 创建一个快捷操作
 *
 *  title 动作的标题
 *  style 快捷操作的类型
 */
+ (instancetype)actionWithTitle:(NSString *)title 
                          style:(UIPreviewActionStyle)style 
                        handler:(void (^)(UIPreviewAction *action, UIViewController *previewViewController))handler;

//快捷操作调用的快
@property(nonatomic, copy, readonly, nonnull) void (^handler)(id<UIPreviewActionItem> action, UIViewController *previewViewController);

  • UIPreviewActionGroup
/* 快捷操作组
 *
 *  title 组的标题
 *  style 组的类型
 */
+ (instancetype)actionGroupWithTitle:(NSString *)title 
                               style:(UIPreviewActionStyle)style 
                             actions:(NSArray<UIPreviewAction *> *)actions;
  • UIPreviewActionItem
//快速行动的标题
@property(nonatomic, copy, readonly) NSString *title;

具体实现步骤

  1. 先判断Touch开关状态以及监听开关状态的变化
  2. 需要预览的视图源控制遵守UIViewControllerPreviewingDelegate协议,并实现相关的代理
  3. 如果需要设置Touch预览向上滑动显示快捷操作,则在预览视图控制器设置previewActionItems属性即可

下载实例