3DTouch简单了解

3D Touch的三大模块

代码Demo:https://github.com/haozheMa/3DTouch

    在我们的app中使用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为我们提供了一个新的交互参数:力度。我们可以检测某一交互的力度值,来做相应的交互处理。例如,我们可以通过力度来控制快进的快慢,音量增加的快慢等。

Home Screen Quick Action使用与相关api详解

1、静态标签

静态标签是我们在项目的配置plist文件中配置的标签,在用户安装程序后就可以使用,并且排序会在动态标签的前面。

我们先来看静态标签的配置:

首先,在info.plist文件中添加如下键值(我在测试的时候,系统并没有提示,只能手打上去):

先添加了一个UIApplicationShortcutItems的数组,这个数组中添加的元素就是对应的静态标签,在每个标签中我们需要添加一些设置的键值:

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

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

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

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

UIApplicationShortcutItemSubtitle 设置标签的副标题

UIApplicationShortcutItemIconType 设置标签Icon类型

UIApplicationShortcutItemIconFile  设置标签的Icon文件

UIApplicationShortcutItemUserInfo 设置信息字典(用于传值)

把截图中的内容配置一下,就可以运行程序,测试一下


 

2、动态标签

动态标签是我们在程序中,通过代码添加的,与之相关的类,主要有三个:

UIApplicationShortcutItem 创建3DTouch标签的类

UIMutableApplicationShortcutItem 创建可变的3DTouch标签的类

UIApplicationShortcutIcon 创建标签中图片Icon的类

首先介绍3DTouch的属性和方法

@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;

 

//这个类继承于 UIApplicationShortcutItem,创建的标签可变
@interface UIMutableApplicationShortcutItem : UIApplicationShortcutItem
@property (nonatomic, copy) NSString *type;
@property (nonatomic, copy) NSString *localizedTitle;
@property (nullable, nonatomic, copy) NSString *localizedSubtitle;
@property (nullable, nonatomic, copy) UIApplicationShortcutIcon *icon;
@property (nullable, nonatomic, copy) NSDictionary<NSString *, id <NSSecureCoding>> *userInfo;
 
@end

 

//这个类创建标签中的icon
@interface UIApplicationShortcutIcon : NSObject <NSCopying>
//创建系统风格的icon
+ (instancetype)iconWithType:(UIApplicationShortcutIconType)type;
//创建自定义的图片icon
+ (instancetype)iconWithTemplateImageName:(NSString *)templateImageName;
@end

 下边是实现的代码,可以写在RootVC中,也可以写在AppDlegate的

didFinishLaunchingWithOptions方法中(根据所查网络资料,写这两处都好使)

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    //创建
    UIApplicationShortcutItem * item = [[UIApplicationShortcutItem alloc]initWithType:@"2" localizedTitle:@"按钮标签" localizedSubtitle:@"副标题" icon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypePlay] userInfo:nil];
    添加
    [UIApplication sharedApplication].shortcutItems = @[item];
}

图标枚举类型

typedef NS_ENUM(NSInteger, UIApplicationShortcutIconType) {
    UIApplicationShortcutIconTypeCompose,//编辑的图标
    UIApplicationShortcutIconTypePlay,//播放图标
    UIApplicationShortcutIconTypePause,//暂停图标
    UIApplicationShortcutIconTypeAdd,//添加图标
    UIApplicationShortcutIconTypeLocation,//定位图标
    UIApplicationShortcutIconTypeSearch,//搜索图标
    UIApplicationShortcutIconTypeShare//分享图标
} NS_ENUM_AVAILABLE_IOS(9_0);

 

 3、响应标签的行为

我们在AppDlegate中添加方法

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

 使用的话可以类似这样

/** 处理shortcutItem */
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {
    switch (shortcutItem.type.integerValue) {
        case 1: { // 测试1
            [[NSNotificationCenter defaultCenter] postNotificationName:@"gotoTestVc" object:self userInfo:@{@"type":@"1"}];
        }
        case 2: { // 测试2
            [[NSNotificationCenter defaultCenter] postNotificationName:@"gotoTestVc" object:self userInfo:@{@"type":@"2"}];
        }   break;
        default:
            break;
    }
}

 或者这样

- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void(^)(BOOL succeeded))completionHandler{
    //判断先前我们设置的唯一标识
    if([shortcutItem.type isEqualToString:@"-11.UITouchText.share"]){
        NSArray *arr = @[@"hello 3D Touch"];
        UIActivityViewController *vc = [[UIActivityViewController alloc]initWithActivityItems:arr applicationActivities:nil];
        //设置当前的VC 为rootVC
        [self.window.rootViewController presentViewController:vc animated:YES completion:^{
        }];
    }
}

几点注意:

1、快捷标签最多可以创建四个,包括静态的和动态的。

2、每个标签的题目和icon最多两行,多出的会用...省略

感觉差不多是这个样子吧。

参考 http://my.oschina.net/u/2340880/blog/511509(有在模拟器上测试的需求可以看原博主的内容)


 

peek and pop

实现peek和pop手势:

 1、遵守协议 UIViewControllerPreviewingDelegate

 2、注册    [self registerForPreviewingWithDelegate:self sourceView:self.view];

 3、实现代理方法

具体代码:(与Home Screen Quick Action相互独立)

