Современная электронная библиотека ModernLib.Net

Бестселлеры O`Reilly - iOS. Приемы программирования

ModernLib.Net / Программирование / Вандад Нахавандипур / iOS. Приемы программирования - Чтение (Ознакомительный отрывок) (стр. 5)
Автор: Вандад Нахавандипур
Жанр: Программирование
Серия: Бестселлеры O`Reilly

 

 


• pickerView: numberOfRowsInComponent: – для каждого компонента, добавляемого в вид выбора, необходимо указать системе, какое количество строк вы хотите отобразить в данном компоненте. Этот метод передает вам экземпляр вида выбора, а в качестве возвращаемого значения ожидает целое число, сообщающее среде времени исполнения, сколько строк вы хотели бы отобразить в этом компоненте.

Итак, мы приказываем системе отобразить один компонент всего с 10 строками для вида выбора, который мы создали ранее и назвали myPicker.

Скомпилируйте приложение и запустите его в эмуляторе iPhone (рис. 1.11). Хм-м-м, и что же это?


Рис. 1.11. Вот как выглядит вид выбора, когда неизвестно, какую информацию в нем отображать


По всей видимости, наш вид выбора знает, сколько компонентов в нем должно быть и сколько строк он должен отображать в интересующем нас компоненте, но не знает, какой текст должен содержаться в каждой строке. Этот вопрос обязательно следует прояснить, и мы решим данную проблему, предоставив делегат для вида выбора. Делегат экземпляра UIPickerView должен подчиняться протоколу UIPickerViewDelegate и реализовывать все методы, помеченные как @required.

Нас интересует только один метод делегата UIPickerViewDelegate, а именно pickerView: titleForRow: forComponent:. Этот метод передает вам индекс актуального раздела и индекс актуальной строки в данном разделе вида выбора и в качестве возвращаемого значения ожидает экземпляр NSString. Строка, представленная NSString, отобразится в заданном ряду внутри компонента. В рассматриваемом случае я предпочитаю просто отобразить первую строку как «Строка 1», а затем продолжить: «Строка 2», «Строка 3» и т. д. Не забывайте, что потребуется также установить свойство delegate нашего вида выбора:


self.myPicker.delegate = self;


А теперь обработаем только что изученный метод делегата:


– (NSString *)pickerView:(UIPickerView *)pickerView

titleForRow:(NSInteger)row

forComponent:(NSInteger)component{


if ([pickerView isEqual: self.myPicker]){


/* Строка имеет нулевое основание, а мы хотим, чтобы первая строка

(с индексом 0) отображалась как строка 1. Таким образом, нужно

прибавить +1 к индексу каждой строки. */

result = [NSString stringWithFormat:@"Row %ld", (long)row + 1];


}

return nil;

}


Теперь запустим приложение и посмотрим, что происходит (рис. 1.12).


Рис. 1.12. Вид выбора с одним разделом и несколькими строками


Виды с возможностью выбора в iOS 6 и старше могут подсвечивать выбранный вариант с помощью свойства showsSelectionIndicator, по умолчанию имеющего значение NO. Вы можете либо напрямую изменить значение этого свойства на YES, либо воспользоваться методом setShowsSelectionIndicator: вида выбора, чтобы включить этот индикатор:


self.myPicker.showsSelectionIndicator = YES;


Снова предположим, что мы создаем вид выбора в окончательной версии нашего приложения. Какая польза от вида выбора, если мы не можем определить, что именно пользователь выбрал в каждом из компонентов? Да, хорошо, что Apple уже позаботилась о решении этой проблемы и предоставила нам возможность спрашивать вид выбора о выбранном варианте. Вызовем метод selectedRowInComponent: класса UIPickerView и передадим индекс компонента (с нулевым основанием), а в качестве возвращаемого значения получим целое число. Это число будет представлять собой индекс с нулевым основанием, сообщающий строку, которая в данный момент выбрана в интересующем нас компоненте.

