Instagram的3D Touch经验谈

来源:互联网 发布:flash8 mac中文版 编辑:程序博客网 时间:2024/05/04 20:56

上周,Apple发布了最新的iPhone产品线,从iPhone 6s开始,产品都添加了一项硬件属性,叫做3D touch。作为屏幕的一部分,新的传感器将能识别用力按下屏幕的动作并检测到精确的压力变化。

同新的硬件一起,Apple发布了3个新的API,帮助开发者为App添加另一维度的交互。”Quick Actions”让你在点击app图标时选择四个菜单项。另一个功能可以让你“预览”某项内容,然后展示内部更详细的信息。最后一个API通过UITouch对象提供给开发者按压动作的详情,比如力度和maximumPossibleForce。

我们有机会在这项新功能发布之初就集成它到Instagram中。在添加了shortcuts和peeking功能后,照片和视频看起来是如此自然,这很让人惊喜。这些新的API在添加3D交互功能时衔接自然,我们整理了实施时的一些要点。

快捷操作(Quick Actions)

快捷操作让用户可以快速跳转到app的某项功能中,而忽略掉中间步骤。例如在Instagram中,我们添加最常用的几项功能到快捷操作中:Search, Direct, Activity和Creation.
(点击查看动图)

001.png

在主界面添加快捷操作相当简单,只需要创建UIApplicationShortcutItems的数组,并添加到app的delegate中。每个item都有一个代表类型的字符串和可选的UIApplicationShortcutIcon作为icon。

在Instagram中,我们创建了UIApplicationShortcutItem的扩展,用来创建快捷方式。

  + (instancetype)ig_searchItem {  NSString *title = NSLocalizedString(@"Search", nil);  UIApplicationShortcutIcon *icon = [UIApplicationShortcutIcon iconWithTemplateImageName:@"search"];  UIApplicationShortcutItem *item = [[UIApplicationShortcutItem alloc] initWithType:@"search"                                                                     localizedTitle:title                                                                  localizedSubtitle:nil                                                                               icon:icon                                                                           userInfo:nil];  return item;}

根据用户是否登录的条件,我们动态的配置快捷方式的item:

application.shortcutItems = @[  [UIApplicationShortcutItem ig_postItem],  [UIApplicationShortcutItem ig_activityItem],  [UIApplicationShortcutItem ig_searchItem],  [UIApplicationShortcutItem ig_directItem]    ];

我们的架构已经处理过诸如app链接和推送通知的流程,因此只需要在-application:performActionForShortcutItem:completionHandler:方法中调用对应的流程即可。

Peek and Pop(预览和详阅)

如同使用放大镜拉近视角,预览(Peek)内容(照片、视频)让你可以获得更多信息而不需要加载完整内容。

Instagram首先将Peek功能添加到了小图片和视频上。

Peek(预览)和Pop(详阅)相关的API为UIViewControllerPreviewingDelegate,它通过view来注册。在Instagram中,我们只将其注册到可以接受到touch事件的controller的view上。当3D touch事件发生时,delegate来检测view中的哪个对象被点击。

45.png

如果delegate判断有Peek(预览)动作发生,它仍需要处理两件事情:1. 设置预览动作发生的view的rect;2. 返回展示的viewcontroller。

12056959_1498703093777728_1543774343_n.jpg

当3D touch发生时,会传递给你context信息,包含源view和点击发生的point。自定义的delegate需要通过这个point映射到一个view,然后查找到需要预览的数据。

大多数的Instagram功能基于UICollectionView和UITableView实现。这两者在数据和UI间对应方面都有不错的API支持。

 - (UIViewController *)previewingContext:(id)previewingContext viewControllerForLocation:(CGPoint)location {  UICollectionView *collectionView = (UICollectionView *)[previewingContext sourceView];  NSIndexPath *indexPath = [collectionView indexPathForItemAtPoint:location];        if (indexPath) {    IGPostCell *cell = [collectionView cellForItemAtIndexPath:indexPath];    [previewingContext setSourceRect:cell.frame];        IGPost *post = self.feedController.posts[indexPath.row];    IGThumbnailPreviewController *controller = [[IGThumbnailPreviewController alloc] initWithPost:post];      return controller;  }    // no peek  return nil;}

将预览相关的API和现有的view和功能结合后,查看Instagram照片和视频变的异常简单。
(点击查看动图)

0111.png

我们为header和comment中的用户名添加了查看信息的功能。用来预览用户信息的delegate和显示照片/视频的实现类似:

  • 使用3D touch点击的location和查找到的index path找到对应的cell。

  • 将点击的point关联转换到cell中的textview上。

  • 通过该point获取到text view中的attributed string的属性。

  • 如果找到了用户名称的属性,则返回IGUserPreviewController。

将这些实现串起来,看起来就像这样:

37.gif

混合内容展示

Instagram中的activity feed功能包含了用户的tag和缩略图。我们之前分别创建过UIViewControllerPreviewingDelegate的对象,用来显示这两种内容。这里我们需要把这些组合在一起。

拷贝已有代码到新的delegate中的做法并不明智。我们选择使用composition模式来组合profile和post展示的delegate代码,这样创建一个新的对象,只需要传递touch 事件即可。

@interface IGUserThumbnailPreviewingHandler : NSObject@property (nonatomic, strong) IGUserPreviewingHandler *userDelegate;@property (nonatomic, strong) IGFeedThumbnailPreviewingHandler *thumbnailDelegate;@end- (UIViewController *)previewingContext:(idUIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location {    id controller = [self.thumbnailDelegate previewingContext:previewingContext viewControllerForLocation:location];    if (!controller) {        controller = [self.userDelegate previewingContext:previewingContext viewControllerForLocation:location];    }    return controller;}

预览视图控制器

用来显示预览的controller只是UIViewController的子类,在某些特别属性上有所不同。

一开始,controller完全无法交互,你无法在上面点击按钮或添加自定义手势。这里我们需要提供遵循UIPreviewActionItem协议的对象组成的数组。在Instagram中,我们只用UIPreviewActions。

这些功能看起来很像UIAlertController的action item。

12057023_182232978776192_861894133_n.jpg

在整个Instagram程序中,我们只在需要的时候加载数据,并缓存以备以后使用。这样做既节省了网络等待的时间,又不会浪费用户的带宽。

有时,当预览用户profile时,我们获取的数据还不足以用来显示最新照片或关注者数量。预览用的view controller仍然会调用viewDidLoad, viewWillAppear:和其他UIViewController事件。在其中可以获取网络数据并更新UI。

最后,我们发现可以通过修改controller的preferredContentSize来调整预览视图的大小,即便是controller已经展示了,这样的改变仍可生效。不过,这个属性无法作用于动画中。

结论

对于Instagram来说,3D touch是2015年版本的“右键点击”。它添加了另一种深度,带来了不同的交互意向:你可能还没有决定跳转到某个内容上去,但你肯定会对它感兴趣。只要有这种想法,预览内容的功能可以让你对眼前内容快速一瞥,而不跳转页面,这样可以快速返回到之前浏览的内容中。

快捷操作让你能够直接跳转到创建新帖子的步骤中,也可以让你快速查看Instagram中最近发生了些什么,而不需要启动程序后,一步一步的点击。在“简约”理念的指导下,快捷操作让Instagram更好用。

0 0