Monday, November 8, 2010

Creating Basic Animations on iPhone


Creating Basic Animations on iPhone


Posted in: 

One of the cool and easy features in Cocoa is animation. Today I am going to show you how to do a couple basic animations using Cocoa Touch for the iPhone. The animation that we are going to create will do two things: move and resize an object on the screen depending on where you touch it.
Before we get started if you haven't created any code for the iPhone yet I suggest you check out our Absolute Beginner's Guide. I also need to give props to the Stanford iPhone Development class, Alan Cannistraro did a demo with basic move animation.
Below is a short video of the application we are going to build. As mentioned earlier there are two things you can do. If you do a single click it will move the inner view to the click location. A double touch will resize the view and move it. The application will create a box from the two clicks and that will create the frame for the view.
Well, let's dig in. The first thing we need to do is create our project. I created a simple Window-Based Application and then we are going to add a view to our application. To do this we open our MainWindow.xib in Interface Builder, you can do this by double clicking on it. Once we have Interface Builder open we are going to open the Library window (Tools > Library). One of the items in there will be the View component, drag it into the main Window. Use the image below for reference.
The main view needs to be told that we are going to allow multiple simultaneous touches, this is set in the Attributes Inspector (Tools > Attributes Inspector). At the bottom there is Multiple Touch, make sure it is selected.
We also need to drag a second view to inside the first view. This second view is the one that is going to move and resize. The second view needs to have a few properties set on it, mainly it's size, color, and starting position. You need to bring up the Size Inspector (Tools > Size Inspector) then you can set the size and position - I went with position 0, 0 and size of 30, 30. Also in the Attributes Inspector uncheck User Interaction Enabled.
The next thing to do is create a custom UIView subclass. I named mine TouchView, this is where we are going to put all our code for this tutorial.
In TouchView.h we need to add a single instance variable for our small inner view that we are going to move and resize. The variable has to be tagged as an IBOutlet so we can connect it to our view in Interface Builder. Our header file ends up looking like the following.
#import <UIKit/UIKit.h>

@interface TouchView : UIView {
  IBOutlet UIView *strechView;
}

@end
In order for the view in Interface Builder to be associated with our custom class we need to set the class name of the view. This is done in Interface Builder by selecting our main view and opening Identity Inspector. At the very top is a the Class input, just enter TouchView.
Now we need to go back to Interface Builder and attach our little view to our instance variable. This is done by holding the Control button and clicking on the main view and dragging to our small view. A popup will show the possible options to connect to, one should be our strechView.
The rest of the code goes into TouchView.m, the first step is to remove all the current code as we don't need any of the current implemented methods. We can add the following though - it handles when someone touches down on the screen.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
}
The first thing we need to do is start the animation, this is done with the UIView class methodbeginAnimations:context:. We pass it a name for the animation and nil for the context. I passed it@"MoveAndStrech" for the name. To finish and begin the animation we need to call the class methodcommitAnimations. What ever is done in between the two calls is what will happen in the animation. There are two quick methods to call to set the animation behavior, setAnimationDuration: andsetAnimationBeginsFromCurrentState. The first is is pretty self explanatory the second tells the animation that it should start from the present state of the view. Our updated touchesBegan follows.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
  [UIView beginAnimations:@"MoveAndStrech" context:nil];
  [UIView setAnimationDuration:1];
  [UIView setAnimationBeginsFromCurrentState:YES];

  [UIView commitAnimations];
}
The rest of the code is going to actually handle the updating of the view. The first case we are going to handle is if the touch count is one. If so, we grab the UITouch object from the touches set. We then set the center of ourstrechView to the location of the touch relative to our main view (self). So in two simple lines we now have a moving view that moves based on the location of touch.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
  [UIView beginAnimations:@"MoveAndStrech" context:nil];
  [UIView setAnimationDuration:1];
  [UIView setAnimationBeginsFromCurrentState:YES];
  if([touches count] == 1) {
    UITouch *touch = [touches anyObject];
    strechView.center = [touch locationInView:self];
  }
  [UIView commitAnimations];
}
Finally, we need to handle the resizing of the view. I'll run through the code right after the following.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
  [UIView beginAnimations:@"MoveAndStrech" context:nil];
  [UIView setAnimationDuration:1];
  [UIView setAnimationBeginsFromCurrentState:YES];
  if([touches count] == 1) {
    UITouch *touch = [touches anyObject];
    strechView.center = [touch locationInView:self];
  } else if([touches count] == 2) {
    NSArray *touchArray = [touches allObjects];
    UITouch *touchOne = [touchArray objectAtIndex:0];
    UITouch *touchTwo = [touchArray objectAtIndex:1];
    CGPoint pt1 = [touchOne locationInView:self];
    CGPoint pt2 = [touchTwo locationInView:self];
    CGFloat x, y, width, height;
    if(pt1.x < pt2.x) {
      x = pt1.x;
      width = pt2.x - pt1.x;
    } else {
      x = pt2.x;
      width = pt1.x - pt2.x;
    }
    if(pt1.y < pt2.y) {
      y = pt1.y;
      height = pt2.y - pt1.y;
    } else {
      y = pt2.y;
      height = pt1.y - pt2.y;
    }
    strechView.frame = CGRectMake(x, y, width, height);  
  }
  [UIView commitAnimations];
}
In order to move and resize the view we need to grab the two touches. This is easily done using the allObjectsinstance method on the touches set. We then get both locations and determine the upper x and y coordinates. The width and height can be calculated by getting the difference of the points. the final thing to do is set the frame of the view using CGRectMake. The entire TouchView.m is below.
#import "TouchView.h"

@implementation TouchView

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
  [UIView beginAnimations:@"MoveAndStrech" context:nil];
  [UIView setAnimationDuration:1];
  [UIView setAnimationBeginsFromCurrentState:YES];
  if([touches count] == 1) {
    UITouch *touch = [touches anyObject];
    strechView.center = [touch locationInView:self];
  } else if([touches count] == 2) {
    NSArray *touchArray = [touches allObjects];
    UITouch *touchOne = [touchArray objectAtIndex:0];
    UITouch *touchTwo = [touchArray objectAtIndex:1];
    CGPoint pt1 = [touchOne locationInView:self];
    CGPoint pt2 = [touchTwo locationInView:self];
    CGFloat x, y, width, height;
    if(pt1.x < pt2.x) {
      x = pt1.x;
      width = pt2.x - pt1.x;
    } else {
      x = pt2.x;
      width = pt1.x - pt2.x;
    }
    if(pt1.y < pt2.y) {
      y = pt1.y;
      height = pt2.y - pt1.y;
    } else {
      y = pt2.y;
      height = pt1.y - pt2.y;
    }
    strechView.frame = CGRectMake(x, y, width, height);  
  }
  [UIView commitAnimations];
}

@end
That pretty much wraps it up for this tutorial. If you have any questions feel free to leave a comment or head on over to the forums.

No comments:

Post a Comment

Followers