Если во время исполнения вам потребуется изменить значения, содержащиеся в вашем виде выбора, необходимо гарантировать, что вид выбора сможет перегружать данные, заменяя старую информацию новой, получаемой из источника и от делегата. Для этого нужно либо принудительно заставить все компоненты перезагрузить содержащиеся в них данные (это делается с помощью метода reloadAllComponents), либо приказать конкретному компоненту перезагрузить содержащиеся в нем данные. Во втором случае применяется метод reloadComponent:. Ему передается индекс компонента, который необходимо перезагрузить.

<p>См. также</p>

Раздел 1.2.

1.5. Выбор даты и времени с помощью UIDatePicker

<p>Постановка задачи</p>

Необходимо предоставить пользователям вашего приложения возможность выбирать дату и время. Для этого нужен интуитивно понятный и уже готовый пользовательский интерфейс.

<p>Решение</p>

Воспользуйтесь классом UIDatePicker.

<p>Обсуждение</p>

Класс UIDatePicker очень напоминает класс UIPickerView. Фактически UIDatePicker – это уже заполненный вид выбора. Хорошим примером такого вида является программа Calendar (Календарь) в iPhone (рис. 1.13).


Рис. 1.13. Вид для выбора даты показан в нижней части экрана


Для начала объявим свойство типа UIDatePicker, а потом выделим и инициализируем это свойство и добавим его в вид, в котором находится контроллер нашего вида:


#import "ViewController.h"


@interface ViewController ()

@property (nonatomic, strong) UIDatePicker *myDatePicker;

@end


@implementation ViewController



А теперь, как и планировалось, инстанцируем вид для выбора даты:


– (void)viewDidLoad{

[super viewDidLoad];

self.myDatePicker = [[UIDatePicker alloc] init];

self.myDatePicker.center = self.view.center;

[self.view addSubview: self.myDatePicker];

}


После этого запустим приложение и посмотрим, как оно выглядит (рис. 1.14).


Рис. 1.14. Простой вид для выбора даты


Как видите, по умолчанию в виде выбора даты ставится сегодняшняя дата. Начиная работать с такими инструментами, первым делом нужно уяснить, что они могут иметь различные стили оформления и режимы работы. Режим можно изменить, работая со свойством datePickerMode, тип которого – UIDatePickerMode:


typedef enum {

UIDatePickerModeTime,

UIDatePickerModeDate,

UIDatePickerModeDateAndTime,

UIDatePickerModeCountDownTimer,

} UIDatePickerMode;


В зависимости от конкретной задачи, стоящей перед вами, для режима вида выбора даты можно задать любое из значений, перечисленных в списке UIDatePickerMode. Далее по мере обсуждения данной темы мы рассмотрим некоторые из этих значений.

Теперь, когда вы успешно смогли отобразить на экране вид для выбора даты, можно попытаться получить дату, которая выведена в нем в настоящий момент. Для получения этой информации используется свойство date данного вида. Другой способ – применить метод date к виду выбора даты:


NSDate *currentDate = self.myDatePicker.date;

NSLog(@"Date = %@", currentDate);


Подобно классу UISwitch, вид для выбора даты также посылает своим целям инициирующие сообщения (Action Messages) всякий раз, когда отображаемая в виде дата изменяется. Чтобы иметь возможность реагировать на эти сообщения, получатель должен добавить себя в список целей вида выбора даты. Для этого используется метод addTarget: action: forControlEvents: следующим образом:


– (void) datePickerDateChanged:(UIDatePicker *)paramDatePicker{


if ([paramDatePicker isEqual: self.myDatePicker]){

NSLog(@"Selected date = %@", paramDatePicker.date);

}


}


– (void)viewDidLoad{

[super viewDidLoad];

self.myDatePicker = [[UIDatePicker alloc] init];

self.myDatePicker.center = self.view.center;

[self.view addSubview: self.myDatePicker];

[self.myDatePicker addTarget: self

action:@selector(datePickerDateChanged:)

forControlEvents: UIControlEventValueChanged];


}


