如何为同一SwiftUI视图设置两种不同的条件转场效果?
解决SwiftUI中X按钮根据点击源应用不同移除转场的问题
问题根源
你遇到的转场延迟触发问题,核心原因是@State变量的更新与视图移除的状态变更属于同一批次的视图刷新。SwiftUI会先处理状态变更,再应用转场逻辑,导致当前移除操作无法获取到刚更新的transition值,只能在下一次视图刷新时生效。
解决方案
不需要用@State持久化转场样式,而是在触发移除操作时,通过Transaction直接为当前动画指定对应的转场效果,确保转场和视图移除操作同步生效。
修改后的完整代码
import Combine import Foundation import SwiftUI extension String { var isNonEmpty: Bool { !isEmpty } } struct SearchBar: View { @Binding var searchField: String let clearSearchField: () -> Void let isFocus: Bool let setFocus: (Bool) -> Void var body: some View { HStack(spacing: 16) { ZStack { Color.gray VStack(alignment: .leading) { HStack { TextField( "Placeholder", text: $searchField, onEditingChanged: { _ in setFocus(true) } ) .foregroundColor(.white) Spacer() if searchField.isNonEmpty { Button { var transaction = Transaction(animation: .default) transaction.transition = .opacity withTransaction(transaction) { clearSearchField() } } label: { Text("X") } .transition(.asymmetric( insertion: .opacity, removal: .identity )) } } } .padding(16) } .cornerRadius(8) if isFocus { Button( action: { hideKeyboard() var transaction = Transaction(animation: .default) transaction.transition = .move(edge: .trailing).combined(with: .opacity) withTransaction(transaction) { clearSearchField() setFocus(false) } }, label: { Text("Cancel") .foregroundColor(.white) } ) .transition(.move(edge: .trailing).combined(with: .opacity)) } } .frame(height: 48) .foregroundColor(searchField.isEmpty ? .gray : .white) .padding(16) .animation(.default, value: isFocus) } private func hideKeyboard() { UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) } }
关键修改点
- 移除
@State var transition:转场样式不需要持久化,每次操作时动态指定即可。 - 用
Transaction绑定转场与状态变更:在触发clearSearchField(导致X按钮消失)前,创建Transaction并设置对应转场,通过withTransaction包裹状态变更,确保当前移除动画使用指定转场。 - X按钮转场配置:将移除转场设为
.identity,表示使用事务中指定的转场样式,插入转场保留原有opacity动画。 - 修复颜色命名:将原代码中的
.grey改为SwiftUI标准命名.gray。
修改后,点击X按钮时,X按钮会立即以opacity效果淡出;点击Cancel按钮时,X按钮会立即以move+opacity的组合效果滑出,完全符合预期行为。
内容的提问来源于stack exchange,提问作者victorgson
相关产品推荐
相关产品推荐

