斯威夫特用户界面。如何更改 TextField 的占位符颜色?

SwiftUI. How to change the placeholder color of the TextField?

我想更改 TextField 的占位符颜色,但找不到相应的方法。

我尝试设置 foregroundColoraccentColor,但它并没有改变占位符颜色。

代码如下:

TextField("Placeholder", $text)
    .foregroundColor(Color.red)
    .accentColor(Color.green)

也许还没有 API?

没有 api(目前)。 但你可以:

使用自定义 placeholder 修饰符将 任何视图 显示为 任何其他视图 的持有者!例如:

TextField("", text: $text)
    .placeholder(when: text.isEmpty) {
        Text("Placeholder recreated").foregroundColor(.gray)
}

这是一个简单的 ZStack,您可以在 View 扩展中使用,例如:

extension View {
    func placeholder<Content: View>(
        when shouldShow: Bool,
        alignment: Alignment = .leading,
        @ViewBuilder placeholder: () -> Content) -> some View {

        ZStack(alignment: alignment) {
            placeholder().opacity(shouldShow ? 1 : 0)
            self
        }
    }
}

现在您可以将 任何 类型的样式应用于占位符,例如带有图像的渐变占位符:

✅ 如果你有兴趣,这里是


简约的艺术

大多数时候您只需要传递一个字符串和一个灰色占位符,例如:

TextField("", text: $text)
    .placeholder("Placeholder", when: text.isEmpty)

你可以为上面的扩展编写一个简单的包装器:

extension View {
    func placeholder(
        _ text: String,
        when shouldShow: Bool,
        alignment: Alignment = .leading) -> some View {
            
        placeholder(when: shouldShow, alignment: alignment) { Text(text).foregroundColor(.gray) }
    }
}

就这样

最终在 ZStack 中嵌入内容的 ViewModifier 更优雅,代码更少:

public struct PlaceholderStyle: ViewModifier {
    var showPlaceHolder: Bool
    var placeholder: String

    public func body(content: Content) -> some View {
        ZStack(alignment: .leading) {
            if showPlaceHolder {
                Text(placeholder)
                .padding(.horizontal, 15)
            }
            content
            .foregroundColor(Color.white)
            .padding(5.0)            
        }
    }
}

用法:

TextField("", text: $data)
.modifier(PlaceholderStyle(showPlaceHolder: data.isEmpty,
                           placeholder: "My Placeholder"))

做了一点修改,我们可以为view创建一个扩展来简化主视图中的修饰符代码,也可以用于TextImage.

struct PlaceHolder<T: View>: ViewModifier {
    var placeHolder: T
    var show: Bool
    func body(content: Content) -> some View {
        ZStack(alignment: .leading) {
            if show { placeHolder }
            content
        }
    }
}

extension View {
    func placeHolder<T:View>(_ holder: T, show: Bool) -> some View {
        self.modifier(PlaceHolder(placeHolder:holder, show: show))
    }
}

TextField 中的用法:

将这行代码 .placeHolder(Text("Your placeholder"), show: text.isEmpty) 添加为 viewModifierTextField

TextField("", text: $text, onEditingChanged: { (changing) in
    print("Changing: \(changing)")
}, onCommit: {
    print("Committed!")
})
    .placeHolder(Text("Your placeholder"), show: text.isEmpty)

图像中的用法:

此外,正如 @EmilioPelaez 所建议的,我修改了代码以支持 ex 的任何视图的占位符。 Image 如下所示。

Image("your_image")
    .placeHolder(Image("placeholder_image"), show: true)

如果您想保留原始的 TextField 并且不介意将 Introspect 添加到您的项目中 (https://github.com/siteline/SwiftUI-Introspect),您可以通过访问 UIKit attributedPlaceholder:

TextField("Email", text: $email)
.introspectTextField { uiTextField in
    uiTextField.attributedPlaceholder = NSAttributedString(string: "placeholder text", 
    attributes: [NSAttributedString.Key.foregroundColor: UIColor.red])
}

您可以尝试根据TextField的内容改变颜色。也许是这样的:

@State var text : String
@State var textFieldColor : Color = .secondary

TextField("Placeholder", text: $text)
   .foregroundColor(textFieldColor)
   .onChange(of: text) { value in
      textFieldColor = value == "" ? .red : .green
   }