Tuesday, October 29, 2013

How To: Convert Your App Into Flat Design (iOS7) Easily

What's up?

The sky.













iOS7 Flat Design. Many thought flat design is easy. But after trying to design it myself I find that flat design is WAY HARDER than Skeumorphic design. With flat design, every single aspect of the design MUST come together in perfect harmony to produce a cool looking and beautiful interface.

As I am updating my apps to the flat design, I created a few custom methods that makes converting apps into flat design a walk in the park (Ok, walking in the park is probably not easy, and not safe either, you'd get mugged, or might step on dog's poo, etc, but you get my meaning :P)

I made a fake Application with the normal old design. The app doesn't do anything. It just shows  some controls on it. Here how it looks like:
Now, with a single loop we will turn all these into a flat design User Interface. It's like magic :D

Since we want to be able to call the method to convert all controls into flat designed controls, we better create a class, so that we can simply call the class from other ViewControllers. For me, I have one class that contains all the general and common methods, it is called "CommonMethods.h and .m".

So how are we going to do this?

The secret to this is to create images ON THE FLY and use it as "custom" backgrounds for each of the controls. So in each of your existing Viewcontrollers, you only need to call these loops in the viewDidLoad method:

    
for(UIView *v in [self.view subviews]) {
        if ([v isKindOfClass:[UIButton class]]) {
            [CommonMethods createCustomBtn:(UIButton *)v];
        }
        
        if ([v isKindOfClass:[UISegmentedControl class]]) {
            [CommonMethods createCustomSegmented:(UISegmentedControl *)v];
        }
        
        if ([v isKindOfClass:[UISlider class]]) {
            [CommonMethods createCustomSlider:(UISlider *)v];
        }
    }

Isn't that cool? Let's take a look at one of the CommonMethods' custom class method - createCustomBtn. This method is custom made - you decide the name of the method and what it does. In this case, we name it createCustomBtn because we want it to uh.. well, create a custom button for us. :P

Flat design is great because, it is simple. There are no fancy shadows, no fancy textures, there are just colors. And sometimes simple gradients. Hence we can make use CoreGraphics to create these designs dynamically and apply to each controls on the fly. Genius? I know. Thanks.

So for all buttons, what we want to do is create individual buttons images and then apply it to them. To create a rectangle gradient, we use the following code (read the comments for explanation):


    
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); // creates an RGB color space.
    
    // gradient colors from top to bottom (only 2 colors allowed)
    CGFloat colors[] =
    {
        133.0 / 255.0, 149.0 / 255.0, 96.0 / 255.0, 1.00,
        90.0 / 255.0,  109.0 / 255.0, 49.0 / 255.0, 1.00,
    };
    // initiate the gradient
    CGGradientRef gradient = CGGradientCreateWithColorComponents(rgb, colors, NULL, sizeof(colors)/(sizeof(colors[0])*4));
    CGColorSpaceRelease(rgb);
    
    // start image context (so we can draw on it) with the same size as the button
    UIGraphicsBeginImageContext(myButton.frame.size);
    
    UIImage *btnImage;
       
    // get the context for CoreGraphics
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    
    // start and end point of gradient
    CGPoint startPoint = CGPointMake(0,0);
    CGPoint endPoint = CGPointMake(0, myButton.frame.size.height);
    
    // DRAW the gradient 
    CGContextDrawLinearGradient(ctx, gradient, startPoint, endPoint, kCGGradientDrawsBeforeStartLocation);
 
    // make image out of bitmap context
    btnImage = UIGraphicsGetImageFromCurrentImageContext();
    
    // free the context
    UIGraphicsEndImageContext();


Easy right? Now that we got the rectangular colored gradient as an image, we then can apply this image as the button's background image. Also, if we want the rounded corner on the button, we set the button layer's cornerRadius property to 10.0 or other float values. Remember to setClipsToBound to YES otherwise the radius will not work.


    [myButton setBackgroundImage:btnImage forState:UIControlStateNormal];
// you can also create another image of different color using the code above and
// apply it to other states of the button like UIControlStateSelected
    myButton.clipsToBounds = YES;
    myButton.layer.cornerRadius = 5.0;
    // Change font to iOS7 common font and color to white
    UIFont *myFont = [UIFont fontWithName:@"Helvetica Neue" size:18];
    [[myButton titleLabel] setFont:myFont];
    [[myButton titleLabel] setTextColor:[UIColor whiteColor]];


DONE! Woah? So easy. What you do is just customize your button as you like once in CommonMethods.m and call the loop in all viewController's viewDidLoad method. And all your buttons now are Flat Designed!



Open up CommonMethods.m to see other customizations. And here is the flat designed new User Interface! Cool eh?

What's more cool, is that now your app bundle doesn't even have ANY user interface images. Non of that btn.png, btn@2.png, btn@2x~ipad.png, btn~ipad.png ANYMORE!

Based on my example, you could convert most objects the same way (but you gotta write code by yourself).



This is an easy way for us noobs to convert our apps' interface. But if you are writing a new app, the way to go is subclassing your controls. But that, is another topic altogether.

So that's all and good luck updating your app to flat design app!.

Oh yeah, you need to choose colors carefully for a flat design - This site http://flatuicolors.com is really cool where you can find Flat Colors easily.