POPVC功能实现,使用第二篇

作者:新葡京简介

前一篇文章介绍了给图片添加快捷方式,这篇主要介绍应用内,3D Touch的peek和pop功能的实现

一、认识3D Touch

API介绍

iOS9 3D Touch 使用第二篇

  • 当前的ViewController实现UIViewControllerPreviewingDelegate,实现代理方法- (UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:location

  • 注册当前的viewController

 

UITouch类里API的变化

iOS9中添加的属性

altitudeAngle

  • 当笔平行于平面时,该值为0
  • 当笔垂直于平面时,该值为Pi / 2

estimatedProperties

  • 当前触摸对象估计的触摸特性,返回值是UITouchPropertyies

updatedProperties

  • 当前触摸对象已经更新的触摸特性,返回值是UITouchPropertyies

estimationUpdateIndex

  • 当每个触摸对象的触摸特性发生变化时,该值将会单独增加,返回值是NSNumber

iOS9中添加的方法

  • PreciseLocationInView:当前触摸对象的坐标
  • PrecisePreviousLocationInView:当前触摸对象的前置坐标
  • azimuthAngleInview:沿着x轴正向的方位角,当与x轴正向方向相同时,该值为0;当view参数为nil时,默认为keyWindow
  • azimuthUnitVectorInView:当前触摸对象的方向上的单位向量
    当view参数为nil时,默认为keyWindow

字数712阅读908评论2喜欢3

1、硬件和操作系统要求

UIForceTouchCapability
  • UIForceTouchCapabilityUnknown 不能确定是否支持压力感应
  • UIForceTouchCapabilityUnavailable 不能支持压力感应
  • UIForceTouchCapabilityAvailable 可以支持压力感应

前一篇文章介绍了给图片添加快捷方式,这篇主要介绍应用内,3D Touch的peek和pop功能的实现

/** 注册当前view */[self registerForPreviewingWithDelegate:self sourceView:self.view];

     iPhone 6s或者iPhone 6s Plus

UITouchType

  • UITouchTypeDirect 垂直的触摸类型
  • UITouchTypeIndirect 非初值的触摸类型
  • UITouchTypeStylus 水平的触摸类型

当前的ViewController实现UIViewControllerPreviewingDelegate,实现代理方法- (UIViewController *)previewingContext:(id)previewingContext viewControllerForLocation:(CGPoint)location

代码如下:

     操作系统要求 ios9

关于重按App icon展开菜单的实现

在项目的Appdelegate中找到如下方法,创建展开菜单

-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{

注册当前的viewController

#import "ViewController.h"#import "DetailViewController.h"@interface ViewController ()<UITableViewDataSource,UITableViewDelegate>{ UITableView *mainTable;}@end@implementation ViewController- viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. self.view.backgroundColor = [UIColor whiteColor]; self.title = @"首页"; if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"您的手机支持3dtouch" message:nil delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alert show]; /** 注册当前view */ [self registerForPreviewingWithDelegate:self sourceView:self.view]; } else { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"很遗憾您的手机不支持3dtouch" message:nil delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alert show]; } mainTable = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped]; mainTable.delegate = self; mainTable.dataSource = self; [self.view addSubview:mainTable]; }- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return 1;}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return 10;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ NSString *cellId = [NSString stringWithFormat:@"%ld--%ld",indexPath.section,indexPath.row]; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId]; if  { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId]; } cell.textLabel.text = cellId; return cell;}- tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ return 45.0f;}- tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ return 15.0f;}- tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{ return 0.1f;}- tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ [tableView deselectRowAtIndexPath:indexPath animated:YES];}#pragma mark - previewing Delegate- (UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:location{ /** 转换坐标 */ CGPoint p = [mainTable convertPoint:location fromView:self.view]; /** 通过坐标活的当前cell indexPath */ NSIndexPath *indexPath = [mainTable indexPathForRowAtPoint:p]; /** 获得当前cell */ UITableViewCell *cell = [mainTable cellForRowAtIndexPath:indexPath]; DetailViewController *detail = [[DetailViewController alloc] init];// detail.preferredContentSize = CGSizeMake; detail.view.frame = self.view.frame; detail.titleString = cell.textLabel.text; if (indexPath.row > 6) { return nil; } return detail;}- previewingContext:(id<UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit{ [self showViewController:viewControllerToCommit sender:self];}- didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}@end

2、3D Touch的交互效果

for example
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    [self.window makeKeyAndVisible];
    UIViewController* vc = [[UIViewController alloc] initWithNibName:nil bundle:nil];
    self.window.rootViewController = vc;

    UIApplicationShortcutItem *item1 = [[UIApplicationShortcutItem alloc] initWithType:@"item1" localizedTitle:@"我的消息" localizedSubtitle:nil icon:nil userInfo:nil];

    UIApplicationShortcutIcon *icon2 = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeAdd];
    UIApplicationShortcutItem *item2 = [[UIApplicationShortcutItem alloc] initWithType:@"item2" localizedTitle:@"发布动态" localizedSubtitle:nil icon:icon2 userInfo:nil];

    UIApplicationShortcutIcon *icon3 = [UIApplicationShortcutIcon iconWithTemplateImageName:@"ico_discovery"];
    UIApplicationShortcutItem *item3= [[UIApplicationShortcutItem alloc] initWithType:@"item3" localizedTitle:@"搜索寻味师" localizedSubtitle:nil icon:icon3 userInfo:nil];
    application.shortcutItems = @[item3,item2,item1];


}

