预览和弹出(Peek and Pop)
Peek and Pop 是指用户在手机屏幕上用力按压想要预览的选项,弹出一个可以预览二级页面的预览窗口,可以设置一些快捷的操作选项,以类似 sheetAlertView 的方式呈现出来。最后附上完整代码。
代码实现
1.注册视图代理
注意:对于不支持 3D Touch 的设备不会报错,但无法触发 Peek And Pop
注册 Peek And Pop 代理前需要判断设备是否支持 3D Touch
typedef NS_ENUM(NSInteger, UIForceTouchCapability) {
UIForceTouchCapabilityUnknown = 0, // 未知错误
UIForceTouchCapabilityUnavailable = 1, // 不支持
UIForceTouchCapabilityAvailable = 2 // 支持
};
- (BOOL)check3DTouch {
if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) {
return YES;
}
return NO;
}
对支持 3D Touch 的设备再进行注册
// iOS 9及以上且支持3D Touch
if (@available(iOS 9.0, *)) {
if ([self check3DTouch]) {
// 注册代理,传入响应3D Touch的视图
[self registerForPreviewingWithDelegate:self sourceView:self.label];
}
}
registerForPreviewingWithDelegate 参数:
-
delegate: Peek And Pop 代理对象
-
sourceView:触发 Peek And Pop 的视图控件
2.实现预览协议
Peek And Pop 功能需要实现 UIViewControllerPreviewingDelegate 的两个代理方法
UIKIT_EXTERN API_AVAILABLE(ios(9.0)) NS_SWIFT_UI_ACTOR
@protocol UIViewControllerPreviewingDelegate <NSObject>
// If you return nil, a preview presentation will not be performed
- (nullable UIViewController *)previewingContext:(id <UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location API_DEPRECATED("UIViewControllerPreviewing is deprecated. Please use UIContextMenuInteraction.", ios(9.0, 13.0)) API_UNAVAILABLE(visionos);
- (void)previewingContext:(id <UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit API_DEPRECATED("UIViewControllerPreviewing is deprecated. Please use UIContextMenuInteraction.", ios(9.0, 13.0)) API_UNAVAILABLE(visionos);
@end
#pragma mark - peek and pop Delegate
// pop 加重按压力度弹起的界面
- (void)previewingContext:(nonnull id<UIViewControllerPreviewing>)previewingContext commitViewController:(nonnull UIViewController *)viewControllerToCommit {
// 将配置好的控制器推入导航栈
[self.navigationController pushViewController:viewControllerToCommit animated:YES];
}
// peek 长按预览界面,其他区域则会变模糊
- (nullable UIViewController *)previewingContext:(nonnull id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location {
self.count++;
// 创建要返回的viewController
DetailViewController *detailVC = [[DetailViewController alloc] init];
detailVC.message = [NSString stringWithFormat:@"count: %ld", self.count];
// 设置预览视图的大小
detailVC.preferredContentSize = CGSizeMake(300, 500); // 根据需要调整大小
// 启用其他UI元素模糊,该区域内不被虚化,通常为触摸控件的位置, 不设置,将使用系统提供的合适区域。
previewingContext.sourceRect = self.label.frame;
return detailVC;
}
-
唤起Peek:长按【Peek & Pop】控件,此时就会触发
- (nullable UIViewController*)previewingContext:viewControllerForLocation:代理方法,返回detailVC预览视图对象,并根据设置的预览视图大小进行展示 -
唤起Pop:在唤起 Peek 的前提下继续加大按压力度就会触发
- (void)previewingContext: commitViewController:代理方法,展示完整的预览页面
预览视图的大小可根据 preferredContentSize 调节,
3.预览菜单
在提供预览的控制器中提供 previewActionItems 预览菜单数据即可
#pragma mark - previewActionItems Delegate
- (NSArray<id<UIPreviewActionItem>> *)previewActionItems {
UIPreviewAction *noReadAction = [UIPreviewAction actionWithTitle:@"标为未读" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"标为未读");
}];
UIPreviewAction *stickAction = [UIPreviewAction actionWithTitle:@"置顶" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"置顶");
}];
UIPreviewAction *deleteAction = [UIPreviewAction actionWithTitle:@"删除" style:UIPreviewActionStyleDestructive handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"删除");
}];
return @[noReadAction, stickAction, deleteAction];
}
预览菜单也支持 group 概念,点击一个菜单操作会展开其子菜单
- (NSArray<id<UIPreviewActionItem>> *)previewActionItems {
UIPreviewAction *noReadAction = [UIPreviewAction actionWithTitle:@"标为未读" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"标为未读");
}];
UIPreviewAction *stickAction = [UIPreviewAction actionWithTitle:@"置顶" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"置顶");
}];
UIPreviewAction *deleteAction = [UIPreviewAction actionWithTitle:@"删除" style:UIPreviewActionStyleDestructive handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
NSLog(@"删除");
}];
UIPreviewActionGroup *group = [UIPreviewActionGroup actionGroupWithTitle:@"group" style:UIPreviewActionStyleDefault actions:@[noReadAction,stickAction]];
return @[group, deleteAction];
}
点击【Group】会再次弹起子菜单
项目链接
代码量有点多,我放到了github上,需要的自取
友情提示
本文同步自微信公众号 "程序员小溪" ,这里只是同步,想看及时消息请移步我的公众号,不定时更新我的学习经验。