如何在UITextView中插入占位符?

52

是否有办法在UITextView中插入类似于UITextField的占位符?如果是,请发送任何链接或任何想法来实现此功能。


使用UITextView+Placeholder类别怎么样?https://github.com/devxoul/UITextView-Placeholder - devxoul
6个回答

212

虽然在UITextView中无法创建占位符,但是可以通过以下方法生成类似于占位符的效果。

- (void)viewDidLoad {   
    commentTxtView.text = @"Comment";
    commentTxtView.textColor = [UIColor lightGrayColor];
    commentTxtView.delegate = self;

}
- (BOOL) textViewShouldBeginEditing:(UITextView *)textView {
    commentTxtView.text = @"";
    commentTxtView.textColor = [UIColor blackColor];
    return YES;
}

-(void) textViewDidChange:(UITextView *)textView {

    if(commentTxtView.text.length == 0) {
        commentTxtView.textColor = [UIColor lightGrayColor];
        commentTxtView.text = @"Comment";
        [commentTxtView resignFirstResponder];
    }
}

-(void) textViewShouldEndEditing:(UITextView *)textView {

    if(commentTxtView.text.length == 0) {
        commentTxtView.textColor = [UIColor lightGrayColor];
        commentTxtView.text = @"Comment";
        [commentTxtView resignFirstResponder];
    }
}

或者你可以像这样在TextView中添加标签

lbl = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 0.0,textView.frame.size.width - 10.0, 34.0)];

[lbl setText:kDescriptionPlaceholder];
[lbl setBackgroundColor:[UIColor clearColor]];
[lbl setTextColor:[UIColor lightGrayColor]];
textView.delegate = self;

[textView addSubview:lbl];

并设置

- (void)textViewDidEndEditing:(UITextView *) textView {
    if (![textView hasText]) {
        lbl.hidden = NO;
    }
}

- (void) textViewDidChange:(UITextView *)textView {
    if(![textView hasText]) {
        lbl.hidden = NO;
    }
    else {
        lbl.hidden = YES;
    }  
}

23
很简单明了,但是textViewShouldBeginEditing函数总是会擦除所有文本——当用户输入一些文本,离开文本视图,然后再次回来编辑时,你可能不希望它这样。可以只检查颜色并且只有在文本为灰色时才进行擦除。 - n13
2
永远不要忘记将TextView的Delegate方法设置为self, 在ViewDidLoad中插入以下代码: commentTxtView.delegate=self; - AsifHabib
很好的解决方案,我稍微修改了一下方法 - (BOOL) textViewShouldBeginEditing:(UITextView *)textView { if ([commentTxtView.text isEqualToString:@"Comment"]) { commentTxtView.text = @""; commentTxtView.textColor = [UIColor blackColor]; } return YES; } 当 TextView 再次获得焦点时很有帮助。 - Arkady
非常好的和有用的回答。+1。感谢@Dejel提供多个文本字段使用标签的建议。将标签添加到与文本字段相关的标签上,以便您可以使用文本字段标签找到它,例如.. textfield.tag = 500,然后给lbl.tag = 1000,因此在textfield委托方法中,您可以使用UILabel *lbl =(UILabel *)[self.view viewWithTag:textView.tag + 500];获取标签。我有类似的需求,我已经使用这种方法完成了它。 - Dilip Manek
你可以使用另一个UITextView代替UILabel来匹配父视图的文本插图。 - Uladzimir
显示剩余2条评论

18

另一个简单的解决方案是将 UILabel 添加为你的 UITextView 子视图。

- (void)viewDidLoad
{
  [super viewDidLoad];

  // you might have to play around a little with numbers in CGRectMake method
  // they work fine with my settings
  placeholderLabel = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 0.0, textView.frame.size.width - 20.0, 34.0)];
  [placeholderLabel setText:kDescriptionPlaceholder];
  // placeholderLabel is instance variable retained by view controller
  [placeholderLabel setBackgroundColor:[UIColor clearColor]];
  [placeholderLabel setFont:[challengeDescription font]];
  [placeholderLabel setTextColor:[UIColor lightGrayColor]];

  // textView is UITextView object you want add placeholder text to
  [textView addSubview:placeholderLabel];
}

- (void) textViewDidChange:(UITextView *)theTextView
{
  if(![textView hasText]) {
    [textView addSubview:placeholderLabel];
  } else if ([[textView subviews] containsObject:placeholderLabel]) {
    [placeholderLabel removeFromSuperview];
  }
}

- (void)textViewDidEndEditing:(UITextView *)theTextView
{
  if (![textView hasText]) {
    [textView addSubview:placeholderLabel];
  }
}

