Статьи

iOS SDK: настройка темы UIKit

Настройка тем — отличный способ выделиться в App Store, но это не всегда легко сделать. Это руководство научит вас нескольким основным приемам настройки UIKit, которые помогут отличить ваши приложения и создать более запоминающийся пользовательский опыт.


Если вы потратили какое-то время, изучая онлайн-документацию Apple в их Центре разработки iOS , то вы наверняка ознакомились с печально известными Принципами взаимодействия с человеком (более часто упоминаемыми как «HIG»). Этот документ предоставляет разработчикам и дизайнерам приложений для iOS рекомендации о том, как пользователи ожидают взаимодействия с приложениями на платформе iOS, общие примеры использования и общие принципы UI / UX, которым необходимо следовать.

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

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


Большинство разработчиков iOS знакомы с общими атрибутами класса UIView, которые легко изменить, такими как цвет фона, размер шрифта или прозрачность. Но иногда настройка этих свойств не дает нам того результата, который нам нужен.

Итак, чтобы продемонстрировать больше практических методов настройки, мы будем работать над простым приложением для просмотра фотографий. Вот как будет выглядеть приложение без каких-либо настроек, а затем с изменениями, которые мы выполним:

До / После Демо

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

Кроме того, я настроил базовое приложение, которое мы будем использовать, которое вы можете скачать здесь . Вам не нужно беспокоиться обо всей подготовительной работе; давайте просто начнем настраивать!


С нашим подготовительным приложением у нас есть несколько основных компонентов:

  • UINavigationBar (переменная: aNavigationBar)
  • UIImageView (переменная: anImageView)
  • UILabel (переменная: aLabel)
  • UISegmentedControl (переменная: aSegmentControl)

Мы начнем с того, что заставим наш фон выглядеть немного класснее, установив фоновое изображение Чтобы сделать это, давайте добавим метод в наш класс «MTViewController» с именем «-setupUI».

Мы добавим этот метод чуть ниже наших объявлений @synthesize.

1
2
— (void)setupUI {
}

Теперь нам нужно добавить наш фоновый файл изображения в наш проект, поэтому получите файл «BG-pattern.png» из ресурсов, которые вы загрузили минуту назад, и перетащите его в наше приложение. Я создал новую группу для наших изображений пользовательского интерфейса под названием «UI Graphics».

Пользовательский Фон

Имея изображение на месте, мы можем войти в этот метод «setupUI», и нам нужно добавить только одну строку:

1
[self.view setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@»BG-pattern.png»]]];

