我的应用程序使用UITextView。现在我想让UITextView有一个占位符,类似于你可以为UITextField设置的占位符。
如何做到这一点?
我的应用程序使用UITextView。现在我想让UITextView有一个占位符,类似于你可以为UITextField设置的占位符。
如何做到这一点?
当前回答
你可以在UITextView上设置标签
[UITextView addSubView:lblPlaceHoldaer];
并隐藏在TextViewdidChange方法上。
这是一个简单易行的方法。
其他回答
这完美地模仿了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
}
}
}
我找到了自己的解决方案
- (void)textViewDidBeginEditing:(UITextView *)textView
{
if ([textView.text isEqualToString:PLACEHOLDER_TEXT])
{
textView.textColor = [UIColor lightGrayColor];
dispatch_async(dispatch_get_main_queue(), ^
{
textView.selectedRange = NSMakeRange(0, 0);
});
}
else
{
textView.textColor = [UIColor blackColor];
}
[textView becomeFirstResponder];
}
- (void)textViewDidEndEditing:(UITextView *)textView
{
if ([textView.text isEqualToString:@""])
{
textView.text = PLACEHOLDER_TEXT;
textView.textColor = [UIColor lightGrayColor];
}
[textView resignFirstResponder];
}
- (BOOL)textView:(UITextView *)textView
shouldChangeTextInRange:(NSRange)range
replacementText:(NSString *)text
{
if (range.location == 0 && range.length == [[textView text] length] && [text isEqualToString:@""])
{
textView.text = PLACEHOLDER_TEXT;
textView.textColor = [UIColor lightGrayColor];
dispatch_async(dispatch_get_main_queue(), ^
{
textView.selectedRange = NSMakeRange(0, 0);
});
return NO;
}
if ([textView.text isEqualToString:PLACEHOLDER_TEXT])
{
textView.text = @"";
textView.textColor = [UIColor blackColor];
}
return YES;
}
简单的方法,使用以下UITextViewDelegate方法在UITextView中创建占位符文本:
- (void)textViewDidBeginEditing:(UITextView *)textView
{
if ([textView.text isEqualToString:@"placeholder text here..."]) {
textView.text = @"";
textView.textColor = [UIColor blackColor]; //optional
}
[textView becomeFirstResponder];
}
- (void)textViewDidEndEditing:(UITextView *)textView
{
if ([textView.text isEqualToString:@""]) {
textView.text = @"placeholder text here...";
textView.textColor = [UIColor lightGrayColor]; //optional
}
[textView resignFirstResponder];
}
只需要记住在创建时使用准确的文本设置myUITextView即可。
UITextView *myUITextView = [[UITextView alloc] init];
myUITextView.delegate = self;
myUITextView.text = @"placeholder text here...";
myUITextView.textColor = [UIColor lightGrayColor]; //optional
在包含这些方法之前,让父类成为一个UITextViewDelegate。
@interface MyClass () <UITextViewDelegate>
@end
Swift 3.1代码
func textViewDidBeginEditing(_ textView: UITextView)
{
if (textView.text == "placeholder text here..." && textView.textColor == .lightGray)
{
textView.text = ""
textView.textColor = .black
}
textView.becomeFirstResponder() //Optional
}
func textViewDidEndEditing(_ textView: UITextView)
{
if (textView.text == "")
{
textView.text = "placeholder text here..."
textView.textColor = .lightGray
}
textView.resignFirstResponder()
}
只需要记住在创建时使用准确的文本设置myUITextView即可。
let myUITextView = UITextView.init()
myUITextView.delegate = self
myUITextView.text = "placeholder text here..."
myUITextView.textColor = .lightGray
在包含这些方法之前,让父类成为一个UITextViewDelegate。
class MyClass: UITextViewDelegate
{
}
让我们简单点
创建一个UILabel并把它放在你的文本视图上(给文本作为占位符-设置颜色为灰色-你可以在你的xib中做这一切) 现在在头文件中声明UILabel和textviewDelegate 现在你可以简单地隐藏标签,当你点击textview
完整代码如下
头
@interface ViewController :UIViewController<UITextViewDelegate>{
}
@property (nonatomic,strong) IBOutlet UILabel *PlceHolder_label;
@property (nonatomic,strong) IBOutlet UITextView *TextView;
@end
实现
@implementation UploadFoodImageViewController
@synthesize PlceHolder_label,TextView;
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView{
if([textView isEqual:TextView]){
[PlceHolder_label setHidden:YES];
[self.tabScrlVw setContentOffset:CGPointMake(0,150) animated:YES];
}
return YES;
}
@end
别忘了连接textView和UILabel文件所有者从xib
After looking through (and trying out) most of the proposed solutions to this seemingly obvious - but missing - feature of UITextView, the 'best' closest I found was that from BobDickinson. But I didnt like having to resort to a whole new subclass [I prefer drop-in categories for such simple functional additions], nor that it intercepted UITextViewDelegate methods, which is probably going to mess up your existing UITextView handling code. So here's my take on a drop-in category that'll work on any existing UITextView instance...
#import <objc/runtime.h>
// Private subclass needed to override placeholderRectForBounds: to correctly position placeholder
@interface _TextField : UITextField
@property UIEdgeInsets insets;
@end
@implementation _TextField
- (CGRect)placeholderRectForBounds:(CGRect)bounds
{
CGRect rect = [super placeholderRectForBounds:bounds];
return UIEdgeInsetsInsetRect(rect, _insets);
}
@end
@implementation UITextView (Placeholder)
static const void *KEY;
- (void)setPlaceholder:(NSString *)placeholder
{
_TextField *textField = objc_getAssociatedObject(self, &KEY);
if (!textField) {
textField = [_TextField.alloc initWithFrame:self.bounds];
textField.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
textField.userInteractionEnabled = NO;
textField.font = self.font;
textField.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;
textField.insets = UIEdgeInsetsMake(self.textContainerInset.top,
self.textContainerInset.left + self.textContainer.lineFragmentPadding,
self.textContainerInset.bottom,
self.textContainerInset.right);
[self addSubview:textField];
[self sendSubviewToBack:textField];
objc_setAssociatedObject(self, &KEY, textField, OBJC_ASSOCIATION_RETAIN);
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(updatePlaceholder:) name:UITextViewTextDidChangeNotification object:nil];
}
textField.placeholder = placeholder;
}
- (NSString*)placeholder
{
UITextField *textField = objc_getAssociatedObject(self, &KEY);
return textField.placeholder;
}
- (void)updatePlaceholder:(NSNotification *)notification
{
UITextField *textField = objc_getAssociatedObject(self, &KEY);
textField.font = self.font;
[textField setAlpha:self.text.length? 0 : 1];
}
@end
它使用简单,只是显而易见的
UITextView *myTextView = UITextView.new;
...
myTextView.placeholder = @"enter text here";
它通过添加一个UITextField -在正确的位置-在你的UITextView后面,并利用它的占位符代替(因此你不必担心得到正确的颜色等),然后监听通知,每当你的UITextView被改变显示/隐藏这个UITextField(因此它不会干扰你现有的UITextViewDelegate调用)。这里面没有什么神奇的数字……: -)
objc_setAssociatedObject()/objc_getAssociatedObject()是为了避免必须子类化UITextView。[不幸的是,要正确地定位UITextField,有必要引入一个'private'子类,以覆盖placeholderRectForBounds:]
改编自BobDickinson的斯威夫特回答。