SwiftUI自定义搜索栏子视图显隐过渡动画失效问题
SwiftUI自定义搜索栏淡入淡出动画失效问题解决
问题根源
你的清除按钮(X)和Cancel按钮的过渡动画失效,核心原因是状态变化未在动画上下文内执行。虽然外层HStack添加了animation修饰符,但@FocusState的切换以及条件视图的插入/移除,需要明确通过withAnimation包裹状态更新,才能触发transition定义的动画效果。
解决方案
- 在触发
isEditing状态变更的动作中,用withAnimation包裹状态更新 - 移除外层
HStack的全局animation修饰符,避免与withAnimation产生冲突 - 修正
onSubmit的错误声明(无需@State修饰)
修改后的完整代码
struct CustomSearchBar: View { var prompt: String @Binding var query: String @FocusState private var isEditing: Bool var onSubmit: () -> Void // 移除不必要的@State修饰 var body: some View { HStack(alignment: .center) { TextField(prompt, text: $query) .onSubmit(onSubmit) .focused($isEditing) .padding(8) .padding(.horizontal, 25) .background(Color(.systemGray6)) .overlay( HStack { Image(systemName: "magnifyingglass") .foregroundColor(.gray) .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading) .padding(.leading, 8) if isEditing { Button { query = "" } label: { Image(systemName: "multiply.circle.fill") .foregroundColor(.gray) .padding([.leading, .trailing], 8) } .transition(.opacity) } } ) .onTapGesture { // 用withAnimation包裹状态切换,触发动画上下文 withAnimation(.linear(duration: 0.3)) { isEditing = true } } .submitLabel(.search) .transition(.slide) if isEditing { Button { // 同样用withAnimation包裹状态回退 withAnimation(.linear(duration: 0.3)) { isEditing = false query = "" } } label: { Text("Cancel") .foregroundColor(.red) } .padding(.trailing, 10) .transition(.opacity) } } // 移除全局animation修饰符,避免冲突 } }
关键修改说明
withAnimation的作用:当修改isEditing状态时,withAnimation会为该状态变化创建动画上下文,所有依赖此状态的视图过渡(如transition(.opacity))都会自动应用指定的动画参数。- 移除全局动画修饰符:全局
animation修饰符的作用范围较宽泛,容易和局部动画逻辑冲突,对于条件视图的过渡,使用withAnimation做精准控制更可靠。 - 修正闭包参数声明:
onSubmit作为组件的闭包参数,不需要@State修饰,否则会引发编译错误。
内容的提问来源于stack exchange,提问作者cenas
相关产品推荐
相关产品推荐

