Objective-C: Blurry UIView

If you’ve been coding Objective-C interfaces for a while you will know that you set the position of a view using it’s frame property. This property is a CGRect which is made up of four float values.  newView.frame = CGRectMake(0.0, 0.0, 100.0, 100.0);

At first these floats were quite an annoyance because when debugging using NSLog() to check if frames were set correctly you have to use NSLog(@"%f",newView.frame.origin.x); and this is printed as a decimal number i.e. 0.00000

After getting used to this and starting a project that required 3 columns down the screen I thought that I could finally use the floats to their full effect. So I divided the space neatly by three and drew UILabels. UILabel *firstLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 1024/3, 768.0)];

Unfortunately this caused my UILabels to become fuzzy or blurry. After an extensive google search I found out that you should NOT be setting your frames using float values. Although CGRects take float values, when a UIView gets drawn and it has a decimal value in the frame it will blur that value to the nearest integer. This makes sense when you remember that the value you are giving is meant to represent a pixel value and a view cannot end halfway through a pixel.

So you should ensure that your frame does not contain any decimal values. An easy way to do this is to use the roundf() function. If placed around all 4 values in your frame you will always have an integer value, however this is a lot of extra code and you only have to do it where there is a possibility of having a decimal value. So my above label example became
UILabel *firstLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, roundf(1024/3), 768.0)];

Using a view’s center property it is possible to get a point with a .5 value (any view with a width or height that is odd will give you a .5 value). Using a view’s center to position another view should therefore be done using roundf(). For example say you have a white view and you want to cover it from the middle to the bottom right corner with red:

UIView *bigView = [[UIView alloc] initWithFrame:CGRectMake(30.0, 30.0, 67.0, 71.0)];
bigView.backgroundColor = [UIColor whiteColor];
[self addSubview:bigView];

UIView *smallView = [[UIView alloc] initWithFrame:CGRectMake(
                                roundf(bigView.center.x),
                                roundf(bigView.center.y),
                                roundf(bigView.frame.size.width/2),
                                roundf(bigView.frame.size.height/2)
                                                                                                )];
smallView.backgroundColor = [UIColor redColor];
[self addSubview:smallView];

[bigView release];
[smallView release];

Leave a Reply