Placeholder text in UITextView
For a recent iPhone app I wanted a multi-line editable text field, in which I could display placeholder text so my user would know what to do with the field.
Placeholder text is a common affordance provided by several UI classes such as UITextField. But UITextView in iOS 4 does not support placeholder text.
A web search turned up several implementations. Some of these seemed too complex, and some failed to provide the behavior I wanted:
- If the view is empty, show the placeholder.
- Whenever the view is the first responder, hide the placeholder.
Here's my implementation. It's very basic. For example it doesn't let you customize the color of the placeholder text; and the placeholder is always centered vertically within the bounds of the text view. But it does provide the behaviors listed above.
PlaceholderTextView.h
#import <UIKit/UIKit.h> @interface PlaceholderTextView : UITextView { UILabel *placeholderLabel; NSString *placeholderText; } @property (nonatomic, retain) NSString *placeholderText; @end
PlaceholderTextView.m
#import "PlaceholderTextView.h" @implementation PlaceholderTextView @synthesize placeholderText; - (void)hidePlaceholder { if ([placeholderLabel superview]) { [placeholderLabel removeFromSuperview]; } } - (void)maybeShowPlaceholder { if ([placeholderText length] > 0) { if (![self hasText] && ![placeholderLabel superview]) { CGRect frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height); placeholderLabel.frame = frame; placeholderLabel.text = placeholderText; [self addSubview:placeholderLabel]; } } } - (void)initCommon { if (!placeholderLabel) { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(beganEditing:) name:UITextViewTextDidBeginEditingNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(endedEditing:) name:UITextViewTextDidEndEditingNotification object:nil]; placeholderLabel = [[UILabel alloc] init]; placeholderLabel.numberOfLines = 0; placeholderLabel.backgroundColor = [UIColor clearColor]; placeholderLabel.textColor = [UIColor lightGrayColor]; placeholderLabel.font = self.font; placeholderLabel.lineBreakMode = UILineBreakModeWordWrap; placeholderLabel.textAlignment = UITextAlignmentCenter; [self maybeShowPlaceholder]; } } - (void)awakeFromNib { [super awakeFromNib]; [self initCommon]; } - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self initCommon]; } return self; } - (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { [self initCommon]; } return self; } - (id)init { self = [super init]; if (self) { [self initCommon]; } return self; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [placeholderLabel release]; [placeholderText release]; [super dealloc]; } - (void)setPlaceholderText:(NSString *)newValue { [newValue retain]; NSString *oldValue = placeholderText; placeholderText = newValue; [oldValue release]; [self maybeShowPlaceholder]; } - (void)beganEditing:(NSNotification *)notification { [self hidePlaceholder]; } - (void)endedEditing:(NSNotification *)notification { [self maybeShowPlaceholder]; } @end