Creating a fun iPhone App called “Bearded” – Part 1

featured-image

Tis the season to be goofy! And since it’s that merry time of the year I thought it would be fun to create an app where you could add Santa’s beard to any photo and share it. I call it “Bearded”.

What You Need

Besides a Mac and an iPhone, you will need basic iOS programming skills. Don’t have them? Fear not, we provide an excellent iPhone programming course taught by none other than yours truly. Head on over to teamtreehouse.com.

Preview

To get you all excited about this tutorial here’s a preview of what the app can do.

[youtube http://www.youtube.com/watch?v=e7JD3BC_qmI&w=640&h=360]

Interface Design

Hope you have your coffee or tea because you need to be awake for this one! Ok, let’s dive right in. Open up Xcode and create a new Single View application template. Make sure you select the options for Use Storyboard and Use Automatic Reference Counting.

Once you have created your project it should look something like the screenshot below with a single app delegate and a view controller.

Project Summary

At the core of this application are two image views (UIImageView), one for the photo and the other for Santa’s beard. While the photo image view will remain in a fixed position, Santas beard will have gestures to enable manipulation of size and position.

Open up the storyboard and add two image views.
Image Views

Create IBOutlets for both the image views.
Creating IBOutlets

Before going any further we need to turn off Autolayouts. “But why?”, you ask. “It’s the best thing in Xcode 4.5″. Well, true but it has a bad habit of automatically creating constraints when they’re not called for. Besides, our app is way too simple to need any constraining. So how do you turn off Autolayout? Simple, click anywhere on the canvas and then select the File inspector in the Utility area. Somewhere down the middle you will notice a checkbox saying ‘Use Autolayout’, un-check it.

Disable Autolayout

While we have the storyboard open let’s go ahead and finish up the interface. We need to add a toolbar with two buttons. One to capture the photo and the other for sharing the finished image. To accomodate the toolbar we will need to reduce the height of the Photo image view by 44px (548 – 44 = 504) because the height of the toolbar is 44px.

Add a toolbar towards the bottom. After the first button, add a Flexible Space bar and then another bar button item. Your interface should now look something like this:

Adding a toolbar

Want to make your design more festive? Why not add a tint color to your toolbar? The identifiers for the two buttons are Camera and Action respectively.

Finally, I’ve created two images:

  1. A default image for the Photo view (download image)
  2. The beard image (download image)

Add both images to your project and select them as the default image for each of the image views.

Adding default images

Adding Gestures

We want the user to be able to move the beard around and size it to fit their photo and that’s where the gesture recognizers come in handy.

UIGestureRecognizer is an abstract base class that has been part of the iOS SDK since version 3.2. It’s an abstract class because it has concrete subclasses for recognizing specific gestures. We will be using two gesture recognizers:

  • UIPinchGestureRecognizer: The pinch gesture is achieved using two fingers. When the fingers are brought closer to each other it is percieved as zooming-out and the reverse is zooming-in. In our case, we will make the beard image larger or smaller based on the distance between the two fingers.
  • UIPanGestureRecognizer: The panning or dragging gesture is achieved using one or more fingers. We will use this gesture to move the beard around for placement.

We will add both the gesture recognizers to the viewDidLoad method of our THViewController.m.

- (void)viewDidLoad
{
    [super viewDidLoad];

    UIPinchGestureRecognizer *pinchGestureRecognizer =
    [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchZoomBeard:)];
    pinchGestureRecognizer.delegate = self;
    [self.beardView addGestureRecognizer:pinchGestureRecognizer];

    UIPanGestureRecognizer  *panGestureRecognizer =
    [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panBeard:)];
    panGestureRecognizer.maximumNumberOfTouches = 1;
    panGestureRecognizer.delegate = self;
    [self.beardView addGestureRecognizer:panGestureRecognizer];
}

The gesture recognizers use the Target-Action design pattern. The reason we are setting the panGestureRecognizer.maximumNumberOfTouches to 1 so that the two gestures don’t interfere with each other. We want to make sure that when there are two fingers the pinch gesture is triggered and when there is only one finger present then the pan gesture is triggered.

Next we implement the two selectors pinchZoomBeard and panBeard.

- (void) pinchZoomBeardView:(UIPinchGestureRecognizer *)sender {

    UIView *beard = [sender view];

    // The scale factor between the two fingers
    CGFloat factor = [sender scale];

    // Apply transformation only for the beginning or changing states
    if (sender.state == UIGestureRecognizerStateBegan || sender.state == UIGestureRecognizerStateChanged )  {

        // Apply an affine transformation based on the factor
        beard.transform = CGAffineTransformMakeScale(factor, factor);

    }    
}

The CGAffineTransformMakeScale function returns a CGAffineTransform struct to scale a coordinate system which is used by Quartz to scale the coordinates of a point (x,y).

Panning or dragging is a bit more involved because you have to capture the movement of the finger over time relative to the coordinate system of a specific view.

- (void) panBeardView:(UIPanGestureRecognizer *)sender {
    UIView *beard = [sender view];      

    if ([sender state] == UIGestureRecognizerStateBegan || [sender state] == UIGestureRecognizerStateChanged) {

        // Get the panning move point relative to the parent view
        CGPoint translation = [sender translationInView:[beard superview]];
        // NSLog(@"x: %1.2f, y: %1.2f",translation.x,translation.y);

        // Add it to the center point of the beard view so that it stays
        // under the finger of the user
        [beard setCenter:CGPointMake([beard center].x + translation.x, [beard center].y + translation.y)];

         // Reset the translation to reduce panning velocity
         // Removing this line will result in the beard view disappearing very quickly
        [sender setTranslation:CGPointZero inView:[beard superview]];

    }               
}