Для того, чтобы это изменение появилось в нашем приложении, нам нужно вызвать наш метод «setupUI» из метода «viewDidLoad» нашего ViewController. Я уже добавил несколько вызовов в метод «viewDidLoad», поэтому мы можем просто добавить этот в начале:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
— (void)viewDidLoad
{
    // set up the custom UI elements
    [self setupUI];
 
    // build arrays for images and titles
    [self setupData];
     
    // start app with first segment selected
    [self didChangeSegmentControl:aSegmentControl];
     
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

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

Итак, перейдите к нашему проекту UIKitDemo, и мы выберем нашу цель (UIKitDemo). Затем перейдем на вкладку «Этапы сборки» и покажем раздел «Связать двоичные файлы с библиотеками».

Внизу мы нажимаем кнопку «+» и выбираем «QuartzCore.framework».

Добавление QuartzCore Framework

Наконец, мы должны #import Quartz в наш ViewController (MTViewController.m).

1
#import <QuartzCore/QuartzCore.h>

С Quartz на месте, мы можем начать возиться с подуровнями anImageView. Мы добавим следующее в наш метод «setupUI», чтобы добавить границу вокруг нашего ImageView:

1
2
[anImageView.layer setBorderWidth:5.0f];
[anImageView.layer setBorderColor:[[UIColor whiteColor] CGColor]];

Если мы сейчас создадим и запустим наше приложение, мы увидим аккуратную белую рамку вокруг нашего ImageView.

Граница изображения

Теперь, чтобы сделать наше изображение еще более ярким, мы можем поместить тонкую тень позади него, используя похожие методы:

1
2
3
4
5
6
[anImageView.layer setShadowRadius:5.0f];
[anImageView.layer setShadowOpacity:.85f];
[anImageView.layer setShadowOffset:CGSizeMake(1.0f, 2.0f)];
[anImageView.layer setShadowColor:[[UIColor blackColor] CGColor]];
[anImageView.layer setShouldRasterize:YES];
[anImageView.layer setMasksToBounds:NO];

Некоторые из этих команд не сразу очевидны в отношении их функции, поэтому мы рассмотрим их построчно:

1
[anImageView.layer setShadowRadius:5.0f];

Мы начинаем с установки «размытия», которое будет иметь наша тень.

1
[anImageView.layer setShadowOffset:CGSizeMake(1.0f, 2.0f)];

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

1
[anImageView.layer setShouldRasterize:YES];

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

1
[anImageView.layer setMasksToBounds:NO];

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

Попробуйте снова запустить приложение, и вы увидите красивую тень за нашим изображением.

У нас много жестких граней, поэтому давайте смягчит наш интерфейс, сделав наш UILabel (aLabel) закругленными углами.

Мы можем сделать это в том же методе «setupUI» под настройками UIImageView. Все, что нам нужно, это одна простая строка, чтобы сделать эту работу:

1
[aLabel.layer setCornerRadius:15.0f];

Теперь, последнее изменение в нашем методе «setupUI» немного повернёт наш UIImageView, что разрушит ощущение «квадрата» остальной части макета.

Мы можем сделать это с помощью еще двух строк в нижней части нашего метода «setupUI»:

1
2
CGAffineTransform transform = CGAffineTransformMakeRotation(.03f);
anImageView.transform = transform;

И это все для нашего «setupUI». Не так уж плохо только для нескольких строк кода, верно?

Изображение и этикетка Рисунок

С выпуском iOS 5 появился новый протокол для подклассов UIViews под названием «внешний вид». Этот протокол позволяет нам изменять некоторые аспекты наших стандартных компонентов UIKit по своему усмотрению — например, настраивать фоновые изображения, тени, цветовые эффекты и многое другое.

Простой пример этого — UINavigationBar. Теперь мы можем настроить пользовательские изображения для изменения наших UINavigationBars в соответствии с темами нашего приложения без каких-либо хлопот:

1
[[UINavigationBar appearance] setBackgroundImage:navBarImage forBarMetrics:UIBarMetricsDefault];

В этом случае у нас есть UIImage с именем navBarImage, который мы устанавливаем в качестве изображения по умолчанию для нашего UINavigationBar. Вызов «внешний вид» повлияет на наш класс UINavigationBar, а не только на один экземпляр. Это означает, что наши изменения будут применены ко всем UINavigationBars, которые мы используем в этом приложении.

Чтобы реализовать это изменение в нашем текущем проекте Photo Viewer, нам нужно перейти в наш класс AppDelegate (MTAppDelegate). Мы собираемся в AppDelegate, потому что хотим, чтобы наши изменения влияли на все экземпляры UINavigationBars в нашем приложении, поэтому, чтобы гарантировать, что наши изменения будут внесены, мы реализуем их сразу после открытия приложения.

Давайте начнем с добавления метода в наш класс «MTAppDelegate» сразу после наших объявлений @synthesize , как мы это делали в нашем классе «MTViewController»:

1
2
— (void)setupUI {
}

Теперь мы импортируем изображение «navBar.png» (из папки ресурсов изображения, которую вы скачали ранее).

Импортировать NavBar

Затем мы можем создать экземпляр UIImage, который мы будем использовать для нашего фона:

1
UIImage *navBarImage = [UIImage imageNamed:@»navBar.png»];

И сразу после этого мы можем сделать наш «внешний вид» вызов:

1
[[UINavigationBar appearance] setBackgroundImage:navBarImage forBarMetrics:UIBarMetricsDefault];

Прежде чем это изменение вступит в силу, нам нужно вызвать наш метод «setupUI» из application:didFinishLaunchingWithOptions: метод.

1
2
3
4
5
6
— (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [self setupUI];
 
    …
}

Вы можете запустить свое приложение сейчас — обратите внимание на темный фон в нашей UINavigationBar вверху.

Для нашего следующего трюка все немного сложнее. Мы собираемся установить пользовательские изображения для нашего UISegmentedControl. Сложность в том, что мы имеем дело не только с одним или двумя фоновыми изображениями, но вместо этого нам приходится работать с определенными разделами изображений; такие как закругленные концы, выбранные или невыбранные средние участки, разделительная линия между двумя сегментами и т. д.

Разделы UISegment

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

UISСегмент импорта

Как и UINavigationBar, который мы изменили минуту назад, нам нужно сделать две вещи, чтобы изменить наш UISegmentedControl.

  1. Создайте UIImages для наших фонов
  2. Применить UIImages для своих соответствующих государств

У меня нет достаточно времени, чтобы пошагово разбить каждое из этих действий, но я расскажу о некоторых из основных в течение минуты. А пока добавьте следующий код в ваш метод «setupUI»:

01
02
03
04
05
06
07
08
09
10
11
12
UIImage *segmentSelected =
[[UIImage imageNamed:@»segcontrol_sel.png»]
 resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 15)];
