The UITextView
class can
display multiple lines of text and contain scrollable content, meaning
that if the contents run off the boundaries of the text view, the text
view’s internal components allow the user to scroll the text up and down
to see different parts of the text. An example of a text view in an iOS
app is the Notes app on the iPhone (Figure 1-54).
Let’s create a text view and see how it works. We start off by declaring the text view in our view controller’s implementation file:
#import "ViewController.h"
@interface
ViewController
()
@property
(
nonatomic
,
strong
)
UITextView
*
myTextView
;
@end
@implementation
ViewController
Now it’s time to create the text view itself. We will make the text view as big as the view controller’s view:
-
(
void
)
viewDidLoad
{
[
super
viewDidLoad
];
self
.
myTextView
=
[[
UITextView
alloc
]
initWithFrame
:
self
.
view
.
bounds
];
self
.
myTextView
.
text
=
@"Some text here..."
;
self
.
myTextView
.
contentInset
=
UIEdgeInsetsMake
(
10.0f
,
0.0f
,
0.0f
,
0.0f
);
self
.
myTextView
.
font
=
[
UIFont
systemFontOfSize
:
16.0f
];
[
self
.
view
addSubview
:
self
.
myTextView
];
}
Now let’s run the app in iOS Simulator and see how it looks (Figure 1-55).
If you tap on the text field, you will notice a keyboard pop up from the bottom of the screen, concealing almost half the entire area of the text view. That means if the user starts typing text and gets to the middle of the text view, the rest of the text that she types will not be visible to her (Figure 1-56).
To remedy this, we have to listen for certain notifications:
UIKeyboardWillShowNotification
Gets sent by the system whenever the keyboard is brought up on the screen for any component, be it a text field, a text view, etc.
UIKeyboardDidShowNotification
Gets sent by the system when the keyboard has already been displayed.
UIKeyboardWillHideNotification
Gets sent by the system when the keyboard is about to hide.
UIKeyboardDidHideNotification
Gets sent by the system when the keyboard is now fully hidden.
Note
The keyboard notifications contain a dictionary, accessible
through the userInfo
property, that
specifies the boundaries of the keyboard on the screen. This property
is of type NSDictionary
. One of the
keys in this dictionary is UIKeyboardFrameEndUserInfoKey
, which
contains an object of type NSValue
that itself contains the rectangular boundaries of the keyboard when
it is fully shown. This rectangular area is denoted with a CGRect
.
So our strategy is to find out when the keyboard is getting
displayed and then somehow resize our text view. For this, we will use
the contentInset
property of UITextView
to specify the margins of contents
in the text view from top, left, bottom, and right:
-
(
void
)
handleKeyboardDidShow:
(
NSNotification
*
)
paramNotification
{
/* Get the frame of the keyboard */
NSValue
*
keyboardRectAsObject
=
[[
paramNotification
userInfo
]
objectForKey:
UIKeyboardFrameEndUserInfoKey
];
/* Place it in a CGRect */
CGRect
keyboardRect
=
CGRectZero
;
[
keyboardRectAsObject
getValue
:&
keyboardRect
];
/* Give a bottom margin to our text view that makes it
reach to the top of the keyboard */
self
.
myTextView
.
contentInset
=
UIEdgeInsetsMake
(
0.0f
,
0.0f
,
keyboardRect
.
size
.
height
,
0.0f
);
}
-
(
void
)
handleKeyboardWillHide:
(
NSNotification
*
)
paramNotification
{
/* Make the text view as big as the whole view again */
self
.
myTextView
.
contentInset
=
UIEdgeInsetsZero
;
}
-
(
void
)
viewWillAppear:
(
BOOL
)
paramAnimated
{
[
super
viewWillAppear
:
paramAnimated
];
[[
NSNotificationCenter
defaultCenter
]
addObserver:
self
selector:
@selector
(
handleKeyboardDidShow
:
)
name:
UIKeyboardDidShowNotification
object:
nil
];
[[
NSNotificationCenter
defaultCenter
]
addObserver:
self
selector:
@selector
(
handleKeyboardWillHide
:
)
name:
UIKeyboardWillHideNotification
object:
nil
];
self
.
myTextView
=
[[
UITextView
alloc
]
initWithFrame
:
self
.
view
.
bounds
];
self
.
myTextView
.
text
=
@"Some text here..."
;
self
.
myTextView
.
font
=
[
UIFont
systemFontOfSize
:
16.0f
];
[
self
.
view
addSubview
:
self
.
myTextView
];
}
-
(
void
)
viewWillDisappear:
(
BOOL
)
paramAnimated
{
[
super
viewWillDisappear
:
paramAnimated
];
[[
NSNotificationCenter
defaultCenter
]
removeObserver
:
self
];
}
In this code, we start looking for keyboard notifications in
viewWillAppear:
and we stop listening
to keyboard notifications in viewWillDisappear:
. Removing your view
controller as the listener is important, because when your view
controller is no longer displayed, you probably don’t want to receive
keyboard notifications fired by any other view controller. There may be
times when a view controller in the background needs to receive
notifications, but these are rare, and you must normally make sure to
stop listening for notifications in viewWillDisappear:
. I’ve seen many programmers
break their apps by not taking care of this simple logic.
Note
If you intend to change your UI structure when the keyboard gets
displayed and when the keyboard is dismissed, the only method that you
can rely on is to use the keyboard notifications. Delegate messages of
UITextField
get fired when the text
field is getting edited, whether there is a soft keyboard on the
screen or not. Remember, a user can have a Bluetooth keyboard
connected to his iOS device and use it to edit the content of text
fields and any other data entry in your apps. In the case of a
Bluetooth keyboard, no soft keyboard will be displayed on the
screen—and if you change your UI when your text fields start to get
edited, you might unnecessarily change the UI while the Bluetooth
keyboard user is editing text.
Now, if the user tries to enter some text into the text view, the keyboard will pop up, and we take the height of the keyboard and assign that value as the bottom margin of the contents inside the text view. This makes our text view’s contents smaller in size and allows the user to enter as much text as she wishes without the keyboard blocking her view.
Get iOS 7 Programming Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.