创建完之后就运行项目,看到效果啦,如图

新葡京8455 1

image

之后可以在application:performActionForShortcutItem:completionHandler方法内根据shortcutItem.type处理点击事件

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

/** 注册当前view */[selfregisterForPreviewingWithDelegate:selfsourceView:self.view];

  • 新葡京8455,预览时滑动底部菜单添加,在要展示的ViewController中(本例为DemoViewController)实现 UIViewControllerPreviewingDelegate的协议重写方法代理方法- (NSArray<id<UIPreviewActionItem>> *)previewActionItems;
  • QuickAction
for example
if ([shortcutItem.type isEqualToString:@"item1"]) {    
    MyMessageViewController *vc = [[MyMessageViewController alloc] init];
    vc.hidesBottomBarWhenPushed = YES;
    [self.navigationController.tabBarController.selectedViewController pushViewController:vc animated:YES];
}

}

代码如下:

代码如下:

          操作:稍微用力按压应用icon按钮

关于peek 和 pop的实现

#import"ViewController.h"#import"DetailViewController.h"@interfaceViewController(){UITableView*mainTable;}@end@implementationViewController- (void)viewDidLoad {    [superviewDidLoad];// Do any additional setup after loading the view, typically from a nib.self.view.backgroundColor= [UIColorwhiteColor];self.title=@"首页";if(self.traitCollection.forceTouchCapability==UIForceTouchCapabilityAvailable)    {UIAlertView*alert = [[UIAlertViewalloc] initWithTitle:@"您的手机支持3dtouch"message:nildelegate:selfcancelButtonTitle:@"OK"otherButtonTitles:nil,nil];        [alert show];/** 注册当前view */[selfregisterForPreviewingWithDelegate:selfsourceView:self.view];    }else{UIAlertView*alert = [[UIAlertViewalloc] initWithTitle:@"很遗憾您的手机不支持3dtouch"message:nildelegate:selfcancelButtonTitle:@"OK"otherButtonTitles:nil,nil];        [alert show];    }    mainTable = [[UITableViewalloc] initWithFrame:self.view.boundsstyle:UITableViewStyleGrouped];    mainTable.delegate=self;    mainTable.dataSource=self;    [self.viewaddSubview:mainTable];}- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView{return1;}- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section{return10;}- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath{NSString*cellId = [NSStringstringWithFormat:@"%ld--%ld",(long)indexPath.section,(long)indexPath.row];UITableViewCell*cell = [tableView dequeueReusableCellWithIdentifier:cellId];if(!cell)    {        cell = [[UITableViewCellalloc] initWithStyle:UITableViewCellStyleDefaultreuseIdentifier:cellId];    }    cell.textLabel.text= cellId;returncell;}- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath{return45.0f;}- (CGFloat)tableView:(UITableView*)tableView heightForHeaderInSection:(NSInteger)section{return15.0f;}- (CGFloat)tableView:(UITableView*)tableView heightForFooterInSection:(NSInteger)section{return0.1f;}- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath{    [tableView deselectRowAtIndexPath:indexPath animated:YES];}#pragma mark -  previewing Delegate- (UIViewController*)previewingContext:(id)previewingContext viewControllerForLocation:(CGPoint)location{/** 转换坐标 */CGPointp = [mainTable convertPoint:location fromView:self.view];/** 通过坐标活的当前cell indexPath */NSIndexPath*indexPath = [mainTable indexPathForRowAtPoint:p];/** 获得当前cell */UITableViewCell*cell = [mainTable cellForRowAtIndexPath:indexPath];    DetailViewController *detail = [[DetailViewController alloc] init];//    detail.preferredContentSize = CGSizeMake(0, 120);detail.view.frame=self.view.frame;    detail.titleString= cell.textLabel.text;if(indexPath.row>6)    {returnnil;    }returndetail;}- (void)previewingContext:(id)previewingContext commitViewController:(UIViewController*)viewControllerToCommit{    [selfshowViewController:viewControllerToCommit sender:self];}- (void)didReceiveMemoryWarning {    [superdidReceiveMemoryWarning];// Dispose of any resources that can be recreated.}@end

