如何在UITextView中添加占位符,类似于你可以为UITextField设置的占位符,在Swift中?
当前回答
斯威夫特5.2
独立的类
如果你想要一个类,你可以在任何地方使用,因为它是自包含的
import UIKit
class PlaceHolderTextView:UITextView, UITextViewDelegate{
var placeholderText = "placeholderText"
override func willMove(toSuperview newSuperview: UIView?) {
textColor = .lightText
delegate = self
}
func textViewDidBeginEditing(_ textView: UITextView) {
if textView.text == placeholderText{
placeholderText = textView.text
textView.text = ""
textView.textColor = .darkText
}
}
func textViewDidEndEditing(_ textView: UITextView) {
if textView.text == ""{
textView.text = placeholderText
textColor = .lightText
}
}
}
这里的关键是willMove(toSuperView:)函数,因为它允许你在添加到另一个视图的层次结构之前设置视图(类似于ViewControllers中的viewDidLoad/viewWillAppear)
其他回答
import UIKit
import RxSwift
@IBDesignable class TextViewWithPlaceholder: UITextView {
//MARK: - Propertise
@IBInspectable var placeholderText: String = ""
let placeholderLabel = LocalizedUILabel()
private let hidePlaceholderObserver = PublishSubject<Bool>()
let disposeBag = DisposeBag()
//MARK: - Did Move To Window
override func didMoveToWindow() {
super.didMoveToWindow()
observeOnTextViewEditing()
configurePlaceholder()
}
//MARK: - Observe On Text View Editing
private func observeOnTextViewEditing() {
rx.text.subscribe(onNext: { [weak self] selectedText in
guard let self = self else { return }
self.hidePlaceholderObserver.onNext((selectedText?.isEmpty ?? true) ? false : true)
}).disposed(by: disposeBag)
}
//MARK: - Observe On Show Hide Placeholder
private func configurePlaceholder() {
hidePlaceholderObserver
.bind(to: placeholderLabel.rx.isHidden)
.disposed(by: disposeBag)
placeholderLabel.text = placeholderText
placeholderLabel.font = UIFont(name: "Poppins-Semibold", size: 16) ?? UIFont()
placeholderLabel.textColor = .lightGray
placeholderLabel.sizeToFit()
placeholderLabel.frame.origin = CGPoint(x: 8, y: 8)
addSubview(placeholderLabel)
}
}
有我的简单版本的UITextView与占位符。主要思想是:
隐藏占位符,如果用户开始编辑和占位符是可见的 如果用户结束编辑并且文本视图的文本为空,则显示占位符。
class PlaceholderTextView: UITextView {
var placeholder = "" {
didSet {
if isPlaceholderVisible {
showPlaceholder()
}
}
}
var isPlaceholderVisible = true {
didSet {
isPlaceholderVisible ? showPlaceholder() : hidePlaceholder()
}
}
init() {
super.init(frame: .zero, textContainer: nil)
delegate = self
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func showPlaceholder() {
text = placeholder
// Set other things like color of text for placeholder, ...
}
private func hidePlaceholder() {
text = ""
// Set other things like color of text for normal input, ...
}
}
extension PlaceholderTextView: UITextViewDelegate {
func textViewDidBeginEditing(_ textView: UITextView) {
if isPlaceholderVisible {
isPlaceholderVisible = false
}
}
func textViewDidEndEditing(_ textView: UITextView) {
if text.isEmpty {
isPlaceholderVisible = true
}
}
}
与这篇文章中几乎所有的答案相反,UITextView确实有一个占位符属性。由于我无法理解的原因,它只在IB中出现,例如:
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="placeholder" value="My Placeholder"/>
</userDefinedRuntimeAttributes>
因此,如果你正在使用故事板,一个静态占位符就足够了,只需在检查器上设置属性。
你也可以像这样在代码中设置这个属性:
textView.setValue("My Placeholder", forKeyPath: "placeholder")
它的多云天气,这是通过私有API访问,因为属性是暴露的。
我还没有尝试过用这种方法提交。但我将很快以这种方式提交,并将相应地更新这个答案。
更新:
我已经在多个版本中发布了这个代码,苹果没有任何问题。
更新: 这将只适用于Xcode pre 11.2
在视图加载中设置值
txtVw!.autocorrectionType = UITextAutocorrectionType.No
txtVw!.text = "Write your Placeholder"
txtVw!.textColor = UIColor.lightGrayColor()
func textViewDidBeginEditing(textView: UITextView) {
if (txtVw?.text == "Write your Placeholder")
{
txtVw!.text = nil
txtVw!.textColor = UIColor.blackColor()
}
}
func textViewDidEndEditing(textView: UITextView) {
if txtVw!.text.isEmpty
{
txtVw!.text = "Write your Placeholder"
txtVw!.textColor = UIColor.lightGrayColor()
}
textView.resignFirstResponder()
}
这里有一些东西可以被放到UIStackView中,它会使用内部高度约束来调整自己的大小。可能需要调整以适应特定的需求。
import UIKit
public protocol PlaceholderTextViewDelegate: class {
func placeholderTextViewTextChanged(_ textView: PlaceholderTextView, text: String)
}
public class PlaceholderTextView: UIView {
public weak var delegate: PlaceholderTextViewDelegate?
private var heightConstraint: NSLayoutConstraint?
public override init(frame: CGRect) {
self.allowsNewLines = true
super.init(frame: frame)
self.heightConstraint = self.heightAnchor.constraint(equalToConstant: 0)
self.heightConstraint?.isActive = true
self.addSubview(self.placeholderTextView)
self.addSubview(self.textView)
self.pinToCorners(self.placeholderTextView)
self.pinToCorners(self.textView)
self.updateHeight()
}
public override func didMoveToSuperview() {
super.didMoveToSuperview()
self.updateHeight()
}
private func pinToCorners(_ view: UIView) {
NSLayoutConstraint.activate([
view.leadingAnchor.constraint(equalTo: self.leadingAnchor),
view.trailingAnchor.constraint(equalTo: self.trailingAnchor),
view.topAnchor.constraint(equalTo: self.topAnchor),
view.bottomAnchor.constraint(equalTo: self.bottomAnchor)
])
}
// Accessors
public var text: String? {
didSet {
self.textView.text = text
self.textViewDidChange(self.textView)
self.updateHeight()
}
}
public var textColor: UIColor? {
didSet {
self.textView.textColor = textColor
self.updateHeight()
}
}
public var font: UIFont? {
didSet {
self.textView.font = font
self.placeholderTextView.font = font
self.updateHeight()
}
}
public override var tintColor: UIColor? {
didSet {
self.textView.tintColor = tintColor
self.placeholderTextView.tintColor = tintColor
}
}
public var placeholderText: String? {
didSet {
self.placeholderTextView.text = placeholderText
self.updateHeight()
}
}
public var placeholderTextColor: UIColor? {
didSet {
self.placeholderTextView.textColor = placeholderTextColor
self.updateHeight()
}
}
public var allowsNewLines: Bool
public required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private lazy var textView: UITextView = self.newTextView()
private lazy var placeholderTextView: UITextView = self.newTextView()
private func newTextView() -> UITextView {
let textView = UITextView()
textView.translatesAutoresizingMaskIntoConstraints = false
textView.isScrollEnabled = false
textView.delegate = self
textView.backgroundColor = .clear
return textView
}
private func updateHeight() {
let maxSize = CGSize(width: self.frame.size.width, height: .greatestFiniteMagnitude)
let textViewSize = self.textView.sizeThatFits(maxSize)
let placeholderSize = self.placeholderTextView.sizeThatFits(maxSize)
let maxHeight = ceil(CGFloat.maximum(textViewSize.height, placeholderSize.height))
self.heightConstraint?.constant = maxHeight
}
}
extension PlaceholderTextView: UITextViewDelegate {
public func textViewDidChangeSelection(_: UITextView) {
self.placeholderTextView.alpha = self.textView.text.isEmpty ? 1 : 0
self.updateHeight()
}
public func textViewDidChange(_: UITextView) {
self.delegate?.placeholderTextViewTextChanged(self, text: self.textView.text)
}
public func textView(_: UITextView, shouldChangeTextIn _: NSRange,
replacementText text: String) -> Bool {
let containsNewLines = text.rangeOfCharacter(from: .newlines)?.isEmpty == .some(false)
guard !containsNewLines || self.allowsNewLines else { return false }
return true
}
}
推荐文章
- 我应该如何从字符串中删除所有的前导空格?- - - - - -斯威夫特
- 如何使用Xcode创建。ipa文件?
- 动态改变UILabel的字体大小
- 在iPhone上确定用户是否启用了推送通知
- 是否有可能禁用浮动头在UITableView与UITableViewStylePlain?
- Swift:理解// MARK
- 错误ITMS-9000:“冗余二进制文件上传。火车1.0版本已经有一个二进制版本上传。
- Swift -转换为绝对值
- Swift编译器错误:“框架模块内的非模块化头”
- 从父iOS访问容器视图控制器
- 自定义dealloc和ARC (Objective-C)
- 调整UITableView的大小以适应内容
- 在代码中为UIButton设置一个图像
- NSRange从Swift Range?
- 我可以使用范围操作符与if语句在Swift?