调整TextField占位文字颜色

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了调整TextField占位文字颜色相关的知识,希望对你有一定的参考价值。

参考技术A 需求:
1.通过不同状态调整TextField占位文字颜色
2.编辑状态下为 WhiteColor ;默认 LightGrayColor
文字描述较为抽象,直接看效果图:

实现思路:
设置 TextField 代理,实现 <UITextFieldDelegate> 协议方法,在开始编辑时,通过富文本直接对 TextField 的 attributedPlaceholder 赋值,同理,在编辑结束后同样操作

当然,在为 TextField 设置占位文字时,也需要通过富文本对 attributedPlaceholder 属性进行赋值

实现思路:
实现代理的方式有点大材小用了,其实还可以 addTarget 的方式
分别在 UIControlEventEditingDidBegin 和 UIControlEventEditingDidEnd 中做上面的操作

实现思路:
通知,在自定义 TextField 中,分别监听 UITextFieldTextDidBeginEditingNotification 和 UITextFieldTextDidEndEditingNotification ,在接收到对应通知后,在方法中执行上面的操作

实现思路:
1.自定义 TextField ;
2.通过 RunTime 获取到私有属性 placeholderLabel 占位文本框;
3.重写 layoutSubviews 方法,根据当前 TextField 状态通过 KVC 设置占位文本框字体颜色

实现思路:
重写 becomeFirstResponder 和 resignFirstResponder 方法,分别对当前 TextField 处理

但需要注意一点,因为 TextField 在实例化时,默认并未设置 placeholder 属性, TextField 内部子控件 placeholderLabel 采用一种懒加载机制,此时相当于为 nil ,如果在自定义 TextField 的 init 方法中直接通过 KVC 方式设置默认状态颜色是无意的,必须要保证在 placeholderLabel 存在的前提下设置才会有意义,而设置延迟的方式并不能完美解决这个问题,文字描述可能比较抽空,直接看图便能更容易的发现这个问题:

虽然 beignEdit 和 endEdit 下的状态正常,但是刚刚展示视图时, TextField 的占位文字还是黑色,暂时想到的方法就是在 layoutSubViews 方法中(方式四中),将未编辑状态下设置成灰色

是否可以在 SwiftUI 中为 TextField 添加字距调整?

【中文标题】是否可以在 SwiftUI 中为 TextField 添加字距调整?【英文标题】:Is it possible to add kerning to a TextField in SwiftUI? 【发布时间】:2019-11-05 15:13:49 【问题描述】:

要匹配样式指南,我必须向文本字段添加字距调整,包括占位符和值本身。

借助 UIKit,我能够做到这一点:

    class MyTextField: UITextField 
    override func awakeFromNib() 
        super.awakeFromNib()

        // ...

        self.attributedPlaceholder = NSAttributedString(string: self.placeholder ?? "", attributes: [
            //...
            NSAttributedString.Key.kern: 0.3
        ])

        self.attributedText = NSAttributedString(string: "", attributes: [
            // ...
            NSAttributedString.Key.kern: 0.3
        ])
    

在 SwiftUI 中,我发现我可以对 Text 元素应用字距调整效果,如下所示:

    Text("My label with kerning")
       .kerning(0.7)

不幸的是,我找不到将字距调整样式应用于 TextField 的值或占位符的方法。关于这个有什么想法吗?提前致谢

【问题讨论】:

如果您需要 UIKit 视图,请使用 UIViewRepresentable。 @matt 我已经在 SwiftUI 中实现了视图,并希望坚持下去。在 SwiftUI 视图inside 中只使用唯一的 UITextField 子类是不可能的,是吗? 是的;这正是你可以做的,使用 UIViewRepresentable。 SwiftUI 视图可以存在于 UIViews 中,而 UIViews 可以存在于 SwiftUI 视图中。 【参考方案1】:

HackingwithSwift 上有一个简单的教程,展示了如何实现 UITextView。它可以很容易地适应 UITextField。

这是一个简单的示例,展示如何为您使用UIViewRepresentable UITextField。在文本和占位符上设置字距。

struct ContentView: View 

    @State var text = ""

    var body: some View 
        MyTextField(text: $text, placeholder: "Placeholder")
    



