日安!

我有两个按钮,一个带有X,另一个表示取消.根据我按下的按钮,我希望X按钮有不同的过渡.

按X键时: 我希望删除的X按钮是.opacity.Animation(.Default)

按取消时: 我希望删除的X按钮是.move(边:.traending).组合(与:.opacity).动画(.Default)

对于上下文,它是一个文本字段,当我输入一些东西时,X按钮就会出现.

我try 了使用State变量,在按钮操作中设置了With Animation中的过渡. 这似乎设定了下一个周期/更新的过渡,而不是当前的周期/更新. 我也调查过交易,但我只能从那里操纵动画?

因此,当我按下X按钮时,下一次我按下X或取消时,它将是我设置的过渡.当我按下Cancel时,下一次它会将转换设置为他们的另一个转换.

gif

正如你在GIF中看到的,它在转换之间循环,但我希望 for each 按钮设置它们.

预期行为:

当按X键时,我希望它使用.不透明度淡出.

当按下Cancel时,我希望X按钮"滑出",使用.move作为删除过渡.

import Combine
import Foundation
import SwiftUI

struct SearchBar: View {
    @Binding var searchField: String
    let clearSearchField: () -> Void
    let isFocus: Bool
    let setFocus: (Bool) -> Void
    @State var transition: AnyTransition = .opacity.animation(.default)

    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 {
                                transition = .opacity.animation(.default)
                                withAnimation {
                                    clearSearchField()
                                }

                            } label: {
                                Text("X")
                            }
                            .transition(
                                .asymmetric(
                                    insertion: .opacity.animation(.default),
                                    removal: transition
                                )
                            )
                        }
                    }
                }
                .padding(16)
            }
            .cornerRadius(8)

            if isFocus {
                Button(
                    action: {
                        transition = .move(edge: .trailing).combined(with: .opacity)
                        hideKeyboard()
                        clearSearchField()
                        setFocus(false)

                    },
                    label: {
                        Text("Cancel")
                            .foregroundColor(.white)
                    }
                )
                .transition(.move(edge: .trailing).combined(with: .opacity).animation(.default))
            }
        }
        .frame(height: 48)
        .foregroundColor(searchField.isEmpty ? .grey: .white)
        .padding(16)
        .animation(.default, value: [isFocus])
    }
}

这个是可能的吗?

感谢任何人的帮助!

推荐答案

根据我的观察,如果不更改其身份,就无法更改视图的过渡.一旦视图与过渡一起出现,您就不能告诉它随着另一个过渡而消失.

因此,解决这个问题的一种方法是有two个X按钮,一个有.opacity转场,另一个有.move转场.使用@State来决定显示哪个按钮:

示例:

@State var showButtons = false
@State var shouldMove = false

var body: some View {
    VStack {
        // imagine this is your text field
        Rectangle().frame(width: 100, height: 100).onTapGesture {
            withAnimation {
                showButtons = true
            }
        }
        Spacer()
        if showButtons {
            // make buttons with different transitions
            // if shouldMove, show the button with the move transition
            // otherwise show the button with the opacity transition
            if shouldMove {
                makeButton(transition: .asymmetric(insertion: .opacity, removal: .move(edge: .trailing)))
            } else {
                makeButton(transition: .opacity)
            }
            
            Button("Cancel") {
                shouldMove = true
                withAnimation {
                    showButtons.toggle()
                }
            }
        }
    }.frame(height: 300)
}

@ViewBuilder func makeButton(transition: AnyTransition) -> some View {
    Button("X") {
        shouldMove = false
        withAnimation {
            showButtons.toggle()
        }
    }.transition(transition)
}

另一种方法是,每当您想要更改过渡时,就给X按钮一个新的id,从而创建一个"新"视图.

@State var showButtons = false
@State var transition: AnyTransition = .opacity
@State var buttonId = UUID()

var body: some View {
    VStack {
        Rectangle().frame(width: 100, height: 100).onTapGesture {
            withAnimation {
                showButtons = true
            }
        }
        Spacer()
        if showButtons {
            Button("X") {
                transition = .opacity
                buttonId = UUID() // new id!
                withAnimation {
                    showButtons.toggle()
                }
            }
            .transition(transition)
            .id(buttonId)
            
            Button("Cancel") {
                transition = .asymmetric(insertion: .opacity, removal: .move(edge: .trailing))
                buttonId = UUID() // new id!
                withAnimation {
                    showButtons.toggle()
                }
            }
        }
    }.frame(height: 300)
}

Swift相关问答推荐

Swift Tree实现中的弱var

防止NavigationLink自行返回导航视图

Form中的Divider在macOS上并不完全扩展

纹理资源加载问题(图像解码失败)

map 视图上的SwiftUI渐变折线

当计数大于索引时,索引超出范围崩溃

从SwiftUI使用UIPageView时,同一页面连续显示两次的问题

快速并行读取进程 standardOutput 和 standardError 而不会阻塞

使用序列初始化字符串的时间复杂度是多少?

Swift String.firstIndex(of: "\n") 返回 nil,即使字符串有 \n

允许为 self 分配新的 struct 值的理由是什么?

如何将变量添加到不属于可解码部分的 struct ?

如何在 SceneKit 上制作毛玻璃效果

快速更改tableView中的数据

创建 ViewModel 时 iOS 模拟器上的黑屏

P384 公钥获取IncorrectParameterSize

有什么方法可以快速为泛型参数分配默认值?

找不到接受提供的参数的/的重载

无法使用锚激活约束

swift中相同的数据类型多变量声明