如果您喜欢的话,甚至可以为淡入/淡出 UILabel 添加小动画效果。

- (void) textViewDidChange:(UITextView *)theTextView
{
  if(![textView hasText]) {
    [textView addSubview:placeholderLabel];
    [UIView animateWithDuration:0.15 animations:^{
      placeholderLabel.alpha = 1.0;
    }];
  } else if ([[textView subviews] containsObject:placeholderLabel]) {

    [UIView animateWithDuration:0.15 animations:^{
      placeholderLabel.alpha = 0.0;
    } completion:^(BOOL finished) {
      [placeholderLabel removeFromSuperview];
    }];
  }
}


- (void)textViewDidEndEditing:(UITextView *)theTextView
{
  if (![textView hasText]) {
    [textView addSubview:placeholderLabel];
    [UIView animateWithDuration:0.15 animations:^{
      placeholderLabel.alpha = 1.0;
    }];
}

1
这可能可行,但违反了苹果的明确建议:“虽然在标准系统控件(从UIControl继承的对象)中添加子视图是技术上可能的,但你不应以此方式自定义它们。”这段话来自https://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/WindowsandViews/WindowsandViews.html#//apple_ref/doc/uid/TP40009503-CH2-SW26的“不要通过嵌入子视图自定义控件”一节。 - algal
当然,我同意。但在苹果实现这个功能之前,这是一个相当不错的解决方案。 - jlajlar
@algal 那么,你有什么建议?重写 drawRect: 不也同样危险(或者说更加危险)吗? - ma11hew28
@MattDiPasquale 所选答案中的两个选项中,第一个选项似乎更加干净,因为它仅将逻辑添加到视图控制器,并仅通过其预定接口修改UITextView。 - algal
@algal 说得好,但那个方案并不完美:1. 它在 textViewShouldBeginEditing: 上删除了占位符文本,而不是使用 !textField.hasText()。2. 它不够模块化。例如,我更愿意有一个自定义的子类叫做 PlaceholderTextView (例如,观察 UITextViewTextDidChangeNotification), 我可以将其直接放置并设置其 placeholder 属性。 - ma11hew28

9
另一个简单的解决方案是将占位符标签的隐藏属性设置为YES/NO。
- (void)textViewDidEndEditing:(UITextView *)theTextView
{
    if (![textView hasText]) {
        placeholderLabel.hidden = NO;
    }
}

- (void) textViewDidChange:(UITextView *)textView
{
    if(![textView hasText]) {
        placeholderLabel.hidden = NO;
    }
    else{
        placeholderLabel.hidden = YES;
    }
}

5
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
  // NSLog(@"REPlace %@ %d",text,range.location);
  if(range.location==0 && ![text isEqualToString:@""])
  {
    placeholderlbl.hidden = YES;
  }
  else if(range.location==0)
  {
    placeholderlbl.hidden = NO;
  }

  return YES;
}

1
你可以使用以下函数来创建占位符,使用它可以在其中设置占位符。
[self addTextViewPlaceholder:self.txtvComment withPlaceholder:@"COMMENT"];

-(void) addTextViewPlaceholder:(UITextView*) tView withPlaceholder:(NSString*) placeholder
{
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(9,8,tView.bounds.size.width - 16,0)];
    label.lineBreakMode = UILineBreakModeWordWrap;
    label.numberOfLines = 0;
    label.font = [UIFont systemFontOfSize:13.0];
    label.backgroundColor = [UIColor clearColor];
    label.textColor = [UIColor colorWithRed:0.7 green:0.7 blue:0.7 alpha:1.0];

    label.text = placeholder;
    label.alpha = 1;
    label.tag = 999;
    [tView addSubview:label];
    [label sizeToFit];
    if(![tView.text isEqualToString:@""])
        [label setAlpha:0];
    [label release];
}

您可以使用此功能管理占位符文本。
- (void)textViewDidChange:(UITextView *)textView
{
    [self textChange:textView];
}

- (void)textChange:(UITextView *)textView
{
    if([textView.text length]>0)
        [[textView viewWithTag:999] setAlpha:0];
    else
        [[textView viewWithTag:999] setAlpha:1];
}

0
另一种解决方法是将一个占位符UITextView放在实际的UITextView正上方。 给它相同的框架。 对于占位符TextView,设置 placeholderTextView.enabled = NO
然后,仅为普通textView设置委托并定义此UITextViewDelegate方法:
- (void)textViewDidChange:(UITextView *)textView
{
    NSLog(@"textViewDidChange");

    if(self.textView.text.length == 0)
    {
        self.placeholderTextView.hidden = NO;
    }
    else
    {
        self.placeholderTextView.hidden = YES;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接