如何在UITextView中添加占位符,类似于你可以为UITextField设置的占位符,在Swift中?
当前回答
我喜欢@nerdist的解决方案。在此基础上,我创建了UITextView的扩展:
import Foundation
import UIKit
extension UITextView
{
private func add(_ placeholder: UILabel) {
for view in self.subviews {
if let lbl = view as? UILabel {
if lbl.text == placeholder.text {
lbl.removeFromSuperview()
}
}
}
self.addSubview(placeholder)
}
func addPlaceholder(_ placeholder: UILabel?) {
if let ph = placeholder {
ph.numberOfLines = 0 // support for multiple lines
ph.font = UIFont.italicSystemFont(ofSize: (self.font?.pointSize)!)
ph.sizeToFit()
self.add(ph)
ph.frame.origin = CGPoint(x: 5, y: (self.font?.pointSize)! / 2)
ph.textColor = UIColor(white: 0, alpha: 0.3)
updateVisibility(ph)
}
}
func updateVisibility(_ placeHolder: UILabel?) {
if let ph = placeHolder {
ph.isHidden = !self.text.isEmpty
}
}
}
例如,在ViewController类中,我是这样使用它的:
class MyViewController: UIViewController, UITextViewDelegate {
private var notePlaceholder: UILabel!
@IBOutlet weak var txtNote: UITextView!
...
// UIViewController
override func viewDidLoad() {
notePlaceholder = UILabel()
notePlaceholder.text = "title\nsubtitle\nmore..."
txtNote.addPlaceholder(notePlaceholder)
...
}
// UITextViewDelegate
func textViewDidChange(_ textView: UITextView) {
txtNote.updateVisbility(notePlaceholder)
...
}
UITextview的占位符!
更新:
如果你在代码中改变textview的文本,记得调用updateVisibitly方法来隐藏占位符:
txtNote.text = "something in code"
txtNote.updateVisibility(self.notePlaceholder) // hide placeholder if text is not empty.
为了防止占位符被添加多次,在扩展中添加了一个私有add()函数。
其他回答
这是我准备使用的解决方案,如果您正在处理多个文本视图
func textViewShouldBeginEditing(textView: UITextView) -> Bool {
// Set cursor to the beginning if placeholder is set
if textView.textColor == UIColor.lightGrayColor() {
textView.selectedTextRange = textView.textRangeFromPosition(textView.beginningOfDocument, toPosition: textView.beginningOfDocument)
}
return true
}
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
// Remove placeholder
if textView.textColor == UIColor.lightGrayColor() && text.characters.count > 0 {
textView.text = ""
textView.textColor = UIColor.blackColor()
}
if text == "\n" {
textView.resignFirstResponder()
return false
}
return true
}
func textViewDidChange(textView: UITextView) {
// Set placeholder if text is empty
if textView.text.isEmpty {
textView.text = NSLocalizedString("Hint", comment: "hint")
textView.textColor = UIColor.lightGrayColor()
textView.selectedTextRange = textView.textRangeFromPosition(textView.beginningOfDocument, toPosition: textView.beginningOfDocument)
}
}
func textViewDidChangeSelection(textView: UITextView) {
// Set cursor to the beginning if placeholder is set
let firstPosition = textView.textRangeFromPosition(textView.beginningOfDocument, toPosition: textView.beginningOfDocument)
// Do not change position recursively
if textView.textColor == UIColor.lightGrayColor() && textView.selectedTextRange != firstPosition {
textView.selectedTextRange = firstPosition
}
}
文本视图委托方法
使用这两个委托方法,并在类中编写UITextViewDelegate
func textViewDidBeginEditing(_ textView: UITextView) {
if (commentsTextView.text == "Type Your Comments")
{
commentsTextView.text = nil
commentsTextView.textColor = UIColor.darkGray
}
}
func textViewDidEndEditing(_ textView: UITextView) {
if commentsTextView.text.isEmpty
{
commentsTextView.text = "Type Your Comments"
commentsTextView.textColor = UIColor.darkGray
}
textView.resignFirstResponder()
}
我相信这是一个非常干净的解决方案。它在实际文本视图下面添加了一个虚拟文本视图,并根据实际文本视图中的文本显示或隐藏它:
import Foundation
import UIKit
class TextViewWithPlaceholder: UITextView {
private var placeholderTextView: UITextView = UITextView()
var placeholder: String? {
didSet {
placeholderTextView.text = placeholder
}
}
override var text: String! {
didSet {
placeholderTextView.isHidden = text.isEmpty == false
}
}
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit() {
applyCommonTextViewAttributes(to: self)
configureMainTextView()
addPlaceholderTextView()
NotificationCenter.default.addObserver(self,
selector: #selector(textDidChange),
name: UITextView.textDidChangeNotification,
object: nil)
}
func addPlaceholderTextView() {
applyCommonTextViewAttributes(to: placeholderTextView)
configurePlaceholderTextView()
insertSubview(placeholderTextView, at: 0)
}
private func applyCommonTextViewAttributes(to textView: UITextView) {
textView.translatesAutoresizingMaskIntoConstraints = false
textView.textContainer.lineFragmentPadding = 0
textView.textContainerInset = UIEdgeInsets(top: 10,
left: 10,
bottom: 10,
right: 10)
}
private func configureMainTextView() {
// Do any configuration of the actual text view here
}
private func configurePlaceholderTextView() {
placeholderTextView.text = placeholder
placeholderTextView.font = font
placeholderTextView.textColor = UIColor.lightGray
placeholderTextView.frame = bounds
placeholderTextView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
override func layoutSubviews() {
super.layoutSubviews()
placeholderTextView.frame = bounds
}
@objc func textDidChange() {
placeholderTextView.isHidden = !text.isEmpty
}
}
这就是我所做的。倾向于代码清晰和简单。我需要添加一个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()
}
}
}
可能是UITextView占位符实现的最简单的开箱即用的解决方案,不会遭受:
使用UILabel而不是UITextView,这可能会有不同的表现 切换到和从占位符“UITextView”拷贝,将捕获第一个键入的字符将从主UITextView控件丢失 打乱主UITextView控件的文本内容,将占位符替换为空字符串或第一个键入的字符。边界情况是,如果用户输入占位符文本,一些建议的实现将把它作为一个占位符本身。
斯威夫特5:
import UIKit
import SnapKit
import RxSwift
import RxCocoa
class TextAreaView: UIView {
let textArea = UITextView()
let textAreaPlaceholder = UITextView()
override init(frame: CGRect) {
super.init(frame: frame)
commonSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonSetup()
}
private func commonSetup() {
addSubview(textAreaPlaceholder)
addSubview(textArea)
textArea.isScrollEnabled = false
textArea.delegate = self
textAreaPlaceholder.isScrollEnabled = false
textAreaPlaceholder.textColor = UIColor.lightGray
textArea.snp.makeConstraints { make in
make.top.bottom.leading.trailing.equalToSuperview()
}
textAreaPlaceholder.snp.makeConstraints { make in
make.top.bottom.leading.trailing.equalTo(textArea.snp.top)
}
textAreaPlaceholder.text = "Placeholder"
updatePlaceholder()
}
func updatePlaceholder() {
if textArea.text.count > 0 {
textArea.alpha = 1.0
} else {
textArea.alpha = 0.0
}
}
}
extension TextAreaView: UITextViewDelegate {
func textViewDidChange(_ textView: UITextView) {
updatePlaceholder()
}
}
推荐文章
- 如何删除默认的导航栏空间在SwiftUI导航视图
- 如何在iOS中使用Swift编程segue
- Swift -整数转换为小时/分钟/秒
- 如何舍入一个双到最近的Int在迅速?
- 扁平化数组的数组在Swift
- Swift:声明一个空字典
- 在成功提交我的应用程序后,“太多符号文件”
- 从数组中随机选择一个元素
- 首先添加一个UIView,甚至是导航栏
- 我如何改变UIButton标题颜色?
- 在Swift中如何调用GCD主线程上的参数方法?
- NSLayoutConstraints是可动画的吗?
- iOS -构建失败,CocoaPods无法找到头文件
- CFNetwork SSLHandshake iOS 9失败
- swift语言中的结构与类