博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
3D Touch 简单应用
阅读量:5873 次
发布时间:2019-06-19

本文共 8856 字,大约阅读时间需要 29 分钟。

随着iPhone 6s 和 iPhone 6s Plus 的发布,苹果开始添加了一种全新的触控方式——3D Touch。最近几天简单地研究了一下,跟大家分享一下我的一些经验。

##UIApplicationShortcutItems

当你重按应用的图标时,会弹出类似这样的小菜单(以微信为例):

添加这样的快捷菜单主要有 静态动态 两种方法: ####静态方法 参看

可以看到 UIApplicationShortcutItemTitleUIApplicationShortcutItemType 这两个变量是必须的。

我们在项目的 info.plist 文件中添加如下信息:

运行结果:

####动态方法 动态方法是在项目中添加代码:

UIApplicationShortcutItem *item1 = [[UIApplicationShortcutItem alloc] initWithType:@"one" localizedTitle:@"Title One" localizedSubtitle:@"Sub one" icon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypePlay] userInfo:nil];UIApplicationShortcutItem *item2 = [[UIApplicationShortcutItem alloc] initWithType:@"two" localizedTitle:@"Title Two" localizedSubtitle:@"Sub two" icon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeHome] userInfo:nil];[UIApplication sharedApplication].shortcutItems = @[item1, item2];复制代码

当该段代码在程序中被执行过一次后才会被添加到主屏幕的 ShortcutItems 菜单中。 运行结果:

注意: ShortcutItems 会优先加载静态方法添加的,然后加载动态方法添加的,并且同时只能拥有最多4个ShortcutItems。

####选择 ShortcutItem 后的回调 在 AppDelegate 根据 shortcutItem.type 判断回调方法:

- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {    if ([shortcutItem.type isEqualToString:@"one"]) {        NSLog(@"Choose One");        MyViewController *vc = [[MyViewController alloc] init];        vc.title = @"One";        vc.view.backgroundColor = [UIColor whiteColor];        [self.window.rootViewController showViewController:vc sender:nil];    } else if ([shortcutItem.type isEqualToString:@"two"]) {        NSLog(@"Choose Two");        MyViewController *vc = [[MyViewController alloc] init];        vc.title = @"Two";        vc.view.backgroundColor = [UIColor orangeColor];        [self.window.rootViewController showViewController:vc sender:nil];    }    }复制代码

按压力度感应


在9.0后 UITouch 新增这样两个属性:

我们创建一个继承于 UIView 的自定义View,这里我们首先要判断一下设备是否支持3D Touch:

- (BOOL)check3DTouch {    if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) {        return YES;    } else {        return NO;    }}复制代码

然后在 touchesMoved 中调用方法:

- (void)touchesMoved:(NSSet
*)touches withEvent:(UIEvent *)event { if ([self check3DTouch]) { UITouch *touch = [touches anyObject]; self.backgroundColor = [UIColor colorWithRed:touch.force / touch.maximumPossibleForce green:0.0f blue:0.0f alpha:1.0f]; } else { NSLog(@"CAN NOT USE 3D TOUCH!"); }}复制代码

这样我们我创建了一个可以根据按压力度改变颜色的View。

Peek & Pop


####Peek和Pop: Peek是指重按一下后出现的预览,Pop是在Peek后进一步按压后进入预览的视图控制器。 首先遵循代理 <UIViewControllerPreviewingDelegate> 然后监测设备是否支持3D Touch,若支持则对需要响应Peek操作的视图进行注册:

- (void)check3DTouch {    if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) {        [self registerForPreviewingWithDelegate:self sourceView:_label];    }}复制代码

Peek的代理方法

- (UIViewController *)previewingContext:(id
)previewingContext viewControllerForLocation:(CGPoint)location { MyViewController *vc = [[MyViewController alloc] init]; vc.title = @"Hello"; vc.view.backgroundColor = [UIColor cyanColor]; return vc;}复制代码

其实就是返回一个视图控制器实例,但是看网上说这个方法会被多次调用,我实际测试有时会调用多次,有时只调用一次,还是不太清楚具体调用情况,有知道的朋友欢迎交流一下。为了保险起见,还是建议写成下面的形式:

- (UIViewController *)previewingContext:(id
)previewingContext viewControllerForLocation:(CGPoint)location { if ([self.presentedViewController isKindOfClass:[MyViewController class]]) { return nil; } else { MyViewController *vc = [[MyViewController alloc] init]; vc.title = @"Hello"; vc.view.backgroundColor = [UIColor cyanColor]; return vc; }}复制代码

至于Pop的方法就更简单了,直接调用下面的方法: Pop的代理方法

- (void)previewingContext:(id
)previewingContext commitViewController:(UIViewController *)viewControllerToCommit { [self showViewController:viewControllerToCommit sender:self];}复制代码

PreviewAction Items

有时在进入Peek但未Pop的时候,我们可以向上滑动选 PreviewAction Items

PreviewAction Items 是在被预览的viewController下面添加下面方法实现的:

