Skip to content

Instantly share code, notes, and snippets.

@pablisco
Created September 28, 2011 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pablisco/1248009 to your computer and use it in GitHub Desktop.
Save pablisco/1248009 to your computer and use it in GitHub Desktop.
Extension to control the UIView frame

Extension to control the UIView frame

Making flexible layouts (that change with content) is quite painful. I worked into a solution to simplify the way to accomplish nice looking interfaces with dynamic content (and most important changing dimensions and position of elements). Even for the example I show bellow it seems fairly complex (although not fully implemented) but by using the provided frame method it would be not just longer but rather harder to read.

Using the builder pattern this class can be used to help with the rendering of UIViews on iPhone interfaces. It is really helpful if you are doing "flexible" layout for a UITableViewCell since it keeps a copy of the original frame. This is useful because we can have member variables with the FrameControl instances for each of the views that require to be moved around and reset to the original state before doing all the layout. (see --)

The normal behavior is to call [control] to apply the changes but if you are using them as local variables they get automatically committed when the FrameControl instance is released (or autoreleased).

It also eases the layout process if you have the tag of the views assigned in IB and then use an NSArray to cycle through all the views.

Hope you enjoy.

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface FrameControl : NSObject {
UIView *view;
CGRect originalFrame;
CGRect frame;
BOOL changed;
}
+ (FrameControl *) control: (UIView *) view;
@property (nonatomic) CGFloat y;
@property (nonatomic) CGFloat x;
@property (nonatomic) CGFloat height;
@property (nonatomic) CGFloat width;
@property (nonatomic) BOOL visible;
@property (nonatomic, readonly) UIView *view;
- (void) commit;
- (void) restore;
@end
#import "FrameControl.h"
@implementation FrameControl
+ (FrameControl *)control:(UIView *)view
{
FrameControl *control = [[FrameControl new] autorelease];
control->view = [view retain];
control->originalFrame = view.frame;
control->frame = view.frame;
control->changed = NO;
return control;
}
@synthesize view;
- (void)setX:(CGFloat)x {
changed = YES;
frame.origin.x = x;
}
- (CGFloat)x {
return frame.origin.x;
}
- (void)setY:(CGFloat)y {
changed = YES;
frame.origin.y = y;
}
- (CGFloat)y {
return frame.origin.y;
}
- (void)setWidth:(CGFloat)width {
changed = YES;
frame.size.width = width;
}
- (CGFloat)width {
return frame.size.width;
}
- (void)setHeight:(CGFloat)height {
changed = YES;
frame.size.height = height;
}
- (CGFloat)height {
return frame.size.height;
}
- (void)setVisible:(BOOL)visible {
view.hidden = !visible;
}
- (BOOL)visible {
return !view.hidden;
}
- (void)commit {
view.frame = frame;
}
- (void) restore {
if (changed) {
frame = originalFrame;
view.frame = originalFrame;
changed = NO;
}
}
- (void)dealloc{
[self commit];
[view release];
[super dealloc];
}
@end
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2011 Mathieu 'p01' Henri <http://www.p01.org/releases/>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
#import "ResultCell.h"
#import "FrameControl.h"
@implementation ResultCell
#define TITLE_VIEW_TAG 0
#define IMAGE_LABEL_TAG 1
#define DESCRIPTION_LABEL_TAG 2
- (NSArray *)childrenControl
{
if (!childrenControl) {
NSMutableArray *mutableChildren = [NSMutableArray array];
for (UIView *view in [NSMutableArray arrayWithObjects:
titleView, // TITLE_VIEW_TAG
imageLabel, // IMAGE_LABEL_TAG
descriptionLabel, // DESCRIPTION_LABEL_TAG
nil]) {
[mutableChildren addObject:[FrameControl control:view]];
}
childrenControl = [mutableChildren retain];
}
return childrenControl;
}
- (void) setData: (id) data {
// first loop sets view into their default state. This can be included into
// the main for loop if the original position is not relevant to other views
for (FrameControl *control in self.childrenControl) {
[control restore];
}
CGFloat currentY = 0;
CGFloat currentX = 0;
for (FrameControl *control in self.childrenControl) {
switch (control.view.tag) {
case IMAGE_VIEW_TAG:
currentX = control.x;
if(data.image) {
currentX += control.width;
}
break;
case TITLE_LABEL_TAG:
control.x = currentX;
currentX += control.width;
currentY = control.y;
UIFont *font = titleLabel.font;
CGSize boundingSize = CGSizeMake(control.width, CGFLOAT_MAX);
CGSize requiredSize = [textToMeasure sizeWithFont: font
constrainedToSize: boundingSize
lineBreakMode: UILineBreakModeWordWrap];
currentY += (control.height = requiredSize.height);
break;
case DETAILS_LABEL_TAG:
control.y = currentY;
// more size processing
break;
}
[control commit];
}
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment