我有一个带有发送按钮的textfield,它是一个systemImage箭头。我希望图像的前景色根据textField是否为空而改变。(即按钮为灰色,如果文本字段为空,则禁用该按钮。如果文本字段文本的计数> 1,则为蓝色)。
我有一个不完善的解决方法:
if chatMessageIsValid {
Spacer()
HStack {
TextField($chatMessage, placeholder: Text("Reply"))
.padding(.leading, 10)
.textFieldStyle(.roundedBorder)
Button(action: sendMessage) {
Image(systemName: "arrow.up.circle")
.foregroundColor(Color.blue)
.padding(.trailing, 10)
}.disabled(!chatMessageIsValid)
}
} else {
Spacer()
HStack {
TextField($chatMessage, placeholder: Text("Reply"))
.padding(.leading, 10)
.textFieldStyle(.roundedBorder)
Button(action: sendMessage) {
Image(systemName: "arrow.up.circle")
.foregroundColor(Color.gray)
.padding(.trailing, 10)
}.disabled(!chatMessageIsValid)
}
}
Run Code Online (Sandbox Code Playgroud)
这几乎可以工作,并且如果文本的长度> 1,它的确会更改图像的颜色。但是,由于状态的变化,您在键入一个字符后将无法再编辑文本字段,因此您需要再次选择文本字段才能继续输入。是否有更好的方法使用.disabled修饰符来做到这一点?
rob*_*off 12
我猜你想要这个:
您可以为按钮颜色添加一个计算属性,然后将该属性传递给按钮的foregroundColor修饰符。您还可以在其子视图的padding周围使用单个修饰符,HStack而不是单独padding的。
struct ContentView : View {
@State var chatMessage: String = ""
var body: some View {
HStack {
TextField($chatMessage, placeholder: Text("Reply"))
.textFieldStyle(.roundedBorder)
Button(action: sendMessage) {
Image(systemName: "arrow.up.circle")
.foregroundColor(buttonColor)
}
.disabled(!chatMessageIsValid)
}
.padding([.leading, .trailing], 10)
}
var chatMessageIsValid: Bool {
return !chatMessage.isEmpty
}
var buttonColor: Color {
return chatMessageIsValid ? .accentColor : .gray
}
func sendMessage() {
chatMessage = ""
}
}
Run Code Online (Sandbox Code Playgroud)
但是,您不应该foregroundColor在这里完全使用修饰符。您应该使用accentColor修饰符。使用accentColor有两个好处:
该Image会自动使用环境的accentColor的时候Button被激活,灰色当Button被禁用。您根本不需要计算颜色。
您可以accentColor在View层次结构中将环境设置为较高,它将滴流到所有后代。这样可以轻松为整个界面设置统一的强调色。
在以下示例中,我将accentColor修饰符放在上HStack。在真实的应用程序中,您可能会在整个应用程序的根视图上进行设置:
struct ContentView : View {
@State var chatMessage: String = ""
var body: some View {
HStack {
TextField($chatMessage, placeholder: Text("Reply"))
.textFieldStyle(.roundedBorder)
Button(action: sendMessage) {
Image(systemName: "arrow.up.circle")
}
.disabled(!chatMessageIsValid)
}
.padding([.leading, .trailing], 10)
.accentColor(.orange)
}
var chatMessageIsValid: Bool {
return !chatMessage.isEmpty
}
func sendMessage() {
chatMessage = ""
}
}
Run Code Online (Sandbox Code Playgroud)
同样,Matt将发送按钮提取为自己的类型的想法可能很聪明。它使用户可以轻松地完成一些精美的事情,例如在用户单击时对其进行动画处理:
这是代码:
struct ContentView : View {
@State var chatMessage: String = ""
var body: some View {
HStack {
TextField($chatMessage, placeholder: Text("Reply"))
.textFieldStyle(.roundedBorder)
SendButton(action: sendMessage, isDisabled: chatMessage.isEmpty)
}
.padding([.leading, .trailing], 10)
.accentColor(.orange)
}
func sendMessage() {
chatMessage = ""
}
}
struct SendButton: View {
let action: () -> ()
let isDisabled: Bool
var body: some View {
Button(action: {
withAnimation {
self.action()
self.clickCount += 1
}
}) {
Image(systemName: "arrow.up.circle")
.rotationEffect(.radians(2 * Double.pi * clickCount))
.animation(.basic(curve: .easeOut))
}
.disabled(isDisabled)
}
@State private var clickCount: Double = 0
}
Run Code Online (Sandbox Code Playgroud)
使用这些不同的解决方案,您可以使用\.isEnabled环境属性而不是创建自定义按钮样式或自己传递禁用的布尔值。
@Environment(\.isEnabled) private var isEnabled
Run Code Online (Sandbox Code Playgroud)
尝试这个
Spacer()
HStack {
TextField($chatMessage, placeholder: Text("Reply"))
.padding(.leading, 10)
.textFieldStyle(.roundedBorder)
Button(action: sendMessage) {
Image(systemName: "arrow.up.circle")
.foregroundColor(chatMessageIsValid ? Color.blue : Color.gray)
.padding(.trailing, 10)
}.disabled(!chatMessageIsValid)
}
Run Code Online (Sandbox Code Playgroud)
我想,TextField失去焦点的原因是在您的代码中,整个视图层次结构根据chatMessageIsValid. SwiftUI 不理解then块中的视图层次结构与块中的视图层次结构几乎相同else,因此它完全重建它。
在这个编辑过的代码中,它应该看到唯一改变的是foregroundColor图像的 和disabled按钮的状态,TextField保持不变。我相信,Apple 在其中一个 WWDC 视频中就有类似的例子。
如果您想在禁用(或任何其他)状态下进一步自定义按钮,您可以将变量添加到您的自定义 ButtonStyle 结构中。
斯威夫特 5.1
struct CustomButtonStyle: ButtonStyle {
var disabled = false
func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.background(disabled ? .red : .blue)
}
}
// SwiftUI
@State var isDisabled = true
var body: some View {
Button().buttonStyle(CustomButtonStyle(disabled: self.isDisabled))
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1789 次 |
| 最近记录: |