iOS 3D Touch 开发(二) Peek & Pop

Posted by Calvin on 2017-04-20

上篇文章写了 3D Touch 的 Quick Actions(快捷菜单),如果你也在添加 3D Touch 功能到 App 中,请点击『文章链接』查看 3D Touch 开发的第一篇文章,接下来我们来谈谈 Peek 和 Pop 的实现。

先上一张效果图:
2017042014926558317018.jpg

如图从左至右展示了 Peek 和 Pop 的三个阶段:

(1)提示用户这里有 3D Touch 的交互,会使交互控件周围模糊。
(2)继续深按,会出现预览视图。
(3)通过视图上的交互控件进行进一步交互。

Peek 实现

因为我是在 UITableViewCell 中长按实现的此功能,接下来上代码:

1、首先检测 3D Touch 是否可用,可以使用的话注册代理和视图

static NSString *homeTwoCell = @"HomeOneCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:homeTwoCell];
if (!cell) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:homeTwoCell];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.text = @"3D Touch";
// 检测3D Touch可用性 并注册
if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) {
[self registerForPreviewingWithDelegate:self sourceView:cell];
}

2、实现 Peek 代理方法

#pragma mark --
#pragma mark -- peek手势
- (nullable UIViewController *)previewingContext:(id <UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location
{
// 转化坐标
location = [self.tableView convertPoint:location fromView:[previewingContext sourceView]];
// 根据locaton获取位置
NSIndexPath *path = [self.tableView indexPathForRowAtPoint:location];
// 根据位置获取字典数据传传入控制器
DetailViewController *detail = [DetailViewController new];
detail.titleStr = [NSString stringWithFormat:@"%ld",(long)path.row];
return detail;
}

至此已经实现了点击 Cell 出现 Peek,当然此时点击 Cell 出现的 Peek 视图的大小是系统默认的(如上图所示,Peek 视图的尺寸是系统默认的)。

如果我们想自定义 Peek 视图的大小该如何设置呢?


『 04.21 更正』

如果在 Peek 页面想要自定义 PeekView 大小的时候,只需要在上面的代码中添加如下代码即可,设置好自己想要的预览试图的大小,添加此代码不影响 Peek 的3个阶段展示:

detail.preferredContentSize = CGSizeMake(0.0f,ScreenHeight-160);

设置以后的视图效果如图所示:
20170420149265672386501.jpg

Pop 实现

当出现 Peek 视图后,用户继续长按会有 Pop 视图,即进入到详情页面。因为我们已经实现了 Peek 视图的代理方法,所以在此实现一下 Pop 视图的代理方法即可。

#pragma mark --
#pragma mark -- pop手势
/**
*previewingContext:被预览的视图控制器的内容对象 == 上面代理方法中的previewingContext,内存中是同一个对象
*viewControllerToCommit:被present(pop)的视图控制器 == 上面代理方法中返回的控制器,内存中是同一个对象
*调用时间:pop阶段调用这个方法
*作用:配置并且present一个commit(pop)视图控制器。
*/
- (void)previewingContext:(id <UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit{
viewControllerToCommit.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:viewControllerToCommit animated:YES];
}

Peek quick action(Peek 视图下的快捷菜单)

部分应用在 Peek 视图是有一些快捷菜单的,如图:
20170420149265672386501.jpg

如何设置 Peek 视图菜单呢?

在即将进入的 DetailView 中声明菜单数组:

@property (nonatomic, readonly) NSArray *previewActionItems;

懒加载数组并在每个 Action 中实现事件:

- (NSArray<id<UIPreviewActionItem>> *)previewActionItems{
// 分享
UIPreviewAction *itemOne = [UIPreviewAction actionWithTitle:@"点赞" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
// 实现分享
}];
// 点赞
UIPreviewAction *itemTwo = [UIPreviewAction actionWithTitle:@"分享" style:UIPreviewActionStyleDestructive handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
// 实现点赞
}];
return @[itemOne,itemTwo];
}

这样在 Peek 界面中就会出现对应的菜单,并做出对应的处理。

至此,3D Touch 的 Peek 和 Pop 实现已经基本完毕,如果后续有更新再继续添加。

附:『源码下载』