The comments in the code above explain what’s going on in each line. However, it is important to note that the method translationInView returns x,y coordinates based on time. The resulting coordinates are the distance from the origin when the panning began. However, we reset those coordinates in the third line with the setTranslation:CGPointZero method. Try uncommenting the NSLog to check the resulting values. In addition, try commenting out the setTranslation:CGPointZero line and see how it affects the panning velocity. It will help you understand the code better.

Important Note

If the beard view is not responding to gestures then it means that you do not have the user interaction property enabled. Add the following line of code to your viewDidLoad:

    self.beardView.userInteractionEnabled = YES;

To be continued..

This concludes Part 1 of a two part series. By now you should have the basic view set up and the ability to move and size your beard around the screen. If you’ve achieved this much then well done!

Still more to come! In Part 2, we will learn the following:

  • Using camera controls to take a photo or pick from the camera roll.
  • Blending or merging the photo and beard image views to create a single composite image.
  • Using the Social framework to share our beards on Facebook, Twitter and Email.
  • Complete source code.
  • Link to download and try out the app from the app store.

Free Workshops

Watch one of our expert, full-length teaching videos. Choose from HTML, CSS or WordPress.

Start Learning

Amit Bijlani

Amit is an iOS Developer who loves teaching and speaking about iOS. When not in front of a computer, he's exploring the outdoors or meditating. Follow him on Twitter: @paradoxed

Comments

8 comments on “Creating a fun iPhone App called “Bearded” – Part 1

  1. I tried following the tutorial above, but the beard image that is linked to the download is not like the one that appears in your image. When I downloaded the file it came out to be a white beard. Also, there seems to be no instructions on how to place and size the beard UIImageView. It would be great to have the right beard asset and possibly some instructions on how to place that in Interface Builder.

  2. If Steve Jobs really did contribute to this notion that you don’t have to play by the rules, then that notion Is nurtured by folks looking through the glasses with the rainbow apple tint to them. Rose wasn’t available at the time.

    And, case in point, many of Apple’s products did conform to the development cycle model… a great add, by the way. In particular, I often think of the (somewhat) parallel development of the Apple Lisa and the MacIntosh. Without rehashing the politics inside of it… two products at the same company, but one finally realizes it’s place in the market because the deals get done to manufacture more of them en masse at a lower price point. However, one gets driven by Steve Jobs from concept to production based his avoiding “business as usual” in terms of conceiving of a product, but still understanding how everyone else does business to get what he needed done in a way that put that computer in the hands of consumers like us.

    You make yourself different to put yourself on the map, but you still have to be identifiable ON the map. And for all those new product developers, playing by most of the rules wouldn’t hurt your cause. Hold up Steve Jobs and Apple as iconclasts if you must, but remember he still had to make his first decision when he and Woz had sold their first 100 Apple I computers to a store, paid off their initial debts, but their potential profits – in the form of the second 100 – were still sitting on the floor of the garage.

    It’s in moments like those that a great product idea either gets to market, or stays dusty.
    I’ve worked on a few dusty Apples in my day… but only after they’ve been sold.

  3. So why is this Steve Jobs “fault.” I don’t think there is any law that says business’s or people need to follow the methodology he used.

  4. I think Steve got early on what other people thought in other industry, e.g. Design.
    Go from the user experience first then backwards to the technology. How we achieve this validation of if the user experience was other point . Even nowadays people come from the technology to the user experiences

  5. Actually, Steve Jobs was not the originator of product development without consulting the consumer. Akio Morita, founder of Sony, makes that very clear with the introduction of the” Walkman”. At a review meeting to select new products, one of his senior managers asks him “You mean you want to make a tape recorder that doesn’t record, and doesn’t have speakers and sell it at a higher price than a product that has both features?” (Paraphrased) Marita’s response “Yes.”

    At the end of the product development meeting Morita summarize the vote “17 against, one in favor: The motion is carried. We will develop and introduce the product.” Those who are old enough to remember will know that the Walkman was just as disruptive in its time, as the iPod was later. He did not do that on every product, but he did do it on Sony’s breakthrough products.

  6. I think the answer with everything here is that it depends.

    Can you build a great product without using other products first?

    Can you build a great product without doing market research?

    There’s a million and one variables here.

    I don’t think somebody is necessarily doomed to failure merely by copying Steve Jobs’s approach to product development.

  7. Interesting blog post. In the Agile world (where I work) we hear about this a lot. (Plan-do-check-act – iterate.)

    However, I think it is also important to dare make a decision and stand fast. This “sway as the wind blows” is only about making money – short term gains. Turning 40 soon, I can surely say I want more out of my life than short term gains. I want to fall a sleep at night knowing I have created something I truly feel is great – not just followed the flow.

    So I believe it is important for people like me – at least – to be able to create something that might not be as easily measured among customers at times. Of course it doesn’t have to be that black or white. Customer input is always good.

    Using Apple as an excuse to do it, though, is perhaps not the best thing to do. Better to stand up and say it like it is – “I do it this way because I feel deeply it is the very best thing possible, it’s not rational – but emotional, and I will take full responsibility for the result”.