先写主页面的内容RootView

#import "ViewController.h"
#import "DetailViewController.h"

#define _ScreenWidth [UIScreen mainScreen].bounds.size.width
#define _ScreenHeight [UIScreen mainScreen].bounds.size.height

@interface ViewController ()<UITableViewDelegate,UITableViewDataSource,UIViewControllerPreviewingDelegate>

@property (strong,nonatomic) UITableView *tableView;

@property (copy, nonatomic) NSArray *items;

@property (assign, nonatomic) CGRect sourceRect; //用户手势点

@property (strong, nonatomic) NSIndexPath *indexPath; //用户手势点

@end

@implementation ViewController

/*
 实现peek和pop手势:
 1、遵守协议 UIViewControllerPreviewingDelegate
 2、注册    [self registerForPreviewingWithDelegate:self sourceView:self.view];
 3、实现代理方法
 */


- (void)viewDidLoad
{
    [super viewDidLoad];
    
    [self loadTableview];
    
    //注册Peek和Pop
    if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
    {
        /**
         *  这个判断的作用是检测当前设备是否支持 3D Touch
         */
        [self registerForPreviewingWithDelegate:self sourceView:self.view];
    }
    
}

//加载tableview
-(void)loadTableview
{
    self.tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, _ScreenWidth, _ScreenHeight) style:UITableViewStylePlain];
    self.tableView.rowHeight = 50;
    self.tableView.delegate= self;
    self.tableView.dataSource = self;
    [self.view addSubview:self.tableView];
}

-(NSArray *)items
{
    if (_items == nil)
    {
        _items = [[NSArray alloc]initWithObjects:@"第一条",@"第二条",@"第三条",@"第四条",@"第五条",@"第六条",nil];
    }
    return _items;
}

#pragma mark - tableViewDelage
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.items.count;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellID = @"cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    
    if (cell == nil)
    {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
    }
    cell.textLabel.text = self.items[indexPath.row];
    return cell;
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"点击了/pop第%zdcell",indexPath.row+1);
}

#pragma mark - peek&& pop代理
/** peek手势  */
-(nullable UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location
{
    //获取用户手势点的Cell的下标,同时判断手势点是否超出tableview的响应范围
    if (![self getShouldShowRectAndIndexPathWithLocation:location]) return nil;
    previewingContext.sourceRect = self.sourceRect;
    
    
    NSIndexPath *index =  [_tableView indexPathForRowAtPoint:location];
    
    UITableViewCell *cell = [_tableView cellForRowAtIndexPath:index];
    
    if(cell != nil ){
        
        DetailViewController *detailViewController = [[DetailViewController alloc] init];
        
        detailViewController.text = [NSString stringWithFormat:@"点击了第%zd个cell,预览图层,再用力按调用pop手势的代理方法", index.row+1];
        
        return detailViewController;
        
    }
    
    return nil;
}

/** pop手势  */
- (void)previewingContext:(id <UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit {
//    [self tableView:self.tableView didSelectRowAtIndexPath:self.indexPath];
    [self showViewController:viewControllerToCommit sender:self];
}

/** 获取用户手势点所在cell的下标。同时判断手势点是否超出tableView响应范围。*/
-(BOOL)getShouldShowRectAndIndexPathWithLocation:(CGPoint)location
{
    NSInteger row = (location.y - 20)/50;
    self.sourceRect = CGRectMake(0, row * 50 , _ScreenWidth, 50);
    self.indexPath = [NSIndexPath indexPathForItem:row inSection:0];
    // 如果row越界了,返回NO 不处理peek手势
    return row >= self.items.count ? NO : YES;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

 然后是预览的那个DetailVC

//
//  DetailViewController.h
//  3DTouchPreviewDemo
//
//  Created by apple on 16/4/14.
//  Copyright © 2016年 apple. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface DetailViewController : UIViewController

@property (nonatomic, strong) NSString *text;

@end

 

//
//  DetailViewController.m
//  3DTouchPreviewDemo
//
//  Created by apple on 16/4/14.
//  Copyright © 2016年 apple. All rights reserved.
//

#import "DetailViewController.h"

@interface DetailViewController ()



@end

@implementation DetailViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UIView *bgView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
    bgView.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:bgView];
    
    UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(20, 64, 50, 50)];
    btn.backgroundColor = [UIColor redColor];
    [btn setTitle:@"返回" forState:UIControlStateNormal];
    [btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [btn addTarget:self action:@selector(getHome) forControlEvents:UIControlEventTouchUpInside];
    [bgView addSubview:btn];
    
    UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 120, self.view.frame.size.width, self.view.frame.size.height)];
    textView.font = [UIFont systemFontOfSize:24];
    textView.text = self.text;
    [bgView addSubview:textView];
    
}

-(void)getHome
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (NSArray<id<UIPreviewActionItem>> *)previewActionItems {
    
    UIPreviewAction *itemShare = [UIPreviewAction actionWithTitle:@"分享" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
        
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"分享" message:@"分享内容" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles: nil];
        
        [alertView show];
        
    }];
    
    return @[itemShare];
    
}

@end

 运行结果:

 

posted @ 2016-04-14 15:00  小屁孩~  阅读(414)  评论(0编辑  收藏  举报