Posts Tagged ‘Design’

Exploring iOS 7 Rounded Corners

Thursday, June 20th, 2013

Apple announced iOS 7 at the WWDC 2013. Compared to the previous iOS versions it gets a whole new look for the first time. There’s a lot of discussion going on whether it’s good or bad design. I personally like it very much, and it reminds me a bit of the huge step from Mac OS 9 to Mac OS X years ago. Many things have changed in iOS 7, but one little detail attracted my attention and that’s what this article is about: rounded corners. Apple is very obsessed about every little detail; in my opinion that’s one of the secrets why they make so beautiful and successful products. Usually a rounded corner is just a quarter of a circle, one might think. But Apple changed the form factor of rounded corners in iOS 7. Here is a little comparison:

Rounded Corners in iOS 6Rounded Corners in iOS 7


Animated iOS 6 vs 7 Comparison


To me, the corners in iOS 7 look much smoother and organic. These new corners are everywhere in iOS 7. One reason for this is that as a developer you get these new corners for free. Whenever you use the existing functions of the operating system to create rounded corners, you get the improved ones in iOS 7, e. g. when calling [UIBezierPath bezierPathWithRoundedRect:cornerRadius:].

Here is an image that shows the difference between the old and the new corners:

Corner Difference between iOS 6 and iOS 7


You see that not many pixels have changed, even at this big size, but nevertheless it has some subtle but perceptible impact in how the corners look and feel.

Currently there are a few discussions on how Apple draws these new corners; even some mathematical equations are published. I took a rather pragmatic approach to analyze it: I created a small test app that lets the system create a rounded rectangle and then introspects and visualizes the elements of the returned bezier path. Then I launched this app on iOS 6 and iOS 7. Here are the results:

Rounded Corner Bezier Path on iOS 6
Rounded Corner Bezier Path on iOS 7
A red cross marks every point where a straight line is drawn to. An orange cross with two green control points in between define a bezier curve. As you can see there are four little points where the path is not perfect yet: there are four (very) short straight lines from a curve end point (orange) to a new point (red) very closely together. These unnecessary four short lines can be stripped out of the path; maybe this will be fixed in the final version of iOS 7.

What’s also interesting is the fact that the edges of the rectangle are bent much earlier than before. In the picture below the blue area is where the lines are curved in iOS 6. The red area is where the lines are curved in iOS 7. It’s more than half the corner radius earlier:

Line bending areas

Update: Together with @flarup and @marcedwards we tried to figure out the exact radius for the corners being used for the app icons in iOS 7. Additionally I filtered out the annoying short lines metioned above and exported the UIBezierPath as SVG file. As far as we can see a radius of 27 pixels at 120×120 pixel icon size produces a pretty good match. Download it here.

In case you wonder how I introspected the UIBezierPath to draw the images above – here is the UIView code:

@interface CornerTestView ()
@property (nonatomic) CGPoint previousPoint;
@end

@implementation CornerTestView

static void pathInspector(void *info, const CGPathElement *element)
{
	CornerTestView *view = (__bridge CornerTestView *)info;
	[view addElement:element];
}

- (void)drawRect:(CGRect)dirtyRect
{
	[[UIColor whiteColor] setFill];
	UIRectFill(dirtyRect);

	CGRect rect = self.bounds;
	CGFloat size = MIN(CGRectGetWidth(rect), CGRectGetHeight(rect)) - 20;
	size = round(size / 2) * 2;
	rect = CGRectMake(round(CGRectGetMidX(rect) - size / 2), round(CGRectGetMidY(rect) - size / 2), size, size);
	CGFloat radius = size / 4;
	UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius];
	[[UIColor colorWithRed:0.90 green:0.93 blue:1.0 alpha:1.0] setFill];
	[path fill];

	CGPathRef cgPath = path.CGPath;
	CGPathApply(cgPath, (__bridge void *)(self), pathInspector);
}

static UIBezierPath *crossAtPoint(CGPoint p)
{
	UIBezierPath *cross = [UIBezierPath bezierPath];
	cross.lineWidth = 0.5;
	[cross moveToPoint:CGPointMake(p.x - 2, p.y - 2)];
	[cross addLineToPoint:CGPointMake(p.x + 2, p.y + 2)];
	[cross moveToPoint:CGPointMake(p.x - 2, p.y + 2)];
	[cross addLineToPoint:CGPointMake(p.x + 2, p.y - 2)];
	return cross;
}