Теперь всякий раз, когда пользователь изменяет дату, вы будете получать сообщение от вида выбора даты.

Пользуясь видом для выбора даты, можно задавать минимальную и максимальную даты, которые он способен отображать. Для этого сначала нужно переключить вид выбора даты в режим UIDatePickerModeDate, а потом с помощью свойств maximumDate и minimumDate откорректировать этот диапазон:


– (void)viewDidLoad{

[super viewDidLoad];

self.myDatePicker = [[UIDatePicker alloc] init];

self.myDatePicker.center = self.view.center;

self.myDatePicker.datePickerMode = UIDatePickerModeDate;

[self.view addSubview: self.myDatePicker];


NSTimeInterval oneYearTime = 365 * 24 * 60 * 60;

NSDate *todayDate = [NSDate date];


NSDate *oneYearFromToday = [todayDate

dateByAddingTimeInterval: oneYearTime];


NSDate *twoYearsFromToday = [todayDate

dateByAddingTimeInterval:2 * oneYearTime];


self.myDatePicker.minimumDate = oneYearFromToday;

self.myDatePicker.maximumDate = twoYearsFromToday;

}


Применяя два этих свойства, можно ограничить доступный пользователю диапазон выбора даты конкретными пределами, как показано на рис. 1.15. В приведенном образце кода мы позволяем пользователю задавать даты в диапазоне от года до двух лет, отсчитывая с настоящего момента.



Рис. 1.15. Минимальная и максимальная даты при работе с видом выбора даты

Если вы хотите применять вид выбора даты в качестве таймера обратного отсчета, нужно задать для этого вида режим UIDatePickerModeCountDownTimer и использовать свойство countDownDuration вида выбора даты для указания длительности обратного отсчета, задаваемой по умолчанию. Например, если вы желаете предложить пользователю такой таймер и задать в качестве периода ведения обратного отсчета 2 минуты, нужно написать следующий код:


– (void)viewDidLoad{

[super viewDidLoad];

self.view.backgroundColor = [UIColor whiteColor];

self.myDatePicker = [[UIDatePicker alloc] init];

self.myDatePicker.center = self.view.center;

self.myDatePicker.datePickerMode = UIDatePickerModeCountDownTimer;

[self.view addSubview: self.myDatePicker];

NSTimeInterval twoMinutes = 2 * 60;

[self.myDatePicker setCountDownDuration: twoMinutes];

}


Результат показан на рис. 1.16.


Рис. 1.16. Таймер обратного отсчета в виде для выбора даты, где стандартная длительность обратного отсчета равна 2 минутам

1.6. Реализация инструмента для выбора временных рамок с помощью UISlider

<p>Постановка задачи</p>

Необходимо дать пользователям возможность указывать определенное значение из диапазона и предоставить для этого удобный в применении и интуитивно понятный пользовательский интерфейс.

<p>Решение</p>

Используйте класс UISlider.

<p>Обсуждение</p>

Вероятно, вы уже знаете, что такое слайдер. Пример слайдера показан на рис. 1.17.


Рис. 1.17. В нижней части экрана находится слайдер, регулирующий уровень громкости


Чтобы создать слайдер, нужно инстанцировать объект типа UISlider. Создадим слайдер и поместим его на вид нашего контроллера. Начнем с файла реализации нашего контроллера вида:


#import "ViewController.h"


@interface ViewController ()

@property (nonatomic, strong) UISlider *slider;

@end


@implementation ViewController



Теперь рассмотрим метод viewDidLoad и создадим сам компонент-слайдер. В этом коде мы будем создавать слайдер, позволяющий выбирать значения в диапазоне от 0 до 100. По умолчанию ползунок слайдера будет установлен в среднем значении шкалы:


– (void)viewDidLoad{

[super viewDidLoad];


self.slider = [[UISlider alloc] initWithFrame: CGRectMake(0.0f,

0.0f,

200.0f,

23.0f)];

self.slider.center = self.view.center;

self.slider.minimumValue = 0.0f;

self.slider.maximumValue = 100.0f;

self.slider.value = self.slider.maximumValue / 2.0;

[self.view addSubview: self.slider];

}

