Читать книгу iOS. Приемы программирования - Вандад Нахавандипур - Страница 41
Глава 1. Реализация контроллеров и видов
1.20. Отображение длинных текстовых строк с помощью UITextView
ОглавлениеПостановка задачи
Требуется отображать в пользовательском интерфейсе несколько строк текста с возможностью прокрутки.
Решение
Воспользуйтесь классом UITextView.
Обсуждение
Класс UITextView позволяет отображать несколько строк текста и создавать прокручиваемое содержимое. Это означает, что если содержимое не умещается в границах текстового вида, то внутренние компоненты этого текстового вида позволяют пользователю прокручивать текст вверх и вниз и просматривать различные его части. В качестве примера текстового вида, входящего в приложение iOS, рассмотрим программу Notes (Блокнот) в iPhone (рис. 1.54).
Рис. 1.54. Программа Notes (Блокнот) в iPhone, здесь текст отображается в текстовом виде
Создадим текстовый вид и посмотрим, как он работает. Для начала определим текстовый вид в файле реализации контроллера нашего вида:
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) UITextView *myTextView;
@end
implementation ViewController
Далее необходимо создать сам текстовый вид. Мы сделаем текстовый вид таким же по размеру, как и вид контроллера вида:
– (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];
}
Запустим приложение в эмуляторе iOS и посмотрим, как оно выглядит (рис. 1.55).
Рис. 1.55. Текстовый вид, занимающий все экранное пространство
Если коснуться текстового поля пальцем, то можно увидеть, как снизу всплывает виртуальная клавиатура. Она довольно крупная и закрывает текстовый вид почти наполовину. То есть если пользователь начнет вводить текст и дойдет примерно до середины окна по вертикали, весь остальной текст, который будет вводиться, окажется заслоненным клавиатурой (рис. 1.56).
Чтобы избежать такой ситуации, необходимо слушать определенные уведомления:
• UIKeyboardWillShowNotification – система выдает такое уведомление всякий раз, когда клавиатура выводится на экран для работы с каким-либо компонентом: текстовым полем, текстовым видом и т. д.;
• UIKeyboardDidShowNotification – система выдает такое уведомление, когда клавиатура отобразится целиком;
• UIKeyboardWillHideNotification – система выдает такое уведомление перед тем, как клавиатура скроется из вида;
Рис. 1.56. Клавиатура, наполовину занимающая текстовый вид
• UIKeyboardDidHideNotification – система выдает такое уведомление после того, как клавиатура полностью скроется из вида.
Уведомления клавиатуры содержат словарь, доступный с помощью свойства userInfo. Он указывает границы клавиатуры на экране и относится к типу NSDictionary. В словаре среди прочего имеется ключ UIKeyboardFrameEndUserInfoKey, содержащий объект типа NSValue. В свою очередь, этот объект содержит прямоугольник, ограничивающий размеры клавиатуры, когда она полностью отображена на экране. Эта прямоугольная область обозначается как CGRect.
Наша стратегия такова: нужно узнать, когда клавиатура полностью отобразится, а потом каким-то способом пересчитать размеры нашего текстового вида. Для этого воспользуемся свойством contentInset класса UITextView, чтобы задать границы контента, содержащегося в текстовом поле, – верхнюю, нижнюю, правую и левую:
– (void) handleKeyboardDidShow:(NSNotification *)paramNotification{
/* Получаем контур клавиатуры. */
NSValue *keyboardRectAsObject =
[[paramNotification userInfo]
objectForKey: UIKeyboardFrameEndUserInfoKey];
/* Помещаем эту информацию в CGRect. */
CGRect keyboardRect;
[keyboardRectAsObject getValue:&keyboardRect];
/* Задаем нижнюю границу нашего текстового вида так, чтобы он доходил ровно до верхней границы клавиатуры. */
self.myTextView.contentInset =
UIEdgeInsetsMake(0.0f,
0.0f,
keyboardRect.size.height,
0.0f);
}
– (void) handleKeyboardWillHide:(NSNotification *)paramNotification{
/* Делаем текстовый вид таким же по размеру, как и вид, содержащий его. */
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];
}
В этом коде начинаем наблюдать за клавиатурными уведомлениями в методе viewWillAppear: и прекращаем слушать их в методе viewWillDisappear:. Важно убрать контроллер вида из списка слушателей, так как вы, вероятно, не хотите получать клавиатурные уведомления, инициируемые контроллером другого вида. Случается, что и при работе в фоновом режиме контроллер вида должен получать уведомления, но это бывает редко. Как правило, нужно прекращать слушание уведомлений в методе viewWillDisappear:. Мне не раз доводилось видеть, как программисты портят хорошие приложения, пренебрегая этой простой логикой.
Если вы намереваетесь изменять структуру пользовательского интерфейса, когда клавиатура выводится на экран и когда она с него убирается, то вам никак не обойтись без слушания клавиатурных уведомлений. Сообщения делегата UITextField запускаются всякий раз, когда начинается редактирование текстового поля, независимо от того, есть ли в этот момент на экране клавиатура. Не забывайте, что пользователь может подключить к устройству iOS беспроводную клавиатуру (с помощью Bluetooth). С этой клавиатуры он сможет редактировать содержимое текстовых полей, а также любых других информационных объектов вашего приложения. При подключении клавиатуры по Bluetooth виртуальная клавиатура на экране отображаться не будет. И если в вашем приложении пользовательский интерфейс станет обязательно перестраиваться, как только начинается ввод данных с клавиатуры, то при подключении беспроводной клавиатуры по Bluetooth такая перестройка окажется ненужной.
Теперь, если пользователь попытается ввести какой-либо текст в текстовый вид, клавиатура «выплывет» на экран снизу, и мы присвоим значение высоты клавиатуры в качестве нижней границы содержимого текстового вида. Таким образом, текстовый вид уменьшится в размерах и пользователь сможет вводить в него столько текста, сколько потребуется, – клавиатура не будет заслонять текст.