You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何处理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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:01:56