Диапазон слайдера совершенно не зависит от его внешнего вида. С помощью указателя диапазона мы приказываем слайдеру вычислить его (слайдера) значение, основываясь на относительной позиции в рамках диапазона. Например, если для слайдера задан диапазон от 0 до 100, то когда ползунок слайдера расположен у левого края шкалы, свойство слайдера value равно 0, а если ползунок стоит у правого края, оно равно 100.

Как будут выглядеть результаты? Теперь вы можете запустить приложение в эмуляторе (рис. 1.18).


Рис. 1.18. Обычный слайдер в центре экрана


Для получения желаемых результатов мы использовали несколько свойств слайдера. Что это за свойства?

• minimumValue – задает минимальное значение диапазона, поддерживаемого слайдером.

• maximumValue – задает максимальное значение диапазона, поддерживаемого слайдером.

• value – текущее значение слайдера. Это свойство доступно как для чтения, так и для изменения, то есть вы можете как считывать это значение, так и записывать в него информацию. Если вы хотите, чтобы при перемещении ползунка в это значение включалась анимация, то можно вызвать метод слайдера setValue: animated: и передать YES в качестве значения параметра animated.

Ползунок слайдера называется также бегунком. Если вы хотите получать событие всякий раз, когда передвигается ползунок слайдера, нужно добавить ваш объект, которому требуется информация о таких событиях, в качестве цели слайдера с помощью относящегося к слайдеру метода addTarget: action: forControlEvents::


– (void) sliderValueChanged:(UISlider *)paramSender{


if ([paramSender isEqual: self.mySlider]){

NSLog(@"New value = %f", paramSender.value);

}


}

– (void)viewDidLoad{

[super viewDidLoad];

self.view.backgroundColor = [UIColor whiteColor];

self.mySlider = [[UISlider alloc] initWithFrame: CGRectMake(0.0f,

0.0f,

200.0f,

23.0f)];

self.slider.center = self.view.center;

self.slider.minimumValue = 0.0f;

self.slider.maximumValue = 100.0f;

self.slider.value = self.slider.maximumValue / 2.0;

[self.view addSubview: self.slider];


[self.slider addTarget: self

action:@selector(sliderValueChanged:)

forControlEvents: UIControlEventValueChanged];

}


Если сейчас запустить приложение в эмуляторе, вы увидите, что вызывается целевой метод sliderValueChanged: и это происходит всякий раз, как только перемещается ползунок слайдера. Возможно, именно этого вы и хотели. Но в некоторых случаях уведомление требуется лишь тогда, когда пользователь отпустил ползунок, установив его в новом значении. Если вы хотите дождаться такого уведомления, установите для свойства слайдера continuous значение NO. Если это свойство имеет значение YES (задаваемое по умолчанию), то на цели слайдера вызов будет идти непрерывно все то время, пока движется ползунок.

В SDK iOS разработчик также может изменять внешний вид слайдера. Например, ползунок может иметь нестандартный вид. Чтобы изменить внешний вид ползунка, просто пользуйтесь методом setThumbImage: forState: и передавайте нужное изображение, а также второй параметр, который может принимать одно из двух значений:

• UIControlStateNormal – обычное состояние ползунка, когда его не трогает пользователь;

• UIControlStateHighlighted – изображение, которое должно быть на месте ползунка, когда пользователь начинает его двигать.


Я подготовил два изображения: одно для стандартного состояния ползунка, а другое – для активного (затронутого) состояния. Добавим их к слайдеру:


[self.slider setThumbImage: [UIImage imageNamed:@"ThumbNormal.png"]

forState: UIControlStateNormal];

[self.slider setThumbImage: [UIImage imageNamed:@"ThumbHighlighted.png"]

forState: UIControlStateHighlighted];


Теперь взглянем, как выглядит в эмуляторе неактивный слайдер (рис. 1.19).


