Utas ini telah memiliki banyak jawaban, tetapi inilah versi yang saya sukai.
Itu memperluasUITextView
kelas yang sudah ada sehingga mudah digunakan kembali, dan itu tidak mencegat peristiwa seperti textViewDidChange
(yang dapat merusak kode pengguna, jika mereka sudah mencegat acara ini di tempat lain).
Menggunakan kode saya (diperlihatkan di bawah), Anda dapat dengan mudah menambahkan placeholder ke salah satu dari Anda UITextViews
seperti ini:
self.textViewComments.placeholder = @"(Enter some comments here.)";
Saat Anda menetapkan nilai tempat penampung baru ini, itu menambahkan nilai diam-diam UILabel
di atas Anda UITextView
, lalu sembunyikan / perlihatkan:
Oke, untuk melakukan perubahan ini, tambahkan file "UITextViewHelper.h" yang berisi kode ini:
// UITextViewHelper.h
// Created by Michael Gledhill on 13/02/15.
#import <Foundation/Foundation.h>
@interface UITextView (UITextViewHelper)
@property (nonatomic, strong) NSString* placeholder;
@property (nonatomic, strong) UILabel* placeholderLabel;
@property (nonatomic, strong) NSString* textValue;
-(void)checkIfNeedToDisplayPlaceholder;
@end
... dan file UITextViewHelper.m yang berisi ini:
// UITextViewHelper.m
// Created by Michael Gledhill on 13/02/15.
//
// This UITextView category allows us to easily display a PlaceHolder string in our UITextView.
// The downside is that, your code needs to set the "textValue" rather than the "text" value to safely set the UITextView's text.
//
#import "UITextViewHelper.h"
#import <objc/runtime.h>
@implementation UITextView (UITextViewHelper)
#define UI_PLACEHOLDER_TEXT_COLOR [UIColor colorWithRed:170.0/255.0 green:170.0/255.0 blue:170.0/255.0 alpha:1.0]
@dynamic placeholder;
@dynamic placeholderLabel;
@dynamic textValue;
-(void)setTextValue:(NSString *)textValue
{
// Change the text of our UITextView, and check whether we need to display the placeholder.
self.text = textValue;
[self checkIfNeedToDisplayPlaceholder];
}
-(NSString*)textValue
{
return self.text;
}
-(void)checkIfNeedToDisplayPlaceholder
{
// If our UITextView is empty, display our Placeholder label (if we have one)
if (self.placeholderLabel == nil)
return;
self.placeholderLabel.hidden = (![self.text isEqualToString:@""]);
}
-(void)onTap
{
// When the user taps in our UITextView, we'll see if we need to remove the placeholder text.
[self checkIfNeedToDisplayPlaceholder];
// Make the onscreen keyboard appear.
[self becomeFirstResponder];
}
-(void)keyPressed:(NSNotification*)notification
{
// The user has just typed a character in our UITextView (or pressed the delete key).
// Do we need to display our Placeholder label ?
[self checkIfNeedToDisplayPlaceholder];
}
#pragma mark - Add a "placeHolder" string to the UITextView class
NSString const *kKeyPlaceHolder = @"kKeyPlaceHolder";
-(void)setPlaceholder:(NSString *)_placeholder
{
// Sets our "placeholder" text string, creates a new UILabel to contain it, and modifies our UITextView to cope with
// showing/hiding the UILabel when needed.
objc_setAssociatedObject(self, &kKeyPlaceHolder, (id)_placeholder, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
self.placeholderLabel = [[UILabel alloc] initWithFrame:self.frame];
self.placeholderLabel.numberOfLines = 1;
self.placeholderLabel.text = _placeholder;
self.placeholderLabel.textColor = UI_PLACEHOLDER_TEXT_COLOR;
self.placeholderLabel.backgroundColor = [UIColor clearColor];
self.placeholderLabel.userInteractionEnabled = true;
self.placeholderLabel.font = self.font;
[self addSubview:self.placeholderLabel];
[self.placeholderLabel sizeToFit];
// Whenever the user taps within the UITextView, we'll give the textview the focus, and hide the placeholder if necessary.
[self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTap)]];
// Whenever the user types something in the UITextView, we'll see if we need to hide/show the placeholder label.
[[NSNotificationCenter defaultCenter] addObserver:self selector: @selector(keyPressed:) name:UITextViewTextDidChangeNotification object:nil];
[self checkIfNeedToDisplayPlaceholder];
}
-(NSString*)placeholder
{
// Returns our "placeholder" text string
return objc_getAssociatedObject(self, &kKeyPlaceHolder);
}
#pragma mark - Add a "UILabel" to this UITextView class
NSString const *kKeyLabel = @"kKeyLabel";
-(void)setPlaceholderLabel:(UILabel *)placeholderLabel
{
// Stores our new UILabel (which contains our placeholder string)
objc_setAssociatedObject(self, &kKeyLabel, (id)placeholderLabel, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[[NSNotificationCenter defaultCenter] addObserver:self selector: @selector(keyPressed:) name:UITextViewTextDidChangeNotification object:nil];
[self checkIfNeedToDisplayPlaceholder];
}
-(UILabel*)placeholderLabel
{
// Returns our new UILabel
return objc_getAssociatedObject(self, &kKeyLabel);
}
@end
Yup, ini banyak kode, tapi begitu Anda sudah menambahkannya ke proyek Anda dan menyertakan file .h ...
#import "UITextViewHelper.h"
... Anda dapat dengan mudah menggunakan placeholder di UITextViews
.
Ada satu gotcha.
Jika kamu melakukan ini:
self.textViewComments.placeholder = @"(Enter some comments here.)";
self.textViewComments.text = @"Ooooh, hello there";
... placeholder akan muncul di atas teks. Saat Anda menetapkan text
nilainya, tidak ada notifikasi reguler yang dipanggil, jadi saya tidak tahu cara memanggil fungsi saya untuk memutuskan apakah akan menampilkan / menyembunyikan placeholder.
Solusinya adalah dengan mengatur textValue
daripada text
:
self.textViewComments.placeholder = @"(Enter some comments here.)";
self.textViewComments.textValue = @"Ooooh, hello there";
Atau, Anda dapat mengatur text
nilainya, lalu menelepon checkIfNeedToDisplayPlaceholder
.
self.textViewComments.text = @"Ooooh, hello there";
[self.textViewComments checkIfNeedToDisplayPlaceholder];
Saya suka solusi seperti ini, karena mereka "mengisi celah" antara apa yang Apple berikan kepada kami, dan apa yang sebenarnya kami (sebagai pengembang) butuhkan dalam aplikasi kami. Anda menulis kode ini satu kali, menambahkannya ke perpustakaan Anda dari file "helper" .m / .h, dan, seiring waktu, SDK sebenarnya mulai menjadi kurang membuat frustrasi.
(Saya menulis pembantu serupa untuk menambahkan tombol "jelas" ke UITextViews saya, hal lain yang mengganggu UITextField
tetapi tidak di UITextView
...)