如何在UITextView中添加占位符,类似于你可以为UITextField设置的占位符,在Swift中?
当前回答
协议版本的clearlight的答案上面,因为协议是伟大的。随便放哪都行。扣篮!
extension UITextViewPlaceholder where Self: UIViewController {
// Use this in ViewController's ViewDidLoad method.
func addPlaceholder(text: String, toTextView: UITextView, font: UIFont? = nil) {
placeholderLabel = UILabel()
placeholderLabel.text = text
placeholderLabel.font = font ?? UIFont.italicSystemFont(ofSize: (toTextView.font?.pointSize)!)
placeholderLabel.sizeToFit()
toTextView.addSubview(placeholderLabel)
placeholderLabel.frame.origin = CGPoint(x: 5, y: (toTextView.font?.pointSize)! / 2)
placeholderLabel.textColor = UIColor.lightGray
placeholderLabel.isHidden = !toTextView.text.isEmpty
}
// Use this function in the ViewController's textViewDidChange delegate method.
func textViewWithPlaceholderDidChange(_ textView: UITextView) {
placeholderLabel.isHidden = !textView.text.isEmpty
}
}
其他回答
不,没有任何占位符可用的textview。你必须把标签上面,当用户进入textview,然后隐藏它或设置默认值时,用户输入删除所有值。
我不得不调度队列,让我的占位符文本重新出现,一旦编辑完成。
func textViewDidBeginEditing(_ textView: UITextView) {
if textView.text == "Description" {
textView.text = nil
}
}
func textViewDidEndEditing(_ textView: UITextView) {
if textView.text.isEmpty {
DispatchQueue.main.async {
textView.text = "Description"
}
}
}
我很惊讶没有人提到NSTextStorageDelegate。UITextViewDelegate的方法只能由用户交互触发,而不是以编程方式触发。例如,当你以编程方式设置一个文本视图的文本属性时,你必须自己设置占位符的可见性,因为委派方法不会被调用。
然而,使用NSTextStorageDelegate的textStorage(_:didProcessEditing:range:changeInLength:)方法,你会收到任何文本更改的通知,即使它是通过编程完成的。就像这样分配它:
textView.textStorage.delegate = self
(在UITextView中,这个委派属性默认为nil,所以它不会影响任何默认行为。)
将它与@clearlight演示的UILabel技术结合起来,可以轻松地将整个UITextView的占位符实现包装成一个扩展。
extension UITextView {
private class PlaceholderLabel: UILabel { }
private var placeholderLabel: PlaceholderLabel {
if let label = subviews.compactMap( { $0 as? PlaceholderLabel }).first {
return label
} else {
let label = PlaceholderLabel(frame: .zero)
label.font = font
addSubview(label)
return label
}
}
@IBInspectable
var placeholder: String {
get {
return subviews.compactMap( { $0 as? PlaceholderLabel }).first?.text ?? ""
}
set {
let placeholderLabel = self.placeholderLabel
placeholderLabel.text = newValue
placeholderLabel.numberOfLines = 0
let width = frame.width - textContainer.lineFragmentPadding * 2
let size = placeholderLabel.sizeThatFits(CGSize(width: width, height: .greatestFiniteMagnitude))
placeholderLabel.frame.size.height = size.height
placeholderLabel.frame.size.width = width
placeholderLabel.frame.origin = CGPoint(x: textContainer.lineFragmentPadding, y: textContainerInset.top)
textStorage.delegate = self
}
}
}
extension UITextView: NSTextStorageDelegate {
public func textStorage(_ textStorage: NSTextStorage, didProcessEditing editedMask: NSTextStorageEditActions, range editedRange: NSRange, changeInLength delta: Int) {
if editedMask.contains(.editedCharacters) {
placeholderLabel.isHidden = !text.isEmpty
}
}
}
注意,使用了一个名为PlaceholderLabel的私有(嵌套)类。它根本没有实现,但它为我们提供了一种识别占位符标签的方法,这比使用tag属性要“快捷”得多。
使用这种方法,你仍然可以将UITextView的委托分配给其他人。
你甚至不需要改变文本视图的类。只要添加扩展,你就可以为项目中的每个UITextView分配一个占位符字符串,甚至在接口生成器中也是如此。
出于清晰的原因,我省略了placeholderColor属性的实现,但是它可以用与placeholder类似的计算变量在多几行中实现。
我们可以很容易地实现textview占位符,如果我们正在使用pod IQKeyboardManagerSwift在我们的项目中,只需遵循4个步骤
我们必须将类IQTextView分配给我们的TextView类。 我们必须在Controller页面中导入IQKeyboardManagerSwift 最后但并非最不重要的是,在控制器页面的textView的出口//如果你想:) 通过storyboard inspectable给textView一些占位符文本
这就是我所做的。倾向于代码清晰和简单。我需要添加一个textView,将获得一些额外的笔记在我的应用程序。这额外的笔记可以创建或保存后修改。见下文。HTH。:)
class NotesTextView: UITextView {
var placeholder = "" {
didSet {
showPlaceholder()
}
}
// if the text is the placeholder, then assign a color fitting for a
// placeholder text, else, assign it your color of choice.
override var text: String! {
didSet {
textColor = text == placeholder ? .tertiaryLabel : .systemBlue
}
}
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
delegate = self
//config your font and translateAutoResizingMaskIntoConstraints here
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func showPlaceholder() {
text = placeholder
}
private func hidePlaceholder() {
text = ""
}
}
extension NotesTextView: UITextViewDelegate {
func textViewDidBeginEditing(_ textView: UITextView) {
if text == placeholder {
hidePlaceholder()
}
}
func textViewDidEndEditing(_ textView: UITextView) {
if text.isEmpty {
showPlaceholder()
}
}
}
推荐文章
- 我如何在我的iOS应用程序中每n分钟得到一个后台位置更新?
- 如何使用iOS创建GUID/UUID
- 禁用所呈现视图控制器的交互式撤销
- 在Swift中转换字符串为日期
- 点击按钮时如何打开手机设置?
- 如何使用UIVisualEffectView来模糊图像?
- 如何修复UITableView分隔符在iOS 7?
- 故事板中的自定义单元格行高设置没有响应
- 在Swift中使用自定义消息抛出错误/异常的最简单方法?
- 编译器错误:带有Objective-C选择器的方法与前面带有相同Objective-C选择器的声明冲突
- 如何在Swift中获得唯一的设备ID ?
- 如何在Swift中获得枚举值的名称?
- 复制文本到剪贴板与iOS
- 在Swift中根据字符串计算UILabel的大小
- 如何调用手势点击在UIView编程在迅速