如何实现iOS16照片应用右上角液态玻璃按钮同款动画效果
iOS16 照片App“最近删除”右上角按钮交互实现方案
核心效果拆解
这个按钮的交互包含两个关键部分:
- 文字切换(“选择” ↔ “取消”)
- 缩放+背景色/文字色的平滑过渡动画
UIKit 实现方案(Swift)
以下是可直接复用的代码,完全贴合系统交互逻辑:
- 自定义按钮类
创建继承自UIButton的子类,封装状态切换和动画:
import UIKit class SelectionToggleButton: UIButton { private var isInSelectionMode = false override init(frame: CGRect) { super.init(frame: frame) setupStyle() } required init?(coder: NSCoder) { super.init(coder: coder) setupStyle() } private func setupStyle() { // 初始状态配置 setTitle("选择", for: .normal) setTitleColor(.systemBlue, for: .normal) titleLabel?.font = .systemFont(ofSize: 17, weight: .semibold) contentEdgeInsets = UIEdgeInsets(top: 6, left: 12, bottom: 6, right: 12) addTarget(self, action: #selector(toggleMode), for: .touchUpInside) } @objc private func toggleMode() { isInSelectionMode.toggle() // 组合动画:缩放+状态切换 UIView.animate(withDuration: 0.25, delay: 0, options: .curveEaseInOut) { self.transform = CGAffineTransform(scaleX: 0.95, y: 0.95) if self.isInSelectionMode { self.setTitle("取消", for: .normal) self.setTitleColor(.systemWhite, for: .normal) self.backgroundColor = .systemBlue self.layer.cornerRadius = 8 } else { self.setTitle("选择", for: .normal) self.setTitleColor(.systemBlue, for: .normal) self.backgroundColor = .clear self.layer.cornerRadius = 0 } } completion: { _ in UIView.animate(withDuration: 0.15) { self.transform = .identity } } } }
- 添加到导航栏
在ViewController中集成按钮:
override func viewDidLoad() { super.viewDidLoad() let toggleBtn = SelectionToggleButton(type: .system) navigationItem.rightBarButtonItem = UIBarButtonItem(customView: toggleBtn) }
SwiftUI 实现方案(可选)
适配SwiftUI项目的简洁版本:
import SwiftUI struct SelectionToggleButton: View { @State private var isSelecting = false var body: some View { Button(action: { withAnimation(.interpolatingSpring(stiffness: 300, damping: 30)) { isSelecting.toggle() } }) { Text(isSelecting ? "取消" : "选择") .font(.system(size: 17, weight: .semibold)) .foregroundColor(isSelecting ? .white : .blue) .padding(.horizontal, 12) .padding(.vertical, 6) .background(isSelecting ? Color.blue : Color.clear) .cornerRadius(8) } } } // 使用示例 struct RecentsDeletedView: View { var body: some View { NavigationStack { List { // 最近删除内容列表 } .navigationTitle("最近删除") .toolbar { ToolbarItem(placement: .navigationBarTrailing) { SelectionToggleButton() } } } } }
细节优化
- 若适配暗黑模式,将颜色替换为动态颜色(如
.label、.systemFill) - 可根据需求调整动画时长、弹簧参数,更贴近系统手感
内容的提问来源于stack exchange,提问作者Ni VIP
相关产品推荐
相关产品推荐