UIImage *segmentUnselected =
[[UIImage imageNamed:@»segcontrol_uns.png»]
 resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 15)];
UIImage *segmentSelectedUnselected =
[UIImage imageNamed:@»segcontrol_sel-uns.png»];
UIImage *segUnselectedSelected =
[UIImage imageNamed:@»segcontrol_uns-sel.png»];
UIImage *segmentUnselectedUnselected =
[UIImage imageNamed:@»segcontrol_uns-uns.png»];

Это создает наши UIImages и выполняет изменение размера по мере необходимости. Вы заметите это немного:

1
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 15, 0, 15)

Это позволяет нам существенно «обрезать» наш файл изображения, обрезая его по определенным полям. В этом случае мы оставляем верхнюю часть как есть, перемещая 15-элементную позицию с левой стороны, оставляя нижнюю часть как есть, и перемещая 15-элементную позицию с правой стороны. Это оставляет нам среднюю часть, которая будет расширяться до необходимой ширины, но закругленные концы останутся такими же, усиливая нашу растянутую середину.

Для получения дополнительной информации о «resizableImageWithCapInsets:» ознакомьтесь с официальной документацией Apple .

Имея размеры и готовность наших изображений, мы можем установить различные состояния нашего UISegmentedControl. Каждое из пяти добавленных нами изображений будет иметь соответствующее состояние:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
[[UISegmentedControl appearance] setBackgroundImage:segmentUnselected
                                           forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[[UISegmentedControl appearance] setBackgroundImage:segmentSelected
                                           forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
 
[[UISegmentedControl appearance] setDividerImage:segmentUnselectedUnselected
                             forLeftSegmentState:UIControlStateNormal
                               rightSegmentState:UIControlStateNormal
                                      barMetrics:UIBarMetricsDefault];
 
[[UISegmentedControl appearance] setDividerImage:segmentSelectedUnselected
                             forLeftSegmentState:UIControlStateSelected
                               rightSegmentState:UIControlStateNormal
                                      barMetrics:UIBarMetricsDefault];
 
[[UISegmentedControl appearance] setDividerImage:segUnselectedSelected
                            forLeftSegmentState:UIControlStateNormal
                               rightSegmentState:UIControlStateSelected
                                      barMetrics:UIBarMetricsDefault];

В отличие от простого UIButton, который в основном либо выбран, либо нет, наш UISegmentedControl может также проверять состояние по обе стороны от текущего сегмента, но это не слишком сложно, как только мы его освоили.


Благодаря новым функциям в iOS 5 и некоторой творческой работе с Quartz, мы можем быстро и легко заставить наши приложения выглядеть так, как нам нравится. Вот некоторые проблемы, связанные с настройкой пользовательского интерфейса:

  1. Найти хорошую графику, которой легко манипулировать.
  2. Убедитесь, что вы сосредоточены на пользовательском опыте.

Найти хорошую графику может быть относительно легко, и есть много хороших дизайнеров, готовых помочь. Иногда бывает сложнее сосредоточиться на «почему», а не только на «как» настройки пользовательского интерфейса. Цитируя фиктивного доктора Яна Малкольма в Парке Юрского периода :

[Они] были так озабочены тем, могут ли они, что не переставали думать, стоит ли им.

Как всегда, выходите, пробуйте новые вещи, настраивайте настройки и исследуйте множество других способов настройки интерфейсов iOS!