Рис. 1.19. Слайдер со специально оформленным ползунком

1.7. Оформление UISlider

<p>Постановка задачи</p>

Вы используете компонент графического интерфейса UISlider, оформленный по умолчанию, и хотите на свой вкус изменить его внешний вид.

<p>Решение</p>

Либо измените оттенки различных частей слайдера, либо подготовьте для его элементов собственные рисунки.

<p>Обсуждение</p>

Apple проделала огромную работу, предоставив нам в iOS SDK методы для оформления компонентов пользовательского интерфейса. В частности, оформление может быть связано с изменением оттенков различных частей компонента в интерфейсе. Схема, демонстрирующая компонентный состав пользовательского интерфейса, приведена на рис. 1.20.


Рис. 1.20. Различные компоненты UISlider


Для каждого из этих компонентов UISlider существуют метод и свойство, позволяющие изменять внешний вид слайдера. Простейшими из этих свойств являются те, которые позволяют изменять оттенок соответствующего компонента:

• minimumTrackTintColor – это свойство задает оттенок для области минимальных значений;

• thumbTintColor – это свойство, как понятно из его названия, задает цвет ползунка;

• maximumTrackTintColor – это свойство задает оттенок для области максимальных значений.

Все эти свойства относятся к типу UIColor.

В следующем образце кода мы инстанцируем UISlider и помещаем его в центре вида, расположенного в нашем контроллере. Кроме того, здесь мы задаем цвет для области минимальных значений (красный), цвет ползунка (черный) и цвет области максимальных значений (зеленый):


– (void)viewDidLoad{

[super viewDidLoad];


/* Создаем слайдер */

self.slider = [[UISlider alloc] initWithFrame: CGRectMake(0.0f,

0.0f,

118.0f,

23.0f)];

self.slider.value = 0.5;

self.slider.minimumValue = 0.0f;

self.slider.maximumValue = 1.0f;

self.slider.center = self.view.center;

[self.view addSubview: self.slider];


/* Задаем оттенок для области минимальных значений */

self.slider.minimumTrackTintColor = [UIColor redColor];


/* Задаем оттенок для ползунка */

self.slider.maximumTrackTintColor = [UIColor greenColor];


/* Задаем цвет для области максимальных значений */

self.slider.thumbTintColor = [UIColor blackColor];

}


Если вы теперь запустите получившееся приложение, то увидите примерно такую картину, как на рис. 1.21.


Рис. 1.21. Оттенки всех составных частей слайдера изменены


Иногда вам может потребоваться более полный контроль над тем, как слайдер будет выглядеть на экране. При этом одних только оттенков может быть недостаточно. Именно поэтому Apple предлагает и другие способы изменения внешнего вида слайдера, позволяя вам задавать изображения для различных его компонентов. Речь идет о следующих изображениях.

• Изображение для минимального значения. Это изображение, которое будет находиться за пределами слайдера у его левого края. По умолчанию такое изображение не предоставляется, поэтому вы его и не увидите, если просто создадите в виде новый слайдер. Вы можете задать такое изображение, чтобы подсказывать пользователю, как трактуется минимальное значение в контексте данного слайдера. Например, в приложении, с помощью которого пользователь может увеличивать или уменьшать яркость экрана, минимальному значению может соответствовать картинка в виде потухшей лампочки. Она показывает, что чем дальше пользователь будет перемещать ползунок в сторону минимального значения (влево), тем более тусклым будет становиться экран. Чтобы изменить это изображение, воспользуйтесь относящимся к слайдеру методом экземпляра setMinimumValueImage:. Это изображение должно иметь по 23 точки в высоту и в ширину. При работе с сетчатым дисплеем используйте такое же изображение, только вдвое крупнее.

• Изображение для области минимальных значений. Это изображение, которое будет соответствовать колее слайдера левее от ползунка. Чтобы изменить это изображение, воспользуйтесь относящимся к слайдеру методом экземпляра setMinimumTrackImage: forState:. Это изображение должно иметь 11 точек в ширину и 9 точек в высоту и допускать изменение размера (подробнее о таких изображениях см. в разделе 17.5).