@interface DetailViewController ()@end@implementation DetailViewController- viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.view.backgroundColor = [UIColor lightGrayColor]; }- viewWillAppear:animated{ [super viewWillAppear:animated]; NSLog(@"title %@",self.titleString); self.navigationItem.title = self.titleString;}底部预览界面选项-(NSArray<id<UIPreviewActionItem>> *)previewActionItems{ UIPreviewAction *p1 = [UIPreviewAction actionWithTitle:@"选项1" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) { NSLog(@"1111111"); UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"111111" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alert show]; }]; UIPreviewAction *p2 = [UIPreviewAction actionWithTitle:@"选项2" style:UIPreviewActionStyleSelected handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) { NSLog(@"2222222222"); }]; UIPreviewAction *p3 = [UIPreviewAction actionWithTitle:@"选项3" style:UIPreviewActionStyleDestructive handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) { NSLog(@"3333333333"); }]; return @[p1,p2,p3];}- didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}

          效果:跳出一系列的快捷选项。用户选择一个快捷选项后,将会启动或者加载应用。

效果图

新葡京8455 2

image

首先创建2个viewController,例如HomeViewControllerDetailPageViewController

  • HomeViewController:需要添加peek和pop的ViewController
  • DetailPageViewController:要展示的View Controller

在HomeViewController中添加<UIViewControllerPreviewingDelegate>,并注册delegate

[self registerForPreviewingWithDelegate:self sourceView:self.view];

实现该Delegate的方法

-(UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)context viewControllerForLocation:(CGPoint)location
{

CGPoint point = [self.view convertPoint:location toView:self.tableView];//根据loaction获取其在不同坐标系中的点坐标,后面会通过这个取获取数据的indexPath
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:point];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
CGRect cellRect = cell.frame;
context.sourceRect = cellRect;
Humors *humor = [(FinderInfo*)dataList[indexPath.row] humors][0];//这是我们项目的一个model,大家可以换成自己的model进行操作
    DetailPageViewController *controller = [[DetailPageViewController alloc]initWithFlavorId:[humor.param intValue]];//创建需要pop的ViewController        
    controller.view.frame = self.view.frame;
    return controller;

}

-(void)previewingContext:(id<UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit{

[self showViewController:viewControllerToCommit sender:self];

}

预览时滑动底部菜单添加,在要展示的ViewController中(本例为DemoViewController)实现 UIViewControllerPreviewingDelegate的协议

通过以上代码,就可实现3D touch peek和pop的效果

           

效果图

新葡京8455 3

image

然后在DetailPageViewController中实现peek操作

打开前面pop出的ViewController(DetailPageViewController),在实现文件中添加如下代码

- (NSArray<id<UIPreviewActionItem>> *)previewActionItems{

__weak typeof(self) weakSelf = self;
NSString *actionTitle = mUserRes.isAttention?@"取消关注":@"+关注";
UIPreviewAction *p1 =[UIPreviewAction actionWithTitle:actionTitle style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
    [weakSelf attention]; //这里添加你需要点击后的操作
}];


UIPreviewAction *p2 =[UIPreviewAction actionWithTitle:@"取消" style:UIPreviewActionStyleDestructive handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
    //这里添加你需要点击后的操作
}];
NSArray *actions = @[p1,p2];
return actions;

}

重写方法代理方法- (NSArray> *)previewActionItems;

 

