Подтвердить что ты не робот

Каков рекомендуемый метод стилизации приложения iOS?

Каков рекомендуемый метод стилизации приложения iOS? Например, если есть несколько меток или текстовых представлений, как можно обновлять стиль/цвет шрифта в одном месте, обновите стиль/цвет во всех других местах?

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

4b9b3361

Ответ 1

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

Styles.h

#define kFontSize 14
#define kFontFamily @"Helevetica"

контроллер

#import "Styles.h" // at the top

myLabel.font = [UIFont fontWithName:kFontFamily size:kFontSize];

Я лично считаю, что интерфейс Builder - лучший способ стиля, но это напрямую отвечает на ваш вопрос.

Ответ 2

Обновление: Я бы рекомендовал начать с понимания API UIAppearance и посмотреть, насколько они соответствуют вашим потребностям. UIAppearance - удобный способ предоставления пользовательской стилизации по умолчанию атрибутов определенных элементов управления на нескольких уровнях (например, глобально или контекстно).


Мой первоначальный ответ, который предшествовал доступности UIAppearance:


так как мы работаем с объектно-ориентированным языком...

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

базовый интерфейс может принимать форму:

@protocol MONLabelThemeProtocol

- (UIFont *)labelFont;
- (UIColor *)labelTextColor;
- (UITextAlignment)labelTextAlignment;
// ...
@end

@protocol MONTableViewCellThemeProtocol

- (UIFont *)tableViewCellFont;
- (UIColor *)tableViewCellTextColor;
- (UIImage *)tableViewCellImage;
- (NSInteger)tableViewCellIndentationLevel;
- (CGFloat)tableViewCellIndentationWidth;
// ...
@end

тогда простая тема амальгамы может быть объявлена ​​следующим образом:

@interface MONAmalgamateThemeBase : NSObject
   < MONLabelThemeProtocol, MONTableViewCellThemeProtocol >
{
@protected
    /* labels */
    UIFont * labelFont;
    UIColor * labelTextColor;
    UITextAlignment labelTextAlignment;
    // ...
    /* table view cells */
    UIFont * tableViewCellFont;
    UIColor * tableViewCellTextColor;
    UIImage * tableViewCellImage;
    NSInteger tableViewCellIndentationLevel;
    CGWidth tableViewCellIndentationWidth;
    // ...
}

@end

в этом примере, амальгамат определяет геттеры и dealloc и ожидает, что подклассы инициализируют переменные экземпляра. вы также можете поддерживать ленивую инициализацию, если время инициализации велико (например, использует много изображений).

тогда специализация могла бы иметь вид:

@interface MONDarkTheme : MONAmalgamateThemeBase
@end

@implementation MONDarkTheme

- (id)init
{
    self = [super init];
    if (nil != self) {
        labelFont = [[UIFont boldSystemFontOfSize:15] retain];
        labelTextColor = [[UIColor redColor] retain];
        // and so on...
    }
    return self;
}

// ...

@end

/* declare another theme and set it up appropriately */
@interface MONLightTheme : MONAmalgamateThemeBase
@end

затем просто повторно используйте экземпляры темы (например, MONDarkTheme) во всем приложении, чтобы стилизовать представления. если у вас много тем или они не являются тривиальными для построения, тогда вам может понадобиться создать коллекцию для тем (диспетчер тем). амальгамат также может принимать параметр, например, init с темой, если ваши потребности просты. вы даже можете настроить объекты для регистрации на изменения в темах, если вам нужна поддержка динамических изменений.

Наконец, вы можете создать приложение для простой темы, чтобы сделать жизнь проще - например:

@interface UILabel (MONThemeAdditions)

- (void)mon_applyMONLabelTheme:(id<MONLabelTheme>)theme;

@end

@implementation UILabel (MONThemeAdditions)

- (void)mon_applyMONLabelTheme:(id<MONLabelTheme>)theme
{
    assert(theme);
    if (nil == theme) return;
    self.font = [theme labelFont];
    self.textColor = [theme labelTextColor];
    self.textAlignment = [theme labelTextAlignment];
}

@end

Ответ 3

Честно говоря, лучший способ сделать это - использовать Interface Builder. Хотя может показаться приятным изменить одну константу где-то в коде и иметь все стили изменения приложения, это никогда не будет так выработано. Вот мои рассуждения:

1) Разработчики не пишут код интерфейса, а также конструктор интерфейса. Разработчик интерфейса - это инструмент, который был усовершенствован, протестирован и запущен в течение многих лет. Он предлагает шрифты, выравнивание текста, тень и т.д. Он обратно совместим, поскольку вы когда-либо хотели. Это обеспечивает очень простой способ для любого числа разработчиков и дизайнеров вникать и работать над чем-то очень простым.

2) Всегда есть краевые случаи, которые вам придется учитывать. Конечно, простая константа будет делать то, что вы хотите больше всего времени, но в конечном итоге вам придется что-то взломать здесь и подкрасться там. "Простой" код интерфейса, который вы написали для начала, будет расти, расти и расти. Другие разработчики должны будут поддерживать этот код. Вы должны будете поддерживать этот код. Вам придется записывать и исправлять ошибки, настраивать их, кроме этого, и т.д. Это неизбежно станет дымящейся кучей беспорядка.

3) Чем больше кода вы пишете, тем больше ошибок вы пишете. Конструктор интерфейсов предназначен для создания "внешнего вида" большинства приложений для iOS. Используй это. Не становитесь слишком умными.

Примечание: Я понимаю, что Interface Builder не может делать все для всех приложений. Бывают случаи, когда кодирование интерфейса является единственным решением. Этот ответ - просто общая "лучшая практика", которую я использую в большинстве своих приложений.

Ответ 4

Как и идея Alex, вы можете создать статический класс под названием ThemeManager:

typedef enum
{
    defaultStyle,
    redStyle,
} ThemeStyles;

@interface Level : NSObject
{
    ThemeStyles currentTheme;
}

Все классы, которые могут быть тематическими, будут импортировать ThemeManager. Затем вы можете создавать такие методы, как:

+ (UIColor*) fontColor;

Какие другие классы вызывали бы, когда им нужен цвет для их шрифта. Затем, если вы хотите изменить темы, вы можете реализовать fontColor как:

+ (UIColor*) fontColor
{
    switch (currentTheme)
    {
        case defaultStyle:
        return [UIColor blackColor];
        case redStyle:
        return [UIColor redColor];
    }
}

Если вы хотите изменить тему, вы можете заставить ThemeManager реализовать такой метод, как:

+ (void) changeTheme:(ThemeStyles)newTheme
{
    currentTheme = newTheme;
}

Ответ 5

Вы можете использовать стороннюю абстракцию UIAppearance:

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

Ответ 6

Я использую plists. Так же, как я локализую строки, я использую ту же процедуру для изменения тем. Я закодировал синглтон, загружающий текущий слой темы и резервный слой. Затем я заменяю имена ресурсов ключами и макрофункциями, которые вытаскивают имя реального ресурса из singleton.

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

Ответ 7

Вам может потребоваться посмотреть эту библиотеку. Он поддерживает несколько тем/скинов "на лету". В настоящее время поддерживает изображения и цвета. Поддержка шрифтов будет добавлена ​​в будущем.

https://github.com/charithnidarsha/MultiThemeManager