前言
3D Touch是iOS 9(系统版本小于iOS 9的不支持)出现的功能,虽然出来有段时间了,但其实有运用到3D Touch的App并不算很多。小编见过3D Touch做的比较好的App中,微信是佼佼者。在这里,小编班门弄斧一下,和大家说说3D Touch的简易实现方式。3D Touch一共有三种呈现形式,小编在此会一一举例,总体效果图如下:

效果
效果一
效果一就是按下屏幕,出现选择框,这是3D Touch目前来说被使用的最多的技术。效果图如下:

实现方法
效果一的实现其实非常简单,这里简单的说一下,效果一的每一个item里面都有3个东西,包括主标题、子标题和图片。主标题和图片必须设置,子标题可以不设置。图片可以用系统自带的,也可以自己设定。
在AppDelegate中加入下列代码即可完成,可以按照自己的要求增加选项的数量:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 判断系统版本大于9.0(只支持9.0以上的操作)
if ([[[UIDevice currentDevice]systemVersion]floatValue] >= 9.0) {
// 自定义图标的设置方法
// UIApplicationShortcutIcon *home = [UIApplicationShortcutIcon iconWithTemplateImageName:@""];
// 系统图标的设置方法
UIApplicationShortcutIcon *home = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeHome];
// 主标题和图标必须设置
UIApplicationShortcutItem *item1 = [[UIApplicationShortcutItem alloc]initWithType:@"type" localizedTitle:@"主标题、子标题、图标" localizedSubtitle:@"子标题" icon:home userInfo:nil];
UIApplicationShortcutItem *item2 = [[UIApplicationShortcutItem alloc]initWithType:@"type" localizedTitle:@"主标题、图标" localizedSubtitle:nil icon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeAdd] userInfo:nil];
// 设置按钮
[[UIApplication sharedApplication] setShortcutItems:[@[item1,item2]mutableCopy]];
}
return YES;
}
// 通过3dtouch菜单启动
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {
NSLog(@"%@", shortcutItem.localizedTitle);
}
效果二
效果二是点击View预览视图,这个功能的实现,主要是因为在iOS 9时加入了UIViewControllerPreviewingDelegate这个协议,小编在例子中使用的是collectionView,大家可以把代理加到相应的地方。

实现方法
在这里先说一下如果只是点击预览而不需要进去的做法。
- 第一步是设置代理;
- 第二步是绑定代理(注意:如果在tableView和collectionView中不要反复绑定);
- 第三步是建立新的视图控制器,这个控制器是用来放需要预览的视图的;
- 第四步是调用系统Api中的 - (nullable UIViewController *)previewingContext:(id <UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location NS_AVAILABLE_IOS(9_0) 方法。
步骤1:
@interface DemoCell : UICollectionViewCell
/**
设置3D Touch代理
*/
@property (weak, nonatomic) id<UIViewControllerPreviewingDelegate> previewingDelegate;
@end
//---------------------------------------------------------------------
@implementation DemoCell
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self){
self.contentView.backgroundColor = [UIColor colorWithRed:arc4random() % 256 / 255.0 green:arc4random() % 256 / 255.0 blue:arc4random() % 256 / 255.0 alpha:1];
}
return self;
}
- (void)setPreviewingDelegate:(id<UIViewControllerPreviewingDelegate>)previewingDelegate
{
// 这里设置代理,需要控制好设置(registerForPreviewingWithDelegate)的次数,确保每个cell都有register就可以,但不要重复(若大量registerForPreviewingWithDelegate 会造成滑动失控)
if (!_previewingDelegate) {
_previewingDelegate = previewingDelegate;
UIViewController *controller = (UIViewController *)previewingDelegate;
[controller registerForPreviewingWithDelegate:previewingDelegate sourceView:self.contentView];
}
}
@end
步骤2:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
DemoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
//设置代理
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9.0){
cell.previewingDelegate = self;
}
return cell;
}
步骤3:
@interface PreViewController : UIViewController
@property (assign,nonatomic) NSInteger currentPage;
@end
//---------------------------------------------------------------------
@implementation PreViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 100,30)];
label.center = self.view.center;
label.text = [NSString stringWithFormat:@"当前第%zd页",self.currentPage];
UIView *view = [[UIView alloc]initWithFrame:(CGRect){0,0,375,20}];
[view setBackgroundColor:[UIColor redColor]];
[self.view addSubview:view];
[self.view addSubview:label];
// Do any additional setup after loading the view.
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
// 在iOS9 中 UITouch对象加入了 force属性,对应的是3dtouch的力度
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9.0){
UITouch *touch = [[touches allObjects]lastObject];
NSLog(@"%lf",touch.force);
}
}
@end
步骤4:
- (UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location
{
// 1.我们可以通过触控的location获取 当前点击的是第几个元素(位于collectionview)
// 2.由于响应3dtouch事件的view是cell的contentView,我们对触控拿到的location要进行一个转换(相对于collectionview(父视图)来说的位置
// 3.这里通过previewingContext中sourceView获取到触摸的view
UIView *contentView = previewingContext.sourceView;
// 看回"2" 中第一句话,我们要拿到这个触控的location位于collectionview中的位置
CGPoint iLocation = [contentView convertPoint:location toView:self.collectionView];
// 将获取到的位置 通过collectionview获取indexPath
NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:iLocation];
PreViewController *preViewController = [[PreViewController alloc]init];
preViewController.currentPage = indexPath.item;
return preViewController;
}
加上点击进入该页面功能
实现这个功能只需要在上面的基础上调用UIViewControllerPreviewingDelegate的另一个代理方法即可。
- (void)previewingContext:(id<UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit
{
// 打开详情页触发
if (viewControllerToCommit) {
[self showViewController:viewControllerToCommit sender:self];
}
}
效果三
效果三是在效果二的基础上实现的,若没有实现效果二,请先实现效果二。效果图如下:

实现方法
在新建的视图控制器中加入代理的方法即可,如下
- (NSArray<id<UIPreviewActionItem>> *)previewActionItems{
UIPreviewAction *itemA = [UIPreviewAction actionWithTitle:@"A" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"操作A");
}];
UIPreviewAction *itemB = [UIPreviewAction actionWithTitle:@"B" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"操作B");
}];
UIPreviewAction *itemC = [UIPreviewAction actionWithTitle:@"C" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"操作C");
}];
return @[itemA,itemB,itemC];
}
这就是3D Touch的内容,最后,希望这篇文章对各位看官们有所帮助。Demo下载地址:Demo