• Изображение для ползунка. Изображение ползунка – это единственный движущийся элемент слайдера. Чтобы изменить это изображение, воспользуйтесь относящимся к слайдеру методом экземпляра setThumbImage: forState:. Это изображение должно иметь 23 точки в высоту и 23 точки в ширину.

• Изображение для области максимальных значений. Это изображение будет соответствовать той части колеи слайдера, которая находится справа от ползунка. Чтобы изменить это изображение, воспользуйтесь относящимся к слайдеру методом экземпляра setMaximumTrackImage: forState:. Это изображение должно иметь 11 точек в ширину и 9 точек в высоту и допускать изменение размера (подробнее о таких изображениях см. в разделе 17.5).

• Изображение для максимального значения. Это изображение, которое будет находиться у правого края слайдера. Оно должно напоминать изображение, соответствующее минимальному значению, но, разумеется, трактуется противоположным образом. Вернувшись к примеру с яркостью лампочки, допустим, что справа от колеи с ползунком у нас изображена яркая лампочка, испускающая лучи. Так пользователю будет понятно, что чем дальше вправо он передвигает ползунок, тем ярче становится экран. Чтобы изменить это изображение, воспользуйтесь относящимся к слайдеру методом экземпляра setMaximumValueImage:. Это изображение должно иметь 23 точки в высоту и столько же в ширину.

Изображения, предоставляемые вами для областей максимальных и минимальных значений, должны при необходимости изменять размер. Подробнее о таких изображениях рассказано в разделе 17.5.

Для этого упражнения я создал пять уникальных изображений – по одному для каждого компонента слайдера. Убедился, что изображения для областей с максимальными и минимальными значениями поддерживают изменение размера. Оформляя этот слайдер по своему усмотрению, я стремлюсь создать у пользователя впечатление, что он меняет температуру в комнате: при перемещении ползунка влево становится прохладнее, вправо – теплее. Далее приведен код, создающий слайдер и оформляющий различные его компоненты:


#import "ViewController.h"


@interface ViewController ()

@property (nonatomic, strong) UISlider *slider;

@end


@implementation ViewController


/*

Этот метод возвращает изображение переменного размера для области слайдера, содержащей минимальные значения

*/

– (UIImage *) minimumTrackImage{

UIImage *result = [UIImage imageNamed:@"MinimumTrack"];

UIEdgeInsets edgeInsets;

edgeInsets.left = 4.0f;

edgeInsets.top = 0.0f;

edgeInsets.right = 0.0f;

edgeInsets.bottom = 0.0f;

result = [result resizableImageWithCapInsets: edgeInsets];

return result;

}


/*

Аналогично предыдущему методу этот возвращает изображение переменного размера для области слайдера, содержащей максимальные значения

*/

– (UIImage *) maximumTrackImage{

UIImage *result = [UIImage imageNamed:@"MaximumTrack"];

UIEdgeInsets edgeInsets;

edgeInsets.left = 0.0f;

edgeInsets.top = 0.0f;

edgeInsets.right = 3.0f;

edgeInsets.bottom = 0.0f;

result = [result resizableImageWithCapInsets: edgeInsets];

return result;

}


– (void)viewDidLoad{

[super viewDidLoad];


/* Создаем слайдер */

self.slider = [[UISlider alloc] initWithFrame: CGRectMake(0.0f,

0.0f,

218.0f,

23.0f)];

self.slider.value = 0.5;

self.slider.minimumValue = 0.0f;

self.slider.maximumValue = 1.0f;

self.slider.center = self.view.center;

[self.view addSubview: self.slider];


/* Изменяем изображение для минимального значения */

[self.slider setMinimumValueImage: [UIImage imageNamed:@"MinimumValue"]];


/* Изменяем изображение для области минимальных значений */


  • Страницы:
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15