如何在UIActivityViewController中添加额外动作按钮(如Done按钮)
给UIActivityViewController添加同级Done按钮的实现方案
嘿,这个需求确实有点绕——苹果并没有给UIActivityViewController开放直接添加和Cancel同级操作按钮的官方API,但我们可以通过遍历它的内部视图结构来实现,下面是适配iPhone和iPad的具体方案:
核心思路
UIActivityViewController在iPhone上是以底部Sheet形式展示,Cancel按钮放在底部的UIToolbar中;在iPad上则是Popover弹窗,Cancel按钮在导航栏右侧。我们需要针对这两种布局分别处理,找到对应的容器视图后插入自定义的Done按钮。
具体实现步骤
- 先持有UIActivityViewController的引用,方便后续操作
- 在控制器present完成后,遍历内部视图找到对应的工具栏/导航栏
- 创建Done按钮并添加到对应位置,绑定点击事件
完整代码示例
首先在你的ViewController中添加属性:
@property (nonatomic, strong) UIActivityViewController *activityVC;
然后替换你原有的present代码:
// 初始化分享内容 NSArray *shareItems = @[@"你的分享内容"]; self.activityVC = [[UIActivityViewController alloc] initWithActivityItems:shareItems applicationActivities:nil]; // 排除不需要的系统活动 NSArray *excludeActivities = @[UIActivityTypePrint, UIActivityTypeAssignToContact, UIActivityTypeSaveToCameraRoll, UIActivityTypePostToWeibo]; self.activityVC.excludedActivityTypes = excludeActivities; // 设置完成回调 [self.activityVC setCompletionWithItemsHandler:^(UIActivityType _Nullable activityType, BOOL completed, NSArray * _Nullable returnedItems, NSError * _Nullable activityError) { // 你的原有逻辑处理 }]; // 模态弹出控制器,在完成回调中添加Done按钮 [self presentViewController:self.activityVC animated:YES completion:^{ [self addCustomDoneButton]; }];
接下来实现添加Done按钮的方法:
- (void)addCustomDoneButton { // 先处理iPad的Popover情况 UINavigationController *navVC = (UINavigationController *)self.activityVC.popoverPresentationController?.presentedViewController; if (navVC) { // 创建Done按钮,添加到导航栏左侧(也可以加到右侧和Cancel并排) UIBarButtonItem *doneItem = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self action:@selector(doneButtonTapped:)]; navVC.navigationItem.leftBarButtonItem = doneItem; return; } // 处理iPhone的Sheet情况,遍历子视图找到底部的UIToolbar for (UIView *subview in self.activityVC.view.subviews) { if ([subview isKindOfClass:[UIToolbar class]]) { UIToolbar *toolbar = (UIToolbar *)subview; // 创建Done按钮 UIBarButtonItem *doneItem = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self action:@selector(doneButtonTapped:)]; // 插入到Cancel按钮的前面(保持布局一致性) NSMutableArray *toolbarItems = [toolbar.items mutableCopy]; [toolbarItems insertObject:doneItem atIndex:toolbarItems.count - 1]; toolbar.items = toolbarItems; break; } } } // Done按钮的点击事件处理 - (void)doneButtonTapped:(UIBarButtonItem *)sender { // 关闭分享控制器 [self.activityVC dismissViewControllerAnimated:YES completion:nil]; // 这里可以添加你的自定义业务逻辑 }
注意事项
- 这种方式依赖于UIActivityViewController的内部视图结构,苹果可能在后续iOS版本中调整布局,所以需要在不同系统版本中测试兼容性
- 如果你的App需要适配iOS 13+的Sheet样式,建议在iOS 13及以上版本中额外做视图层级的校验
- 如果追求更稳定的实现,也可以考虑自定义一个仿UIActivityViewController的界面,这种方式更可控但开发成本更高
内容的提问来源于stack exchange,提问作者vroldan
相关产品推荐
相关产品推荐

