Tutorial details

Playing around with Core Graphics | App Code for Sale | Preview

Playing around with Core Graphics - Core Animation and Touch Events (Part 1) | iOS Tutorial

How to connect Core Graphics, Core Animation and Touch event management

Overview PAGE TOP

In this two parts iOS tutorial I’ll show you a way to connect Core Graphics, Core Animation and Touch event management. The result of this experiment is a circle filled with a red gradient which appears smoothly when the user touches the screen, following his pan actions.

In this post, we draw the circle using Core Graphics. In the next post, we manage touches using gestures and NSEvent and then we animate the layer opacity using Core Animation.

You will find the complete project at the end of the post.

Drawing the circle

In my opinion, drawing shapes just by using code is a really fulfilling experience (when your code works immediately, that is). So let’s create our shape just using Core Graphics in a quick and easy way.

The next image is a preview of what we are going to draw.


We keep the code clean thanks to a dedicated class which describes the shape. So create a new UIView subclass and call it CircleGradient, then add the QuartzCore framework and import it in the header (we’ll need it next to use Core Animation).

1   #import <QuartzCore/QuartzCore.h>

Now define the function generateRadial which returns a UIImage containing a red radial gradient (remember that you can find the full code at the end of the post)

1   -(UIImage*)generateRadial{
3       //Define the gradient ----------------------
4       CGGradientRef gradient;
5       CGColorSpaceRef colorSpace;
6       size_t locations_num = 5;
8       CGFloat locations[5] = {0.0,0.4,0.5,0.6,1.0};
10      CGFloat components[20] = {  1.0, 0.0, 0.0, 0.2,
11                                  1.0, 0.0, 0.0, 1,
12                                  1.0, 0.0, 0.0, 0.8,
13                                  1.0, 0.0, 0.0, 0.4,
14                                  1.0, 0.0, 0.0, 0.0 
15                              }; 
17      colorSpace = CGColorSpaceCreateDeviceRGB();
19      gradient = CGGradientCreateWithColorComponents (colorSpace, components,
20                                                        locations, locations_num);
23      //Define Gradient Positions ---------------
25      //We want these exactly at the center of the view  
26      CGPoint startPoint, endPoint;
28      //Start point
29      startPoint.x = self.frame.size.width/2;
30      startPoint.y = self.frame.size.height/2;
32      //End point
33      endPoint.x = self.frame.size.width/2;
34      endPoint.y = self.frame.size.height/2;
36      //Generate the Image -----------------------
37      //Begin an image context 
38      UIGraphicsBeginImageContext(self.frame.size);
39      CGContextRef imageContext = UIGraphicsGetCurrentContext();
40      //Use CG to draw the radial gradient into the image context
41      CGContextDrawRadialGradient(imageContext, gradient, startPoint, 0, endPoint, self.frame.size.width/2, 0);
42      //Get the image from the context
43      UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
44      UIGraphicsEndImageContext();
46      return result;
47  }

To draw the gradient we use a CGGradient object.

This struct essentially needs a list of steps defined by the pair Color/Location. The simplest gradient could be described by two steps, but our example uses five just to make the gradient more interesting. Like a boss, right?

This part of code defines the gradient steps:

1   CGFloat locations[5] = {0.0,0.4,0.5,0.6,1.0}; //Locations 
3   CGFloat components[20] = {  1.0, 0.0, 0.0, 0.2, //First Color  ----> location  0.0
4                               1.0, 0.0, 0.0, 1,   //Second Color ----> location 0.4
5                               1.0, 0.0, 0.0, 0.8, //Third Color  ----> location 0.5
6                               1.0, 0.0, 0.0, 0.4, //Fourth Color ----> location 0.6
7                               1.0, 0.0, 0.0, 0.0  //Last Color   ----> location 1.0
8                           };

The first color component (defined in RGBA) is associated to the first element of the array locations, the second color to the second location and so on…

The drawing method used by Core Graphics for radial gradients relies on interpolation between gradient steps. This method differs from Photoshop’s (and many other “drawing tools”) in the way it draws the steps. In Photoshop each step’s center has the same position (remember, Radial Gradients), while in Core Graphics the initial and final steps’ centers can be defined in different positions (check the documentation for more information about that).

We want to represent a circle, so we draw initial and final steps at the same position. In this case, it’s the center point of the view.

1   //Start point
2   startPoint.x = self.frame.size.width/2;
3   startPoint.y = self.frame.size.height/2;
5   //End point
6   endPoint.x = self.frame.size.width/2;
7   endPoint.y = self.frame.size.height/2;

We want this function to return a UIImage*. So we create an image context and we draw in it using the Core Graphics function CGContextDrawRadialGradient.

1   UIGraphicsBeginImageContext(self.frame.size);
2   CGContextRef imageContext = UIGraphicsGetCurrentContext();
3   //Use CG to draw the radial gradient into the image context
4   CGContextDrawRadialGradient(imageContext, gradient, startPoint, 0, endPoint, self.frame.size.width/2, 0);

This function receives the gradient that we have previously created using the color and location components, the initial step position, the initial radius (this case 0), the final step position and the final radius (half of the view width).

Last, we create the image using the function UIGraphicsGetImageFromCurrentImageContext, which has a self explanatory name, and we close the image graphic context.

1   UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
2   UIGraphicsEndImageContext();

We have programmatically created a UIImage that can be used in our code as any other image. Let’s add it as content of the view layer in the initWithFrame function.

1   - (id)initWithFrame:(CGRect)frame
2   {
3       self = [super initWithFrame:frame];
5       if (self) {
6           self.layer.contents = (__bridge id)([[self generateRadial]CGImage]);
7       }
9       return self;
10  }

The Layer property contents expects a CGImageRef as value casted to id.

This class is now ready to draw the red circle. We could test the work done so far just by attaching an instance of CircleGradient as subview of the main view controller. Let’s add a property of type GradientCircle* in ViewController.h and in ViewController.m set this property with a new instance of GradientCircle.

1   @property GradientCircle* gradientView;

1   - (void)viewDidLoad
2   {
3       [super viewDidLoad];
4       //Generate the gradient view --------------------
5       self.gradientView = [[GradientCircle alloc]initWithFrame:CGRectMake(50, 50, 200, 200)];
6       [self.view addSubview:self.gradientView];

We can now compile and see the result. :)

That’s all for this post. In the next one I’ll show you how to add touch management and animations to this simple application.

Reference PAGE TOP


0 Comments Leave a comment

Please login in order to leave a comment.

Newest first

to your Chupamobile Account.

The Easiest way to Launch your next App or Game.

Join Chupamobile and get instant access to thousands of ready made App and Game Templates.

Creating an account means you’re okay with Chupamobile’s Terms of Service and Privacy Policy.