- (void)addElement:(const CGPathElement *)element
{
	switch (element->type) {
		case kCGPathElementMoveToPoint:
			[[UIColor grayColor] setStroke];
			[crossAtPoint(element->points[0]) stroke];
			self.previousPoint = element->points[0];
			break;
		case kCGPathElementAddLineToPoint:
		{
			UIBezierPath *line = [UIBezierPath bezierPath];
			line.lineWidth = 0.25;
			[[UIColor lightGrayColor] setStroke];
			[line moveToPoint:self.previousPoint];
			[line addLineToPoint:element->points[0]];
			[line stroke];

			[[UIColor redColor] setStroke];
			[crossAtPoint(element->points[0]) stroke];
			self.previousPoint = element->points[0];
		}
			break;
		case kCGPathElementAddQuadCurveToPoint:
		{
			UIBezierPath *line = [UIBezierPath bezierPath];
			line.lineWidth = 0.25;
			[[UIColor lightGrayColor] setStroke];
			[line moveToPoint:self.previousPoint];
			[line addLineToPoint:element->points[0]];
			[line addLineToPoint:element->points[1]];
			[line stroke];
			[[UIColor cyanColor] setStroke];
			[crossAtPoint(element->points[0]) stroke];
			[[UIColor magentaColor] setStroke];
			[crossAtPoint(element->points[1]) stroke];
			self.previousPoint = element->points[1];
		}
			break;
		case kCGPathElementAddCurveToPoint:
		{
			UIBezierPath *line = [UIBezierPath bezierPath];
			line.lineWidth = 0.25;
			[[UIColor lightGrayColor] setStroke];
			[line moveToPoint:self.previousPoint];
			[line addLineToPoint:element->points[0]];
			[line addLineToPoint:element->points[1]];
			[line addLineToPoint:element->points[2]];
			[line stroke];
			[[UIColor greenColor] setStroke];
			[crossAtPoint(element->points[0]) stroke];
			[crossAtPoint(element->points[1]) stroke];
			[[UIColor orangeColor] setStroke];
			[crossAtPoint(element->points[2]) stroke];
			self.previousPoint = element->points[2];
		}
			break;
		case kCGPathElementCloseSubpath:
			break;
	}
}

@end

Have fun!

Being Rejected. Not.

Thursday, March 12th, 2009

Here’s another story of an application being rejected by Apple from the App Store.

“Hey, you have an iPhone! – Can I take a look?”

Do you know that? This situation gave me the idea for a funny application that should display the Home screen of your iPhone or iPod touch, but as soon as someone touches it, a scary barking dog should appear. The idea for my little funny “Watchdog” application was born.

I developed it, polished it until I liked it much, wrote a description, created a web page etc. and finally submitted my iPhone application to Apple so they can review it and put it into their App Store.

Round One

On my first submitting attempt the Watchdog application contained real screenshots of the Home screen of the iPhone and the iPod touch in all available languages (blowing up the application size to about 7 MB). I already had the feeling that Apple will reject this because with the screenshots I indirectly use their icon graphics, but nevertheless I tried it. OK, my app really got rejected the first time.

Apple’s official answer was:

Unfortunately, your application, Watchdog Mobile, cannot be added to the App Store because it uses standard iPhone screen images in a non-standard way, potentially resulting in user confusion. Changing the behavior of standard iPhone graphics, actions, and images, or simulating failures of those graphics, actions, or images is a violation of the iPhone Developer Program agreement which requires applications to abide by the Human Interface Guidelines.

I can understand that Apple does not want screenshots of the Home screen in apps. The statement is still a bit strange, because Apple complains about “potentially resulting in user confusion”. Er … yes … indeed … Watchdog is designed to confuse (or surprise) the user! When someone uses Watchdog, he does it intentionally and after seeing the barking dog it should be obvious to everyone that there is a kind of … uhm … “watchdog” application running. It’s surprising and can be really shocking if you don’t reckon that (it actually happened to myself a few times) but it’s very funny and you realize the joke at the same second.

Round Two

OK, having screenshots of the Home screen containing Apple icons in an application is really a bad idea. So I added the ability to choose a custom image and wrote a description how the user can make a screenshot of his Home screen. Unfortunately this decreases the ease-of-use of the application a little bit, but it’s not really dramatic. I removed all bundled screenshots and created a funny comic styled “Fake Home screen” that is used as default image. As a side note, the size of the app reduced to around 1.5 MB.

