如何处理UIActivityViewController完成回调?滑动分享图片状态适配
实现取消分享时的图片动画效果
首先恭喜你开发自己的第一个应用!这已经很棒了😉。我们来解决你说的取消分享时的动画问题:
问题分析
当前你在取消分享后直接调用了moveView...(.backIn)让图片移回原位,但可能在UIActivityViewController弹出的过程中,系统的视图层级变化导致你的图片已经自动回到了屏幕内,所以现在的流程是“图片回到屏幕→移回原位”。而你需要的是“取消分享→图片先在屏幕外→再移回原位”,所以我们需要调整动画的顺序:先把图片重新移到屏幕外,再执行移回原位的动画。
解决方案
1. 先修改你的移动视图方法,添加完成回调
首先需要让moveViewVertically和moveViewHorizontally支持动画完成后的回调,这样我们可以在第一个动画结束后再执行第二个动画:
// 先确保你的MoveDirection枚举包含offScreen和backIn(如果还没定义的话) enum MoveDirection { case offScreen case backIn } // 修改垂直移动方法,增加completion参数 func moveViewVertically(_ direction: MoveDirection, range: CGFloat, completion: ((Bool) -> Void)? = nil) { let targetY: CGFloat switch direction { case .offScreen: // 这里用你原来滑动图片到屏幕外的目标Y值,比如self.offScreenPosition.y targetY = self.offScreenPosition.y case .backIn: // 图片原位的Y值 targetY = self.view.bounds.midY // 或者你原来的初始位置Y值 } UIView.animate(withDuration: 0.3, animations: { self.grids.center.y = targetY }, completion: completion) } // 同理修改水平移动方法 func moveViewHorizontally(_ direction: MoveDirection, range: CGFloat, completion: ((Bool) -> Void)? = nil) { let targetX: CGFloat switch direction { case .offScreen: targetX = self.offScreenPosition.x case .backIn: targetX = self.view.bounds.midX } UIView.animate(withDuration: 0.3, animations: { self.grids.center.x = targetX }, completion: completion) }
2. 调整分享控制器的完成回调逻辑
在completionWithItemsHandler的取消分支里,先执行“移到屏幕外”的动画,等这个动画完成后,再执行“移回原位”的动画:
let activityViewController = UIActivityViewController(activityItems: [imageToShare], applicationActivities: nil) self.present(activityViewController, animated: true) { print("presented") print("position share is \(self.grids.center)") } switch deviceOrientation { case "portrait": activityViewController.completionWithItemsHandler = { (activityType: UIActivityType?, completed: Bool, returnedItems: [Any]?, error: Error?) in if !completed { print("cancelled") // 第一步:先把图片移回屏幕外 self.moveViewVertically(.offScreen, range: self.verticalRange) { finished in // 确认第一个动画完成后,再执行移回原位的动画 if finished { self.moveViewVertically(.backIn, range: self.verticalRange) } } } else { print("completed") self.moveViewVertically(.backIn, range: self.verticalRange) } } case "landscape": activityViewController.completionWithItemsHandler = { (activityType: UIActivityType?, completed: Bool, returnedItems: [Any]?, error: Error?) in if !completed { print("cancelled") self.moveViewHorizontally(.offScreen, range: self.horizontalRange) { finished in if finished { self.moveViewHorizontally(.backIn, range: self.horizontalRange) } } } else { self.moveViewHorizontally(.backIn, range: self.horizontalRange) } } default: break }
关键说明
- 我们通过给动画添加完成回调,确保了“移到屏幕外”的动画完全结束后,才开始“移回原位”的动画,这样就实现了你想要的顺序。
- 注意
offScreenPosition要和你滑动图片时的目标位置保持一致,这样动画看起来才连贯。
如果你的moveView方法原来已经有自己的动画逻辑,只需要把completion参数加进去,在动画的completion里调用传入的闭包就可以了。
内容的提问来源于stack exchange,提问作者morgan
相关产品推荐
相关产品推荐