- (NSArray
> *)previewActionItems { UIPreviewAction *action1 = [UIPreviewAction actionWithTitle:@"Default" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) { }]; UIPreviewAction *action2 = [UIPreviewAction actionWithTitle:@"Selected" style:UIPreviewActionStyleSelected handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) { }]; UIPreviewAction *action3 = [UIPreviewAction actionWithTitle:@"Destructive" style:UIPreviewActionStyleDestructive handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) { }]; NSArray *actions = @[action1, action2, action3]; UIPreviewActionGroup *group = [UIPreviewActionGroup actionGroupWithTitle:@"Actions Group" style:UIPreviewActionStyleDefault actions:actions]; UIPreviewAction *action4 = [UIPreviewAction actionWithTitle:@"Single Action" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) { }]; NSArray *array = @[group, action4]; return array;}复制代码

通过返回 UIPreviewActionUIPreviewActionGroup 组成的数组实现。

一个viewController下注册多个视图控件

前面说到如果要让视图控件响应Peek操作需要对其进行注册,但是如果一个viewController中有多个控件需要响应Peek并且可能不知道何时会出现的时候(譬如添加了一个tableView后,需要每一个单独的cell独立响应一个Peek操作),是不可能一个一个注册的,这个时候我们可以直接将- (void)check3DTouch 中的代码改成:

- (void)check3DTouch {    if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) {        [self registerForPreviewingWithDelegate:self sourceView:self.view];    }}复制代码

我们直接注册整个view,根据peek代理方法中的属性location 判断响应的UI控件

- (UIViewController *)previewingContext:(id
)previewingContext viewControllerForLocation:(CGPoint)location {    if (CGRectContainsPoint(_tableView.frame, location)) {        if ([self.presentedViewController isKindOfClass:[DisplayViewController class]]) {            return nil;        } else {            location = [self.view convertPoint:location toView:_tableView];            NSIndexPath *indexPath = [_tableView indexPathForRowAtPoint:location];            NSLog(@"%@", indexPath);            DisplayViewController *displayVC = [[DisplayViewController alloc] init];            displayVC.title = [_tableView cellForRowAtIndexPath:indexPath].textLabel.text;            displayVC.view.backgroundColor = [UIColor colorWithRed:arc4random() % 256 / 256.0                                                             green:arc4random() % 256 / 256.0                                                              blue:arc4random() % 256 / 256.0                                                             alpha:1.0];                        // peek预览窗口大小            displayVC.preferredContentSize = CGSizeMake(0.0, 100 * indexPath.row);                        // 进入peek前不被虚化的rect            previewingContext.sourceRect = [self.view convertRect:[_tableView cellForRowAtIndexPath:indexPath].frame fromView:_tableView];                        return displayVC;        }    }            if ([self.presentedViewController isKindOfClass:[MyViewController class]]) {        return nil;    } else {        if (CGRectContainsPoint(_label.frame, location)) {            MyViewController *vc = [[MyViewController alloc] init];            vc.title = @"Hello";            vc.view.backgroundColor = [UIColor cyanColor];            NSLog(@"New ViewController.");            return vc;        }    }        return nil;}复制代码

3D Touch 小应用 —— 压力感应画板


这段是引用了 / 的代码

- (void)touchesBegan:(NSSet
*)touches withEvent:(UIEvent *)event {    UITouch *touch = [touches anyObject];    _touchPoint = [touch locationInView:_drawBoard];}- (void)touchesMoved:(NSSet
*)touches withEvent:(UIEvent *)event {    UITouch *touch = [touches anyObject];    CGPoint currentPoint = [touch locationInView:_drawBoard];        UIGraphicsBeginImageContext(_drawBoard.frame.size);    [_drawBoard.image drawInRect:_drawBoard.frame];    CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);        float lineWidth = 10.0f;    if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) {        lineWidth *= touch.force;    }        CGContextSetLineWidth(UIGraphicsGetCurrentContext(), lineWidth);    CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.0, 0.0, 0.0, 1.0);    CGContextMoveToPoint(UIGraphicsGetCurrentContext(), _touchPoint.x, _touchPoint.y);    CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);    CGContextStrokePath(UIGraphicsGetCurrentContext());    _drawBoard.image = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();        _touchPoint = currentPoint;}复制代码

以上是我的一点浅薄的心得,本文中所有代码都已经上传至 / 欢迎大家交流讨论。

转载地址:http://evhnx.baihongyu.com/

你可能感兴趣的文章
asp.net中异步调用WebService(异步页)[转]
查看>>
转 Android中this、super的区别
查看>>
高数积分总结
查看>>
win10 python 3.7 pip install tensorflow
查看>>
学习面向对象的Javascript的第一步就是要搞清楚两个东西:原型链和作用域链
查看>>
后期处理
查看>>
switch语句
查看>>
进程内存分配
查看>>
运动App后台持续定位生成轨迹
查看>>
做一个APP
查看>>
Web-Attak系列教程第二季0x12讲——HTTP的请求与响应格式
查看>>
缓存基础整理
查看>>
【BZOJ】2599: [IOI2011]Race 点分治
查看>>
git仓库构建小记
查看>>
JDK 1.8新特性
查看>>
matlab做聚类分析
查看>>
“/"应用程序中的服务器错误
查看>>
快速定位NodeJs线上问题 - 之火焰图篇
查看>>
leetcode-345-Reverse Vowels of a String
查看>>
Spring Cloud F & Spring Boot 2.0 版本升级说明书
查看>>