iOS开发之3D Touch

作者: Camille_chen | 来源:发表于2015-12-29 21:12 被阅读8086次

    1.简单的介绍一下3D Touch

    3D Touch的触控技术,被苹果称为新一代多点触控技术。其实,就是此前在Apple Watch上采用的Force Touch,屏幕可感应不同的感压力度触控。

    2.在模拟器上如何进行3D Touch测试

    声明:可能由于本人技术水平有限,按照此方法未能在模拟器上实现3D Touch功能,所以仅供参考!若有能实现者,请快告诉我哟!!!😊😊

    3D Touch 是一个很新颖的设计,可是苹果文档有言:

    With Xcode 7.0 you must develop on a device that supports 3D Touch. Simulator in Xcode 7.0 does not support 3D Touch.

    看到这句话心是不是凉了一半,是的,xcode7是支持3D Touch开发的,可是模拟器并不支持这个手势,我们只能在真机上进行学习与测试,但是在IT的世界,从来都不缺拯救世界的人物,github上有人为我们提供了这样的一个插件,可以让我们在模拟器上进行3D Touch的效果测试:

    git地址:https://github.com/DeskConnect/SBShortcutMenuSimulator

    附.SBShortcutMenuSimulator的安装和使用

    其实安装和使用并不需要怎么介绍,git主页里介绍的很清楚,这里在记录一遍,其中只有一点需要注意,如果你像我一样,电脑中装有Xcode6和Xcode7两个版本,那个Xcode的编译路径,需要做一下修改。

    安装:

    在终端中一次运行如下指令:

    git clone https://github.com/DeskConnect/SBShortcutMenuSimulator.gitcd SBShortcutMenuSimulator

    make

    如果电脑中有多个Xcode版本,先做如下操作,如果只有Xcode7,则可以跳过

    sudo xcode-select -switch /Applications/Xcode2.app/Contents/Developer/

    注意:上面命令中,Xcode2.app是你电脑中Xcode的名字,这里如要特别注意,如果名字中有空格,需要修改一下,把空格去掉,否则会影响命令的执行。

    之后在SBShortcutMenuSimulator的目录中执行如下操作:

    xcrun simctl spawn booted launchctl debug system/com.apple.SpringBoard --environment DYLD_INSERT_LIBRARIES=$PWD/SBShortcutMenuSimulator.dylib

    xcrun simctl spawn booted launchctl stop com.apple.SpringBoard

    如果没有报错,我们可以通过向指定端口发送消息的方法来在模拟器上模拟3D Touch的效果:

    echo 'com.apple.mobilecal' | nc 127.0.0.1 8000

    其中,com.apple.mobilecal是应用的Bundle ID ,如果要测试我们的应用,将其改为我们应用的BundleID即可,上面的示例应用是系统日历,可以看到模拟器的效果如下:

    3.如何实现3D Touch功能

    3D Touch的三大模块

    3D Touch功能主要分为以下三个模块:

    1、Home Screen Quick Actions

    通过主屏幕的应用Icon,我们可以用3D Touch呼出一个菜单,进行快速定位应用功能模块相关功能的开发。如上面的日历。

    2、peek and pop

    这个功能是一套全新的用户交互机制,在使用3D Touch时,ViewController中会有如下三个交互阶段:

    (1)提示用户这里有3D Touch的交互,会使交互控件周围模糊

    (2)继续深按,会出现预览视图

    (3)通过视图上的交互控件进行进一步交互

            这个模块的设计可以在网址连接上进行网页的预览交互。

    3、Force Properties

    iOS9为我们提供了一个新的交互参数:力度。我们可以检测某一交互的力度值,来做相应的交互处理。例如,我们可以通过力度来控制快进的快慢,音量增加的快慢等。

    4.通过实例来看是如何实现3D Touch功能的

    用一个简单的相册来举例说明:

    首先,创建Quick Action(用力按压图标出现的标签)有两种方式:静态和动态

    ①静态创建的方式是在Info.plist文件中进行声明的

    有两种方式进行编辑:

    (1)第一种方法——如图所示:

    选择红色框中的选项

    将上面的代码填入Info.plist文件中

    必填项(下面两个键值是必须设置的):

    UIApplicationShortcutItemType 这个键值设置一个快捷通道类型的字符串

    UIApplicationShortcutItemTitle 这个键值设置标签的标题

    选填项(下面这些键值不是必须设置的):

    UIApplicationShortcutItemSubtitle 设置标签的副标题

    UIApplicationShortcutItemIconType 设置标签Icon类型

    UIApplicationShortcutItemIconFile  设置标签的Icon文件

    (2)第二种方法

    直接在Info.plist文件中添加如下代码(红色方框中的代码):

    其实静态添加的两种方法都是在Info.plist文件中添加的,只是通过的方式不同。

    ②以动态方式创建

    动态创建是在程序初始化的时候用代码动态添加。UIApplication对象多了一个支持快捷方式的数组(shortcutItems),如果需要增加快捷方式,可以赋值给shortcutItems属性。

    可在rootViewController的viewDidLoad中添加(具体写哪,可根据自己情况而定),代码如下:

    UIApplicationShortcutItem * item = [[UIApplicationShortcutItem alloc]initWithType:@"two" localizedTitle:@"标签2" localizedSubtitle:@"222" icon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeLove] userInfo:nil];

    // 设置自定义标签图片

    UIApplicationShortcutItem * itemTwo = [[UIApplicationShortcutItem alloc]initWithType:@"two" localizedTitle:@"标签3" localizedSubtitle:@"333" icon:[UIApplicationShortcutIcon iconWithTemplateImageName:@"jieri"] userInfo:nil];

    UIApplicationShortcutItem * itemThird = [[UIApplicationShortcutItem alloc]initWithType:@"two" localizedTitle:@"标签4" localizedSubtitle:@"444" icon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeSearch] userInfo:nil];

    [UIApplication sharedApplication].shortcutItems = @[item, itemTwo, itemThird];

    说明:

    1)系统限制每个App最多能够显示4个Action Item,其中包括静态方式和动态方式进行创建的;

    2)如果静态和动态方式同时使用的时候,给UIApplication的shortcutItems赋值的时候不会覆盖

    按压图标的效果图

    响应回调

    当App在后台的时候UIApplication提供了一个回调方法

    - (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void(^)(BOOL succeeded))completionHandler NS_AVAILABLE_IOS(9_0);

    我们依据这个回调中的shortcutItem的type和userinfo来做出不同的事件处理,代码如下:

    // 用来处理3D Touch触发事件

    - (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void(^)(BOOL succeeded))completionHandler{

    //判断先前我们设置的唯一标识

    if([shortcutItem.localizedTitle isEqualToString:@"标签1"]){

    NSArray *arr = @[@"hello 3D Touch"];

    UIActivityViewController *vc = [[UIActivityViewController alloc]initWithActivityItems:arr applicationActivities:nil];

    //设置当前的VC 为rootVC

    [self.window.rootViewController presentViewController:vc animated:YES completion:^{

    }];

    }

    if ([shortcutItem.localizedTitle isEqual: @"标签2"]) {

    // 点击标签2时,显示提示框

    UIAlertController *alertC = [UIAlertController alertControllerWithTitle:@"OPPS!" message:@"啦啦啦" preferredStyle:UIAlertControllerStyleAlert];

    UIAlertAction *alert = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {

    }];

    [alertC addAction:alert];

    [self.window.rootViewController presentViewController:alertC animated:YES completion:^{

    }];

    return;

    }

    }

    点击标签1的效果图 点击标签2的效果图

    实际上就是,当我们按压图标,出现标签,点击某个标签后触发的事件

    在rootViewController中创建一个UICollectionView,并实现其协议方法,代码如下:

    - (void)createCollectionView {

    UICollectionViewFlowLayout *flow = [[UICollectionViewFlowLayout alloc] init];

    /* API */

    /* item 大小 */

    flow.itemSize = CGSizeMake(100, 100);

    /* 行间的最小间距 */

    flow.minimumLineSpacing = 5.0f;

    flow.sectionInset = UIEdgeInsetsMake(20, 20, 20, 20);

    /* 创建collectionView对象 */

    self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 64, self.view.frame.size.width, self.view.frame.size.height - 64) collectionViewLayout:flow];

    [self.view addSubview:self.collectionView];

    self.collectionView.backgroundColor = [UIColor whiteColor];

    /* 两个协议 */

    self.collectionView.dataSource = self;

    self.collectionView.delegate = self;

    [self.collectionView registerClass:[PicCollectionViewCell class] forCellWithReuseIdentifier:@"pic"];

    }

    - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {

    return self.arrPic.count;

    }

    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    PicCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"pic" forIndexPath:indexPath];

    cell.backgroundColor = [UIColor whiteColor];

    cell.name = [self.arrPic objectAtIndex:indexPath.row];

    return cell;

    }

    整理图片相关数据:

    - (void)handleData {

    self.arrPic = [NSMutableArray array];

    self.arrName = [NSMutableArray array];

    for (int i = 1; i < 27; i ++) {

    [self.arrPic addObject:[NSString stringWithFormat:@"%d", i]];

    [self.arrName addObject:[NSString stringWithFormat:@"%c", i + 64]];

    }

    }

    在自定义Cell中给图片赋值

    需要签UIViewControllerPreviewingDelegate代理方法,为了实现peek and pop功能

    (1)peek功能的实现

    Peek窗口的内容其实是目标VC【ps即将要显示的ViewController】的一个实时快照,但它不可以点击。Peek触发阶段有三种:

    长按【显示一个焦点视图,触发Peek的源视图高亮,其它视图都处于模糊状态】

    轻压【显示Peek窗口,此时如果Peek窗口支持Quick Actions,往上滑会显示Quick Actions菜单,此时的Peek窗口是不可以点击的】

    重压 【进入到真正的ViewController】

    Peek由一个可响应事件的View触发,默认是关闭的,我们需要通过控制器的registerForPreviewingWithDelegate: sourceView:方法注册,第一个参数为UIViewControllerPreviewingDelegate的代理,Peek触发轻压时会调用其previewingContext:viewControllerForLocation方法,重压时会调用previewingContext:commitViewController:方法。第二个参数为触发Peek事件的源视图

    首先要在viewDidLoad中进行注册:

    // 注册预览视图的代理和来源视图

    [self registerForPreviewingWithDelegate:(id)self sourceView:self.view];

    实现方法:

    #pragma mark - 按压图片进入预览模式

    - (UIViewController * _Nullable)previewingContext:(id_Nonnull)previewingContext viewControllerForLocation:(CGPoint)location {

    ContentViewController *content = [[ContentViewController alloc] init];

    NSIndexPath *index = [self.collectionView indexPathForItemAtPoint:CGPointMake(location.x, location.y - 64 + self.collectionView.contentOffset.y)];

    if (index == NULL) {

    return nil;

    } else {

    content.name = [self.arrPic objectAtIndex:index.item];

    content.picName = [self.arrName objectAtIndex:index.item];

    return content;

    }

    }

    按压图片进入预览模式的效果图

    #pragma mark - 继续按压进入查看图片

    - (void)previewingContext:(id_Nonnull)previewingContext commitViewController:(UIViewController * _Nonnull)viewControllerToCommit

    {

    viewControllerToCommit.view.backgroundColor = [UIColor whiteColor];

    [self showViewController:viewControllerToCommit sender:self];

    }

    继续按压进入查看图片的效果图

    (2)pop功能的实现

    在创建的ContentViewController中实现如下代码:

    首先在.h文件中声明两个属性

    @property (nonatomic, copy) NSString *name;  // 图片的文件名(如xxx.png)

    @property (nonatomic, copy) NSString *picName;  // 图片名(如自己给图片起的名字)

    在.m文件中实现如下方法:

    // 设置预览视图向上滑动时出现的视图

    - (NSArray> *)previewActionItems {

    UIPreviewAction *action1 = [UIPreviewAction actionWithTitle:@"Action 1" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {

    // 点击此选项触发

    self.alertC = [UIAlertController alertControllerWithTitle:@"你查看的是:" message:[NSString stringWithFormat:@"图片%@", self.picName] preferredStyle:UIAlertControllerStyleActionSheet];

    UIAlertAction *alert = [UIAlertAction actionWithTitle:@"噢噢" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {

    }];

    [self.alertC addAction:alert];

    // 因为预览视图与根视图不在一个视图层级上,所以需要通过根视图去推出这个

    [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:self.alertC animated:YES completion:^{

    }];

    }];

    // 可以添加多个选项

    NSArray *arr = @[action1];

    return arr;

    }

    视图向上滑动时的效果图 点击Action1出现的效果图

    在viewDidLoad中添加如下代码,将图片显示出来:

    UIImageView *image = [[UIImageView alloc] initWithImage:[UIImage imageNamed:self.name]];

    image.frame = CGRectMake(20, 0, self.view.frame.size.width - 40, self.view.frame.size.width - 40);

    image.center = CGPointMake(self.view.frame.size.width / 2, (self.view.frame.size.height - 64) / 2);

    [self.view addSubview:image];

    大概总结到这里,有待完善。。。

    相关文章

      网友评论

      • 抢手的哥:楼主把代码放到代码块吧,看着好难受
      • SHICHUAN:[self registerForPreviewingWithDelegate:(id)self sourceView:self.view]; 这样是非官方的做法 [self registerForPreviewingWithDelegate:(id)self sourceView:cell]; 要是cell 或者item。 当sourceView是cell这样你应该怎么做??
      • 风吹柳絮如花落:楼主,在info.plist中设置icon和subtitle都无效,只有title和type可以展示,是我哪里写错了么?这是为什么那?
      • 4a0cfa4e9f80:我想问一下楼主知道touch 3d点击标签不进入app,直接从下面弹出系统分享吗,最近在做这一块,不清楚这个分享如何实现
        Janlor:这个是iOS10的新特性,不用处理, iOS 10以下估计需要用到私有 API
        FindViewById:请问搞定了吗?同求呀😂
        丶大明:@linlinyin1991 你好,方法实现了吗?最近也在搞这个,没在网上找到相关的资料 :joy:
      • NSBug:springborard意外退出什么原因?
        6e080f4a6965:你的模拟器系统是不是9.1的,不是的话好像不行,我试过其他的只有是9.1的模拟器才可以
        Camille_chen:@孙琦 没遇到过,试试重新启动吧
      • YY树:很棒的分享,非常感谢楼主
        YY树:@Camille_chen 嗯嗯,向你学习
        Camille_chen:@YY树 有帮助就好:smile:

      本文标题:iOS开发之3D Touch

      本文链接:https://www.haomeiwen.com/subject/pokuhttx.html