But guess what … the second version of my application got rejected again. Apple’s statement was that “the modified iPhone screen image is still too similar to the iPhone screen image”. Argh. OK, I know there are different types of people … some are more “visual”, others are more “auditory” and others more “tactile” oriented. Maybe people that are not so “visual” may still confuse the comic styled Home screen with a real Home screen. By the way, I really like the big funny icons and once I saw them on the iPhone screen I wished they could be used for real. 😉

Round Three

I though about what I can use as default image instead. My first idea was to use a cute looking puppy. Perhaps with a sign around its neck saying something like “Replace me” or so. While this might be a bit funny, I did not want to get too far away from the original idea to present a Home screen. So I came up with a modified version of my comic styled Home screen: I dimmed it in brightness and put a very flashy text above it saying that it’s a Fake Home screen. So nobody can ever confuse this with a real Home screen. I was very curious about the reaction from Apple.

But – I was already prepared for that – Apple rejected it again. “Simulating failures” is obviously not accepted by Apple. At some degree I understand that, but I thought it’s obvious enough that no-one gets “potentially confused” by this application. Thought wrong.

Round Four

So I prepared my last attempt before giving up. I completely threw away the idea of simulating a Home screen. Let’s just make a dog application and let’s hope that the user has the idea of using a Home screen image for himself. I removed every comment about the Home screen from the application and its description. I replaced the Default image with a neat looking dog. I completely rewrote the description. There’s nothing of the original idea in this app. Of course, the user can still use a screenshot of the Home screen to have the original effect, but it’s not so obvious anymore. This time is took much longer for Apple to review this app … but finally …

Hooray – Apple accepted my Watchdog application! 🙂

Feel free to purchase Watchdog at the iPhone App Store and tell everybody how cool that thing can be used. 😉 Thank you very much for your support!

To get the best effect, you have to create a screenshot of your Home screen. This can be done by quickly pressing and releasing the Sleep/Wake and Home buttons at the same time while the Home screen is displayed. The screenshot ends up in the “Camera Roll” section of the Photo application on the iPhone. Then just choose this image in the Watchdog application. Have fun!

Finally a little gallery of the four different versions of the default image that I have created:

Evolution of the Default Image

Evolution of the Default Image

The Art of the Camel

Monday, January 26th, 2009

This weekend my first iPhone / iPod touch game Sahara found its way into the App Store.

Sahara is a challenging puzzle game where you have to guide a camel through a labyrinth in the desert. If you like it, you can purchase it in the App Store.

I am very happy about that release of my first iPhone app. It was very exciting and fun to do all those things like registering as iPhone Application Developer, signing all the contracts, exploring the iPhone SDK, developing the game e.g. programming an algorithm to find the shortest way through the maze, implementing animations, doing all the graphics and sounds, preparing my web site and finally submitting the application to Apple. It went through the review process in just about two days without any problems. It seems I did everything alright. 😉

To give you some insight to the graphical development process of Sahara, here is an example how the camel was born:

Life of the camel

Life of the Camel

At the left is a rough pencil drawing of the camel how it was in my head. I did about five to ten drawings of that style or so. It was not exactly how I thought it should look like, but this one was pretty close. Then I scanned the drawing and did the final artwork directly on my Mac with vector graphics. I put the scan of the draft drawing underneath the image with 50% transparency as orientation. As you can see, I did a lot of corrections especially to the head of the camel. The funny eyes are bigger, the shape of the head is different, the ears are smaller and better aligned and so on. Although I own a Wacom tablet, I did all the graphics with my mouse, because I did no real “drawing”: I added a bunch of bezier paths for each stroke and then I corrected the points and anchors until I was satisfied with the result. Note that I did not have a pencil drawing for the skeleton; I just used the final camel as orientation underneath and drew the bones directly on the computer as vector graphics onto it.

After doing years of “just coding and coding” I really enjoyed doing this artistic work. Although in my opinion developing software is also some sort of artistic work, but I mean artistic in a graphical manner here. I did a lot of drawing in my childhood, but once I got my first computer it was displaced by programming so far. I am happy that I can combine both now.

Finally some more studies used for developing the camel for the game:

Study of the Camel

Studying the Camel