ios 3D Touch功能的实现
ios9中3D Touch功能是一个新的亮点,这个方便快捷的功能实现也比较简单,废话不多说直接上代码,
一.3D Touch功能添加分为两种(1).静态标签 (2).动态标签
(1).静态添加
这个方法是在app的plist文件中添加如下图的键值对,
先添加了一个UIApplicationShortcutItems的数组,这个数组中添加的元素就是对应的静态标签,在每个标签中我们需要添加一些设置的键值:
必填项(下面两个键值是必须设置的):
UIApplicationShortcutItemType 这个键值设置一个快捷通道类型的字符串
UIApplicationShortcutItemTitle 这个键值设置标签的标题
选填项(下面这些键值不是必须设置的):
UIApplicationShortcutItemSubtitle 设置标签的副标题
UIApplicationShortcutItemIconType 设置标签Icon类型
UIApplicationShortcutItemIconFile 设置标签的Icon文件
UIApplicationShortcutItemUserInfo 设置信息字典(用于传值)
(2).动态标签
动态标签是我们在程序运行过程中动态添加上去的,可以修改或者直接取消,与之相关的类,主要有三个:
UIApplicationShortcutItem 创建3DTouch标签的类
UIMutableApplicationShortcutItem 创建可变的3DTouch标签的类
UIApplicationShortcutIcon 创建标签中图片Icon的类
@interface UIApplicationShortcutItem : NSObject <NSCopying, NSMutableCopying> //下面是两个初始化方法 通过设置type,title等属性来创建一个标签,这里的icon是UIApplicationShortcutIcon对象,我们后面再说 - (instancetype)initWithType:(NSString *)type localizedTitle:(NSString *)localizedTitle localizedSubtitle:(nullable NSString *)localizedSubtitle icon:(nullable UIApplicationShortcutIcon *)icon userInfo:(nullable NSDictionary *)userInfo NS_DESIGNATED_INITIALIZER; - (instancetype)initWithType:(NSString *)type localizedTitle:(NSString *)localizedTitle; //下面这是一些只读的属性,获取相应的属性值 @property (nonatomic, copy, readonly) NSString *type; @property (nonatomic, copy, readonly) NSString *localizedTitle; @property (nullable, nonatomic, copy, readonly) NSString *localizedSubtitle; @property (nullable, nonatomic, copy, readonly) UIApplicationShortcutIcon *icon; @property (nullable, nonatomic, copy, readonly) NSDictionary<NSString *, id <NSSecureCoding>> *userInfo;
接下来就是创建标签
/** * 手动添加3D touch功能 */ -(void)init3DTouchActionShow:(BOOL)isShow{ /** type 该item 唯一标识符 localizedTitle :标题 localizedSubtitle:副标题 icon:icon图标 可以使用系统类型 也可以使用自定义的图片 userInfo:用户信息字典 自定义参数,完成具体功能需求 */ UIApplication *application = [UIApplication sharedApplication]; UIApplicationShortcutIcon *icon1 = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeLove]; UIApplicationShortcutItem *item1 = [[UIApplicationShortcutItem alloc]initWithType:KTouchItemPublicPosition localizedTitle:@"我就是我" localizedSubtitle:@"还有什么" icon:icon1 userInfo:nil]; UIApplicationShortcutIcon *icon2 = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeShare]; UIApplicationShortcutItem *item2 = [[UIApplicationShortcutItem alloc]initWithType:KTouchItemMyPublic localizedTitle:@"你就是你" localizedSubtitle:@"你知道" icon:icon2 userInfo:nil]; UIApplicationShortcutIcon *icon3 = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeCompose]; UIApplicationShortcutItem *item3 = [[UIApplicationShortcutItem alloc]initWithType:KTouchItemRecharge localizedTitle:@"他就是他" localizedSubtitle:@"我不知道" icon:icon3 userInfo:nil]; UIApplicationShortcutIcon *icon4 = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeCompose]; UIApplicationShortcutItem *item4 = [[UIApplicationShortcutItem alloc]initWithType:KTouchItemCheck localizedTitle:@"她就是她" localizedSubtitle:@"不信算了" icon:icon4 userInfo:nil]; if (isShow) { application.shortcutItems = @[item1,item2,item3,item4]; }else{ application.shortcutItems = @[]; } }
动态方法添加可以在某个条件下取消3D Touch功能,比如登陆之前取消3D Touch功能和登陆之后添加3D Touch功能,代码中的UIApplicationShortcutIconTypeShare等是系统风格的icon,这里只是举个例子直接拿来用,但是不知道审核的时候会不会被拒。
typedef NS_ENUM(NSInteger, UIApplicationShortcutIconType) {
UIApplicationShortcutIconTypeCompose,
UIApplicationShortcutIconTypePlay,
UIApplicationShortcutIconTypePause,
UIApplicationShortcutIconTypeAdd,
UIApplicationShortcutIconTypeLocation,
UIApplicationShortcutIconTypeSearch,
UIApplicationShortcutIconTypeShare,
UIApplicationShortcutIconTypeProhibit NS_ENUM_AVAILABLE_IOS(9_1),
UIApplicationShortcutIconTypeContact NS_ENUM_AVAILABLE_IOS(9_1),
UIApplicationShortcutIconTypeHome NS_ENUM_AVAILABLE_IOS(9_1),
UIApplicationShortcutIconTypeMarkLocation NS_ENUM_AVAILABLE_IOS(9_1),
UIApplicationShortcutIconTypeFavorite NS_ENUM_AVAILABLE_IOS(9_1),
UIApplicationShortcutIconTypeLove NS_ENUM_AVAILABLE_IOS(9_1),
UIApplicationShortcutIconTypeCloud NS_ENUM_AVAILABLE_IOS(9_1),
UIApplicationShortcutIconTypeInvitation NS_ENUM_AVAILABLE_IOS(9_1),
UIApplicationShortcutIconTypeConfirmation NS_ENUM_AVAILABLE_IOS(9_1),
UIApplicationShortcutIconTypeMail NS_ENUM_AVAILABLE_IOS(9_1),
UIApplicationShortcutIconTypeMessage NS_ENUM_AVAILABLE_IOS(9_1),
UIApplicationShortcutIconTypeDate NS_ENUM_AVAILABLE_IOS(9_1),
UIApplicationShortcutIconTypeTime NS_ENUM_AVAILABLE_IOS(9_1),
UIApplicationShortcutIconTypeCapturePhoto NS_ENUM_AVAILABLE_IOS(9_1),
UIApplicationShortcutIconTypeCaptureVideo NS_ENUM_AVAILABLE_IOS(9_1),
UIApplicationShortcutIconTypeTask NS_ENUM_AVAILABLE_IOS(9_1),
UIApplicationShortcutIconTypeTaskCompleted NS_ENUM_AVAILABLE_IOS(9_1),
UIApplicationShortcutIconTypeAlarm NS_ENUM_AVAILABLE_IOS(9_1),
UIApplicationShortcutIconTypeBookmark NS_ENUM_AVAILABLE_IOS(9_1),
UIApplicationShortcutIconTypeShuffle NS_ENUM_AVAILABLE_IOS(9_1),
UIApplicationShortcutIconTypeAudio NS_ENUM_AVAILABLE_IOS(9_1),
UIApplicationShortcutIconTypeUpdate NS_ENUM_AVAILABLE_IOS(9_1)
} NS_ENUM_AVAILABLE_IOS(9_0) __TVOS_PROHIBITED;
这里有几点需要注意:
1、快捷标签最多可以创建四个,包括静态的和动态的,静态标签会一直存在。
2、每个标签的题目和icon最多两行,多出的会用...省略
3、我们在app的入口函数:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
也需要进行一下判断,在launchOptions中有UIApplicationLaunchOptionsShortcutItemKey这样一个键,通过它,我们可以区别是否是从标签进入的app,如果是则处理结束逻辑后,返回NO,防止处理逻辑被反复回调。
二.响应标签的行为
当我们点击标签进入应用程序时,也可以进行一些操作,我们可以看到,在applocation中增加了这样一个方法:
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void(^)(BOOL succeeded))completionHandler NS_AVAILABLE_IOS(9_0);(要注意上面的第三点)
当我们通过标签进入app时,就会在appdelegate中调用这样一个回调,我们可以获取shortcutItem的信息进行相关逻辑操作。
#pragma mark -3Dtouch功能 - (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void(^)(BOOL succeeded))completionHandler{ //判断先前我们设置的唯一标识 NSLog(@"选择了3Dtouch功能--%@",shortcutItem.type); UIViewController *myVC; if ([shortcutItem.type isEqualToString:KTouchItemPublicPosition]) { myVC = [[YBSPublicViewController alloc]initWithNibName:@"YBSPublicViewController" bundle:nil]; }else if ([shortcutItem.type isEqualToString:KTouchItemMyPublic]){ myVC = [[YBSPositionViewController alloc]initWithNibName:@"YBSPositionViewController" bundle:nil]; }else if ([shortcutItem.type isEqualToString:KTouchItemRecharge]){ myVC = [[YBSResumeViewController alloc]initWithNibName:@"YBSResumeViewController" bundle:nil]; }else if ([shortcutItem.type isEqualToString:KTouchItemCheck]){ myVC = [[YBSResumeViewController alloc]initWithNibName:@"YBSResumeViewController" bundle:nil]; } YBSNavigationViewController *nav = [[YBSNavigationViewController alloc]initWithRootViewController:myVC]; //设置当前的VC 为rootVC [self.window.rootViewController presentViewController:nav animated:YES completion:nil]; } 这里面主要是做一个例子,显示的视图跳转 要根据具体情况加上
效果图
三. 3D Touch ViewController 弹出自定义的ViewContoller,向上滑动还有下一步的菜单可以显示
首先在viewController的.m方法中添加下面代码,判断当前设备是否支持压力感,并注册delegate
//注册3D Touch,先判断是否可用 if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable){ [self registerForPreviewingWithDelegate:self sourceView:self.view]; NSLog(@"3D Touch 可用!"); }else{ NSLog(@"3D Touch 无效"); }
添加你想要弹出来的viewcontroller,
/** * peek手势 */ -(UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location{ // 获取用户手势点所在cell的下标。同时判断手势点是否超出tableView响应范围。 if (![self getShouldShowRectAndIndexPathWithLocation:location]) return nil; //弹出视图的初始位置,sourceRect是peek触发时的高亮区域。这个区域内的View会高亮显示,其余的会模糊掉 previewingContext.sourceRect = sourceRect; //获取数据进行传值 YBS3DTouchViewController *childVC = [[YBS3DTouchViewController alloc] init]; return childVC; } /** * pop手势 */ -(void)previewingContext:(id<UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit{ [self tableView:self.myTableView didSelectRowAtIndexPath:selectedPath]; } /** * 获取用户手势点所在cell的下标,同时判断手势点是否超出tableview的范围 */ - (BOOL)getShouldShowRectAndIndexPathWithLocation:(CGPoint)location { //坐标点的转化, CGPoint tableLocation = [self.view convertPoint:location toView:self.myTableView]; selectedPath = [self.myTableView indexPathForRowAtPoint:tableLocation]; sourceRect = CGRectMake(0, selectedPath.row * KMessageRowHeight, ScreenHeight, KMessageRowHeight); // 如果row越界了,返回NO 不处理peek手势 NSLog(@"当前所在的行---%zd",selectedPath.row); return (selectedPath.row >= (self.messageArr.count+10)) ? NO : YES; }
接下来在添加的视图中,添加向上滑显示的菜单,上面代码中YBS3DTouchViewController *childVC,视图中我就是简单定义了一个backView和一个label,下面是在-(NSArray<id<UIPreviewActionItem>> *)previewActionItems函数中定义你要显示的菜单
/** * 3D Touch 上移显示的视图 */ -(NSArray<id<UIPreviewActionItem>> *)previewActionItems{ UIPreviewAction *action1 = [UIPreviewAction actionWithTitle:@"我就是我" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) { NSLog(@"click---我就是我"); }]; UIPreviewAction *action2 = [UIPreviewAction actionWithTitle:@"你还是你" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) { NSLog(@"click---你还是你"); }]; UIPreviewAction *action3 = [UIPreviewAction actionWithTitle:@"她还是她" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) { NSLog(@"click---她还是她"); }]; //想要显示多个就定义多个 UIPreviewAction NSArray *actions = @[action1,action2,action3]; return actions; }
在block里面进行的一个回调,在这里处理你的点击事件,效果如下
学习的就这么多,有更多的,后面加上😊