我的应用程序使用UITextView。现在我想让UITextView有一个占位符,类似于你可以为UITextField设置的占位符。
如何做到这一点?
我的应用程序使用UITextView。现在我想让UITextView有一个占位符,类似于你可以为UITextField设置的占位符。
如何做到这一点?
当前回答
我建议使用pod 'UITextView+Placeholder'
pod 'UITextView+Placeholder'
在代码中
#import "UITextView+Placeholder.h"
////
UITextView *textView = [[UITextView alloc] init];
textView.placeholder = @"How are you?";
textView.placeholderColor = [UIColor lightGrayColor];
其他回答
这里还有另一种方法,它复制了UITextField占位符的轻微缩进:
将UITextField拖到UITextView的右边,这样它们的左上角就对齐了。将占位符文本添加到文本字段。
在viewDidLoad中添加:
[tView setDelegate:self];
tView.contentInset = UIEdgeInsetsMake(-8,-8,0,0);
tView.backgroundColor = [UIColor clearColor];
然后添加:
- (void)textViewDidChange:(UITextView *)textView {
if (textView.text.length == 0) {
textView.backgroundColor = [UIColor clearColor];
} else {
textView.backgroundColor = [UIColor whiteColor];
}
}
如果有人需要Swift的解决方案:
添加UITextViewDelegate到类中
var placeHolderText = "Placeholder Text..."
override func viewDidLoad() {
super.viewDidLoad()
textView.delegate = self
}
func textViewShouldBeginEditing(textView: UITextView) -> Bool {
self.textView.textColor = .black
if(self.textView.text == placeHolderText) {
self.textView.text = ""
}
return true
}
func textViewDidEndEditing(textView: UITextView) {
if(textView.text == "") {
self.textView.text = placeHolderText
self.textView.textColor = .lightGray
}
}
override func viewWillAppear(animated: Bool) {
if(currentQuestion.answerDisplayValue == "") {
self.textView.text = placeHolderText
self.textView.textColor = .lightGray
} else {
self.textView.text = "xxx" // load default text / or stored
self.textView.textColor = .black
}
}
I know there are already a lot of answers to this one, but I didn't really find any of them sufficient (at least in Swift). I needed the "placeholder" functionality of the UITextField in my UITextView (I wanted the exact behavior, including text display attributes, animations, etc, and didn't want to have to maintain this over time). I also wanted a solution that provided the same exact border as a UITextField (not an approximated one that looks sort of like it looks right now, but one that looks exactly like it and will always look exactly like it). So while I was not initially a fan of jamming an extra control into the mix, it seemed that in order to meet my goals I had to use an actual UITextField and let it do the work.
这个解决方案处理定位占位符和保持字体在两个控件之间的同步,以便占位符文本是输入到控件的文本的确切字体和位置(许多其他解决方案没有解决的问题)。
// This class is necessary to support "inset" (required to position placeholder
// appropriately in TextView)
//
class TextField: UITextField
{
var inset: UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0);
override func textRectForBounds(bounds: CGRect) -> CGRect
{
return UIEdgeInsetsInsetRect(bounds, inset);
}
override func placeholderRectForBounds(bounds: CGRect) -> CGRect
{
return UIEdgeInsetsInsetRect(bounds, inset);
}
}
// This class implements a UITextView that has a UITextField behind it, where the
// UITextField provides the border and the placeholder text functionality (so that the
// TextView looks and works like a UITextField).
//
class TextView : UITextView, UITextViewDelegate
{
var textField = TextField();
required init?(coder: NSCoder)
{
super.init(coder: coder);
}
override init(frame: CGRect, textContainer: NSTextContainer?)
{
super.init(frame: frame, textContainer: textContainer);
self.delegate = self;
// Create a background TextField with clear (invisible) text and disabled
self.textField.borderStyle = UITextBorderStyle.RoundedRect;
self.textField.textColor = UIColor.clearColor();
self.textField.userInteractionEnabled = false;
// Align the background TextView to where text appears in the TextField, so
// that any placeholder will be in the correct position.
self.textField.contentVerticalAlignment = UIControlContentVerticalAlignment.Top;
self.textField.inset = UIEdgeInsets(
top: self.textContainerInset.top,
left: self.textContainerInset.left + self.textContainer.lineFragmentPadding,
bottom: self.textContainerInset.bottom,
right: self.textContainerInset.right
);
// The background TextField should use the same font (for the placeholder)
self.textField.font = self.font;
self.addSubview(textField);
self.sendSubviewToBack(textField);
}
convenience init()
{
self.init(frame: CGRectZero, textContainer: nil)
}
override var font: UIFont?
{
didSet
{
// Keep the font of the TextView and background textField in sync
self.textField.font = self.font;
}
}
var placeholder: String? = nil
{
didSet
{
self.textField.placeholder = self.placeholder;
}
}
override func layoutSubviews()
{
super.layoutSubviews()
// Do not scroll the background textView
self.textField.frame = CGRectMake(0, self.contentOffset.y, self.frame.width, self.frame.height);
}
// UITextViewDelegate - Note: If you replace delegate, your delegate must call this
func scrollViewDidScroll(scrollView: UIScrollView)
{
// Do not scroll the background textView
self.textField.frame = CGRectMake(0, self.contentOffset.y, self.frame.width, self.frame.height);
}
// UITextViewDelegate - Note: If you replace delegate, your delegate must call this
func textViewDidChange(textView: UITextView)
{
// Updating the text in the background textView will cause the placeholder to
// appear/disappear (including any animations of that behavior - since the
// textView is doing this itself).
self.textField.text = self.text;
}
}
我刚刚发现,在iOS 10中,你现在可以将UITextView转换为方法的UITextField,并在方法中设置占位符。刚试过,它不需要子类化UITextView就能工作。
下面是一个对我有用的例子:
-(void)customizeTextField:(UITextField *)textField placeholder:(NSString *)pText withColor:(UIColor *)pTextColor{
textField.attributedPlaceholder = [[NSAttributedString alloc]
initWithString:pText
attributes:@{NSForegroundColorAttributeName:pTextColor}];
}
为了将它用于UITextView,你只需要将它传递给方法,使用像这样的类型转换:
[self customizeTextField:(UITextField*)_myTextView placeholder:@"Placeholder" withColor:[UIColor blackColor]];
注:经过测试,我发现这个解决方案在iOS9上也很好。但是会在iOS8.x上导致崩溃
这完美地模仿了UITextField的占位符,其中占位符文本一直保留到您实际键入一些内容为止。
private let placeholder = "Type here"
@IBOutlet weak var textView: UITextView! {
didSet {
textView.textColor = UIColor.lightGray
textView.text = placeholder
textView.selectedRange = NSRange(location: 0, length: 0)
}
}
extension ViewController: UITextViewDelegate {
func textViewDidChangeSelection(_ textView: UITextView) {
// Move cursor to beginning on first tap
if textView.text == placeholder {
textView.selectedRange = NSRange(location: 0, length: 0)
}
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if textView.text == placeholder && !text.isEmpty {
textView.text = nil
textView.textColor = UIColor.black
textView.selectedRange = NSRange(location: 0, length: 0)
}
return true
}
func textViewDidChange(_ textView: UITextView) {
if textView.text.isEmpty {
textView.textColor = UIColor.lightGray
textView.text = placeholder
}
}
}