调整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的占位文字的颜色,和光标的颜色
如何更改 QML TextField 中的 placeholderText 颜色