Tips:判断设备是否支持3D touch,需要做判断
  • self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable
  • [[[UIDevice currentDevice] systemVersion] floatValue] >= 9.0f

必须要两样同时满足,才可以使用,不作判断会引起不支持3D Touch的手机编译crash

部分内容摘自简书原地址点我

代码如下:

  • Peek
    操作:轻度力量按压某个视图
    效果:此视图的周围内容会变得模糊,提示用户这个视图支持3D Touch



    操作:中度力量按压某个视图
    效果:跳出预览界面peek



     操作:手指保持在peek页面上,向上滑动
     效果:底部展示peek快速选项
      

  • Pop

@interfaceDetailViewController()@end@implementationDetailViewController- (void)viewDidLoad {    [superviewDidLoad];// Do any additional setup after loading the view.self.view.backgroundColor= [UIColorlightGrayColor];}- (void)viewWillAppear:(BOOL)animated{    [superviewWillAppear:animated];NSLog(@"title  %@",self.titleString);self.navigationItem.title=self.titleString;}底部预览界面选项-(NSArray> *)previewActionItems{UIPreviewAction*p1 = [UIPreviewActionactionWithTitle:@"选项1"style:UIPreviewActionStyleDefaulthandler:^(UIPreviewAction* _Nonnull action,UIViewController* _Nonnull previewViewController) {NSLog(@"1111111");UIAlertView*alert = [[UIAlertViewalloc] initWithTitle:@""message:@"111111"delegate:selfcancelButtonTitle:@"OK"otherButtonTitles:nil,nil];        [alert show];    }];UIPreviewAction*p2 = [UIPreviewActionactionWithTitle:@"选项2"style:UIPreviewActionStyleSelectedhandler:^(UIPreviewAction* _Nonnull action,UIViewController* _Nonnull previewViewController) {NSLog(@"2222222222");    }];UIPreviewAction*p3 = [UIPreviewActionactionWithTitle:@"选项3"style:UIPreviewActionStyleDestructivehandler:^(UIPreviewAction* _Nonnull action,UIViewController* _Nonnull previewViewController) {NSLog(@"3333333333");    }];return@[p1,p2,p3];}- (void)didReceiveMemoryWarning {    [superdidReceiveMemoryWarning];// Dispose of any resources that can be recreated.}

          操作:在预览界面peek上重度力量按压

通过以上代码,就可实现3D touch peek和pop的效果

          效果:会完全跳转到peek所预览的那个界面

 

 

 

二、3D Touch效果实现

 

3D Touch共有1、QuickAction  2、peek 3、pop 4、peek快捷选项四种功能,下面就分别讲解这四种功能,每种功能的做法都区分了步骤,非常简单,简直就是傻瓜式操作。

 

【1】QuickAction

第一步 注册

AppDelegate.m的

   - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

 

代码示例:

*)localizedTitle;

第二步:实现AppDelegate.m中的代理方法,按不同控件做不同操作:

代码示例:

     

【2】peek

第一步:遵循 UIViewControllerPreviewingDelegate协议

 

第二步:实现UIViewControllerPreviewingDelegate代理方法


(nullable UIViewController *)previewingContext:(id <UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location**

 

1、创建预览VC

2、创建预览内容View

3、将预览内容View添加到预览VC上

4、返回预览VC

 

代码示例:

 

 

【3】Pop

第一步:遵循 UIViewControllerPreviewingDelegate协议

 

第二步:实现实现UIViewControllerPreviewingDelegate代理方法


(void)previewingContext:(id <UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController*)viewControllerToCommit 
**

 

这个代理方法可以自由定义任何功能,但一般的实现是直接跳转到peek所预览的页面上

 

代码示例:

 

【4】peek快速选项

第一步:找到实现peek的代理方法所返回的ViewController类

第二步:让peek的代理方法所返回的ViewController类遵循 UIPreviewActionItem协议**

 

第三步:实现**UIPreviewActionItem的代理方法**

-(NSArray<id<UIPreviewActionItem>> *)previewActionItems

 

这个代理方法要求返回一个UIPreviewAction数组,UIPreviewAction类中提供了两个创建UIPreviewAction实例的类方法,每个UIPreviewAction实例的点击业务都在block中实现。

 

代码示例:

 

 

二、3D Touch四种效果小Demo

本文由新葡京8455发布,转载请注明来源

关键词: