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

SwiftUI 长按后将视图移至中央并模糊背景 实现信息App同类效果

iOS实现苹果信息App长按消息弹窗效果方案

该效果完全可以通过原生API实现,不需要引入第三方库,以下是UIKit和SwiftUI两个场景的实现方案:

UIKit实现

实现逻辑分为3个核心步骤:

  • 给目标消息视图添加UILongPressGestureRecognizer监听长按事件
  • 长按触发时在当前Window层添加UIVisualEffectView实现背景模糊效果,同步做透明度渐入动画
  • 对原消息视图生成快照,将快照从原位置动画移动到屏幕中央,同时叠加缩放动效,隐藏原视图

核心代码参考:

@objc func handleLongPress(_ gesture: UILongPressGestureRecognizer) {
    guard gesture.state == .began, let targetView = gesture.view, let window = view.window else { return }
    // 初始化模糊背景
    let blurEffect = UIBlurEffect(style: .systemUltraThinMaterial)
    let blurView = UIVisualEffectView(effect: blurEffect)
    blurView.frame = window.bounds
    blurView.alpha = 0
    window.addSubview(blurView)
    // 生成原消息视图快照
    guard let snapshot = targetView.snapshotView(afterScreenUpdates: false) else { return }
    let originFrame = targetView.convert(targetView.bounds, to: window)
    snapshot.frame = originFrame
    window.addSubview(snapshot)
    targetView.isHidden = true
    // 执行同步动画
    UIView.animate(withDuration: 0.28) {
        blurView.alpha = 1
        snapshot.center = window.center
        snapshot.transform = .init(scaleX: 1.12, y: 1.12)
    }
}

手势结束恢复时只需反向执行动画,移除临时的模糊层和快照,恢复原消息视图的显示即可。

SwiftUI实现

可以通过matchedGeometryEffect转场API快速实现,逻辑和UIKit一致:

  • 用@State变量记录长按触发状态、选中的消息ID
  • 列表层根据长按状态叠加blur模糊效果,做动画过渡
  • 选中的消息通过matchedGeometryEffect匹配原位置和中央弹窗位置,做无缝动效

核心代码参考:

struct MessageListView: View {
    @Namespace var msgAnimationNamespace
    @State private var isLongPressActive = false
    @State private var selectedMsgID: String?
    // 你的消息列表数据
    let messages: [MessageItem] = []
    
    var body: some View {
        ScrollView {
            LazyVStack(spacing: 12) {
                ForEach(messages) { msg in
                    Text(msg.content)
                        .padding(.horizontal, 16)
                        .padding(.vertical, 10)
                        .background(Color(UIColor.systemBlue))
                        .foregroundColor(.white)
                        .cornerRadius(16)
                        .matchedGeometryEffect(id: msg.id, in: msgAnimationNamespace, isSource: selectedMsgID != msg.id)
                        .onLongPressGesture(minimumDuration: 0.3) {
                            withAnimation(.easeInOut(duration: 0.28)) {
                                selectedMsgID = msg.id
                                isLongPressActive = true
                            }
                        }
                }
            }
            .padding()
        }
        .blur(radius: isLongPressActive ? 8 : 0)
        .overlay {
            if isLongPressActive, let targetID = selectedMsgID, let targetMsg = messages.first(where: {$0.id == targetID}) {
                Text(targetMsg.content)
                    .padding(.horizontal, 16)
                    .padding(.vertical, 10)
                    .background(Color(UIColor.systemBlue))
                    .foregroundColor(.white)
                    .cornerRadius(16)
                    .scaleEffect(1.12)
                    .matchedGeometryEffect(id: targetID, in: msgAnimationNamespace, isSource: false)
                    .onTapGesture {
                        withAnimation(.easeInOut(duration: 0.28)) {
                            isLongPressActive = false
                            selectedMsgID = nil
                        }
                    }
            }
        }
    }
}

可以根据需求调整模糊半径、动画时长、缩放比例,就能完全对齐原生信息App的效果。

内容的提问来源于stack exchange,提问作者alionthego

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 18:48:02