struct MyTextField: UIViewRepresentable 
    @Binding var text: String
    var placeholder: String

    func makeUIView(context: Context) -> UITextField 
        return UITextField()
    

    func updateUIView(_ uiView: UITextField, context: Context) 
        uiView.attributedPlaceholder = NSAttributedString(string: self.placeholder, attributes: [
            NSAttributedString.Key.kern: 0.3
        ])
        uiView.attributedText = NSAttributedString(string: self.text, attributes: [
            NSAttributedString.Key.kern: 0.3
        ])
    


更新

以上方法不适用于在属性文本上设置字距。借鉴 Costantino Pistagna 在他的medium article 中所做的出色工作,我们需要做更多的工作。

首先,我们需要创建一个 UITextField 的包装版本,它允许我们访问委托方法。

class WrappableTextField: UITextField, UITextFieldDelegate 
    var textFieldChangedHandler: ((String)->Void)?
    var onCommitHandler: (()->Void)?

    func textFieldShouldReturn(_ textField: UITextField) -> Bool 
        if let nextField = textField.superview?.superview?.viewWithTag(textField.tag + 1) as? UITextField 
            nextField.becomeFirstResponder()
         else 
            textField.resignFirstResponder()
        
        return false
    

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool 
        if let currentValue = textField.text as NSString? 
            let proposedValue = currentValue.replacingCharacters(in: range, with: string)
            print(proposedValue)
            self.attributedText = NSAttributedString(string: currentValue as String, attributes: [
                NSAttributedString.Key.kern: 10
            ])
            textFieldChangedHandler?(proposedValue as String)
        
        return true
    

    func textFieldDidEndEditing(_ textField: UITextField) 
        onCommitHandler?()
    

由于每次文本更改时都会调用shouldChangeCharactersIn 委托方法,我们应该使用它来更新attributedText 值。我尝试先使用proposedVale,但它会使字符加倍,如果我们使用currentValue,它会按预期工作

现在我们可以在UIViewRepresentable 中使用WrappedTextField

struct SATextField: UIViewRepresentable 
    private let tmpView = WrappableTextField()

    //var exposed to SwiftUI object init
    var tag:Int = 0
    var placeholder:String?
    var changeHandler:((String)->Void)?
    var onCommitHandler:(()->Void)?

    func makeUIView(context: UIViewRepresentableContext<SATextField>) -> WrappableTextField 
        tmpView.tag = tag
        tmpView.delegate = tmpView
        tmpView.placeholder = placeholder
        tmpView.attributedPlaceholder = NSAttributedString(string: self.placeholder ?? "", attributes: [
            NSAttributedString.Key.kern: 10
        ])
        tmpView.onCommitHandler = onCommitHandler
        tmpView.textFieldChangedHandler = changeHandler
        return tmpView
    

    func updateUIView(_ uiView: WrappableTextField, context: UIViewRepresentableContext<SATextField>) 
        uiView.setContentHuggingPriority(.defaultHigh, for: .vertical)
        uiView.setContentHuggingPriority(.defaultLow, for: .horizontal)
    

我们在makeUIView 中为占位符设置了属性文本。占位符文本没有被更新,所以我们不需要担心改变它。

这是我们如何使用它的:

struct ContentView: View 

    @State var text = ""

    var body: some View 
        SATextField(tag: 0, placeholder: "Placeholder", changeHandler:  (newText) in
            self.text = newText
        ) 
            // do something when the editing of this textfield ends
        
    

【讨论】:

嗯……实际上,它工作得很好,但我无法让内部填充工作……This answer 过去对我来说工作得很好:( :) 我很高兴字距调整现在为您工作。如果您有一个与字距调整无关的问题,那么我建议您将其写成一个新问题,以便您可以清楚地表达您需要做的所有事情,因为 SO 上的 cmets 并不允许进行详细的讨论。一方面,这里的代码格式不好;其次,你被限制在 600 个字符以内,所以很难充分表达自己。

以上是关于调整TextField占位文字颜色的主要内容,如果未能解决你的问题,请参考以下文章

iOS开发中设置UITextField的占位文字的颜色,和光标的颜色

文本编辑框光标颜色和占位文字颜色自定义

在webkit中调整中文

如何更改 QML TextField 中的 placeholderText 颜色

如何访问 XLFormRowDescriptor 的占位符文本颜色

百思不得姐第4天:文本框占位文字颜色