如何在UITextView中添加占位符,类似于你可以为UITextField设置的占位符,在Swift中?
当前回答
斯威夫特
这是一个Swiftui TextView使用UIVIewRepresentable,具有占位符功能和边界颜色
struct TextView: UIViewRepresentable {
@Binding var text: String
var placeholderText: String
var textStyle: UIFont.TextStyle
func makeUIView(context: Context) -> UITextView {
let textView = UITextView()
textView.font = UIFont.preferredFont(forTextStyle: textStyle)
textView.autocapitalizationType = .sentences
textView.isSelectable = true
textView.isUserInteractionEnabled = true
textView.delegate = context.coordinator
textView.layer.borderWidth = 0.6
textView.layer.borderColor = UIColor.lightGray.cgColor
textView.layer.cornerRadius = 10
textView.text = placeholderText
textView.textColor = UIColor.lightGray
return textView
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.text = text
uiView.font = UIFont.preferredFont(forTextStyle: textStyle)
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, UITextViewDelegate {
var parent: TextView
init(_ parent: TextView) {
self.parent = parent
}
func textViewDidChange(_ textView: UITextView) {
self.parent.text = textView.text
}
func textViewDidBeginEditing(_ textView: UITextView) {
if textView.textColor == UIColor.lightGray {
textView.text = nil
textView.textColor = UIColor.black
}
}
func textViewDidEndEditing(_ textView: UITextView) {
if textView.text.isEmpty {
textView.text = self.parent.placeholderText
textView.textColor = UIColor.lightGray
}
}
}
}
然后在你的视图中你可以这样使用它
TextView(text: self.$viewModel.addPostCommentText, placeholderText: "Share your story about this cash", textStyle: .body)
.padding()
.frame(height: 150)
其他回答
Swift 4更新
UITextView本身没有占位符属性,所以你必须用UITextViewDelegate方法来创建和操作一个。我建议使用下面的解决方案#1或#2,这取决于所需的行为。
注意:对于任何一种解决方案,都需要将UITextViewDelegate添加到类中,并设置textView.delegate = self来使用文本视图的委托方法。
解决方案#1 -如果你想让占位符在用户选择文本视图时立即消失:
首先将UITextView设置为包含占位符文本,并将其设置为浅灰色,以模拟UITextField的占位符文本的外观。要么在viewDidLoad中这样做,要么在文本视图创建时这样做。
textView.text = "Placeholder"
textView.textColor = UIColor.lightGray
然后,当用户开始编辑文本视图时,如果文本视图包含一个占位符(即,如果其文本颜色是浅灰色),则清除占位符文本,并将文本颜色设置为黑色,以便容纳用户的输入。
func textViewDidBeginEditing(_ textView: UITextView) {
if textView.textColor == UIColor.lightGray {
textView.text = nil
textView.textColor = UIColor.black
}
}
然后,当用户完成编辑文本视图并将其作为第一响应器时,如果文本视图为空,则通过重新添加占位符文本并将其颜色设置为浅灰色来重置其占位符。
func textViewDidEndEditing(_ textView: UITextView) {
if textView.text.isEmpty {
textView.text = "Placeholder"
textView.textColor = UIColor.lightGray
}
}
解决方案#2 -如果你想要占位符显示文本视图是空的,即使文本视图被选中:
首先在viewDidLoad中设置占位符:
textView.text = "Placeholder"
textView.textColor = UIColor.lightGray
textView.becomeFirstResponder()
textView.selectedTextRange = textView.textRange(from: textView.beginningOfDocument, to: textView.beginningOfDocument)
(注意:由于OP希望在视图加载时立即选择文本视图,所以我将文本视图选择合并到上面的代码中。如果这不是你想要的行为,你不希望在视图加载时选择文本视图,从上面的代码块中删除最后两行。)
然后使用shouldChangeTextInRange UITextViewDelegate方法,如下所示:
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
// Combine the textView text and the replacement text to
// create the updated text string
let currentText:String = textView.text
let updatedText = (currentText as NSString).replacingCharacters(in: range, with: text)
// If updated text view will be empty, add the placeholder
// and set the cursor to the beginning of the text view
if updatedText.isEmpty {
textView.text = "Placeholder"
textView.textColor = UIColor.lightGray
textView.selectedTextRange = textView.textRange(from: textView.beginningOfDocument, to: textView.beginningOfDocument)
}
// Else if the text view's placeholder is showing and the
// length of the replacement string is greater than 0, set
// the text color to black then set its text to the
// replacement string
else if textView.textColor == UIColor.lightGray && !text.isEmpty {
textView.textColor = UIColor.black
textView.text = text
}
// For every other case, the text should change with the usual
// behavior...
else {
return true
}
// ...otherwise return false since the updates have already
// been made
return false
}
也实现textViewDidChangeSelection,以防止用户改变光标的位置,而占位符是可见的。(注意:textViewDidChangeSelection在视图加载之前被调用,所以如果窗口是可见的,只检查文本视图的颜色):
func textViewDidChangeSelection(_ textView: UITextView) {
if self.view.window != nil {
if textView.textColor == UIColor.lightGray {
textView.selectedTextRange = textView.textRange(from: textView.beginningOfDocument, to: textView.beginningOfDocument)
}
}
}
文本视图委托方法
使用这两个委托方法,并在类中编写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()
}
我知道这是一个老问题,但想分享我认为是一个有用的方式扩展UITextView有placeholderText和placeholderColor字段。基本上你将UITextView转换为UITextField,然后设置attributedPlaceholder字段。PlaceholderText和placeholderColor是IBInspectable字段,所以它们的值可以在IB中设置,并与UITextField占位符功能完全相同。
UITextView+Extend.h
#import <UIKit/UIKit.h>
@interface UITextView (Extend)
@property (nonatomic) IBInspectable NSString *placeholderText;
@property (nonatomic) IBInspectable UIColor *placeholderColor;
@end
UITextView+Extend.m
#import "UITextView+Extend.h"
#import "objc/runtime.h"
@implementation UITextView (Extend)
- (void)setPlaceholderText:(NSString *)placeholderText
{
objc_setAssociatedObject(self, @selector(placeholderText), placeholderText, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[self updatePlaceholderText];
}
- (NSString*)placeholderText
{
return objc_getAssociatedObject(self, @selector(placeholderText));
}
- (void)setPlaceholderColor:(UIColor *)placeholderColor
{
objc_setAssociatedObject(self, @selector(placeholderColor), placeholderColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[self updatePlaceholderText];
}
- (UIColor*)placeholderColor
{
return objc_getAssociatedObject(self, @selector(placeholderColor));
}
- (void)updatePlaceholderText
{
NSString *text = self.placeholderText;
UIColor *color = self.placeholderColor;
if(text && color)
{
UITextField *textField = (UITextField*)self;
textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:text attributes:@{NSForegroundColorAttributeName:color}];
}
}
@end
我不得不调度队列,让我的占位符文本重新出现,一旦编辑完成。
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"
}
}
}
以下是我解决这个问题的方法(Swift 4):
这个想法是做出最简单的解决方案,允许使用不同颜色的占位符,调整占位符大小,不会覆盖委托,同时保持所有UITextView函数正常工作。
import UIKit
class PlaceholderTextView: UITextView {
var placeholderColor: UIColor = .lightGray
var defaultTextColor: UIColor = .black
private var isShowingPlaceholder = false {
didSet {
if isShowingPlaceholder {
text = placeholder
textColor = placeholderColor
} else {
textColor = defaultTextColor
}
}
}
var placeholder: String? {
didSet {
isShowingPlaceholder = !hasText
}
}
@objc private func textViewDidBeginEditing(notification: Notification) {
textColor = defaultTextColor
if isShowingPlaceholder { text = nil }
}
@objc private func textViewDidEndEditing(notification: Notification) {
isShowingPlaceholder = !hasText
}
// MARK: - Construction -
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
private func setup() {
NotificationCenter.default.addObserver(self, selector: #selector(textViewDidBeginEditing(notification:)), name: UITextView.textDidBeginEditingNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(textViewDidEndEditing(notification:)), name: UITextView.textDidEndEditingNotification, object: nil)
}
// MARK: - Destruction -
deinit { NotificationCenter.default.removeObserver(self) }
}
推荐文章
- 如何删除默认的导航栏空间在SwiftUI导航视图
- 如何在iOS中使用Swift编程segue
- Swift -整数转换为小时/分钟/秒
- 如何舍入一个双到最近的Int在迅速?
- 扁平化数组的数组在Swift
- Swift:声明一个空字典
- 在成功提交我的应用程序后,“太多符号文件”
- 从数组中随机选择一个元素
- 首先添加一个UIView,甚至是导航栏
- 我如何改变UIButton标题颜色?
- 在Swift中如何调用GCD主线程上的参数方法?
- NSLayoutConstraints是可动画的吗?
- iOS -构建失败,CocoaPods无法找到头文件
- CFNetwork SSLHandshake iOS 9失败
- swift语言中的结构与类