Styling iOS apps: how we stretch fonts, colors, and images

  • Tutorial


In the course of working on a mobile application, developers receive layouts, fonts and images from designers. Transforming these materials into a code is a tedious task, and in the process, everyone tries to invent his own bicycle. To keep projects clean, we adopted a unified convention on working with styles.

Color scheme




This is the first candidate for code generation. We decided to send a list of colors in a format that is easy to type with hands and just as easy to parse to generate the UIColor category.
Designers assemble a simple text file #COLOR - TITLE. Developers include this file in the project, and the script generates files with code and palette in the CLR format before compilation. This palette can be used to work with Interface Builder.

#B3ED3B green#5ABBF2 blue#FD86C9 pink#FD4737 red#FEAE30 orange




Nuances


There are several problems with using the palette.

The first is that the Colors panel does not update the list of available palettes, as well as their contents. Each application in OS X can have its own copy of the Colors panel, and in order for the newly generated palette to be added to the panel or updated, you need to restart the entire application.
Therefore, we wrote a small plugin for Xcode, which after each build distorts all custom palettes in the Colors panel.

The second problem comes from the format in which Interface Builder stores the color set for the item:

<colorkey="textColor"red="0.29803922772407532"green="0.85098040103912354"blue="0.39215686917304993"alpha="1"colorSpace="deviceRGB"/>


Bare numbers, and not a single hint of the palette - which means that if we update it, everything will remain the same in the xib / storyboard. Unfortunately, we could not solve this problem, but we identified two possible approaches:

  1. Do not use palettes. For all items, hang Outlets and paint with code. The problem of irrelevant representation of elements in Interface Builder is partially solved by IBDesignable technology.
  2. Use the solution in the forehead. If you need to replace the color, go through the xml that stands behind each xib or storyboard, and replace the matches with a new color. Like, for example, here . Not the most elegant solution, but it works.

You can find our utility for generating the UIColor category and the plugin for reloading the palette list of the Colors panel on GitHub - RMRColorTools-iOS .

With the plugin everything is simple. You need to clone the repository and run the target RMRRefreshColorPanelPlugin, and then restart Xcode.

To automatically generate a UIColor on every build, on the Build Phases tab, add a Run Script Phase with a call to the RMRHexColorGen utility.





Fonts




We wanted to have one entry point for working with fonts, so based on the stylesheet, we implement the UIFont category:

@implementationUIFont (RMRFonts)
+ (UIFont *)rmr_regularFontOfSize:(CGFloat)size
{
   return [UIFont fontWithName:@"HelveticaNeue"
                          size:size];
}
+ (UIFont *)rmr_mediumFontOfSize:(CGFloat)size
{
   return [UIFont fontWithName:@"HelveticaNeue-Medium"
                          size:size];
}
#pragma mark - Style fonts
+ (UIFont *)rmr_fontA1 { return [self rmr_mediumFontOfSize:17.f]; }
+ (UIFont *)rmr_fontA2 { return [self rmr_regularFontOfSize:17.f]; }
+ (UIFont *)rmr_fontB1 { return [self rmr_regularFontOfSize:14.f]; }
+ (UIFont *)rmr_fontB2 { return [self rmr_regularFontOfSize:11.f]; }
+ (UIFont *)rmr_fontB3 { return [self rmr_mediumFontOfSize:10.f]; }
@end


Hanging on each label outlet to install the font - even does not sound very. Therefore, we have implemented the UILabel subclass with setting the style during initialization. The style is set in a specific subclass.

@implementationRMRLabel
- (void)prepareAppearance
{
   // Абстрактный метод для переопределения наследниками
}
- (instancetype)initWithFrame:(CGRect)frame
{
   if (self = [super initWithFrame:frame]) {
       [self prepareAppearance];
   }
   returnself;
}
- (void)awakeFromNib
{
   [self prepareAppearance];
}
@end@implementationRMRLabelA1
- (void)prepareAppearance { self.font = [UIFont rmr_fontA1]; }
@end


This allows you to define an installed style by specifying a particular UILabel subclass in Interface Builder.

Profit from such a scheme (Font ⇢ UlLabel ⇢ IB) - if you need to change the style, then all the work will be localized in a single file.

Images


In Xcode 6, we were able to use vector images in pdf format. Together with the tint color and the ability to use images as a template, we get a simple mechanism that allows you to forget about dancing with resources, if it took a half tone to change the color of icons.




Conclusion


The colors were generated, the fonts were graded, the icons were repainted. These simple mechanisms allowed us to reduce the number of errors and simplify the interaction between designers and developers.


See also:
Architectural design of mobile applications: part 2
Architectural design of mobile applications: part 1
What could be simpler buttons?

Also popular now: