From de79672a58f9fa34157d5579aaea8494886d11f2 Mon Sep 17 00:00:00 2001 From: Markus Emrich Date: Mon, 11 Feb 2013 21:53:42 +0100 Subject: [PATCH 1/7] converted to ARC, using auto synthesizing --- CSLinearLayoutView/CSLinearLayoutView.h | 5 +- CSLinearLayoutView/CSLinearLayoutView.m | 49 ++----------------- .../project.pbxproj | 2 +- 3 files changed, 10 insertions(+), 46 deletions(-) diff --git a/CSLinearLayoutView/CSLinearLayoutView.h b/CSLinearLayoutView/CSLinearLayoutView.h index b0e160b..13729ac 100644 --- a/CSLinearLayoutView/CSLinearLayoutView.h +++ b/CSLinearLayoutView/CSLinearLayoutView.h @@ -100,4 +100,7 @@ typedef struct { CSLinearLayoutItemPadding CSLinearLayoutMakePadding(CGFloat top, CGFloat left, CGFloat bottom, CGFloat right); -@end \ No newline at end of file +@end + + + diff --git a/CSLinearLayoutView/CSLinearLayoutView.m b/CSLinearLayoutView/CSLinearLayoutView.m index 94dcef1..90feab1 100644 --- a/CSLinearLayoutView/CSLinearLayoutView.m +++ b/CSLinearLayoutView/CSLinearLayoutView.m @@ -9,20 +9,13 @@ #import "CSLinearLayoutView.h" @interface CSLinearLayoutView() - - (void)setup; - (void)adjustFrameSize; - (void)adjustContentSize; - @end @implementation CSLinearLayoutView -@synthesize items = _items; -@synthesize orientation = _orientation; -@synthesize autoAdjustFrameSize = _autoAdjustFrameSize; -@synthesize autoAdjustContentSize = _autoAdjustContentSize; - #pragma mark - Factories - (id)init { @@ -58,14 +51,6 @@ - (void)setup { } -#pragma mark - Lifecycle - -- (void)dealloc { - [_items release], _items = nil; - [super dealloc]; -} - - #pragma mark - Layout - (void)layoutSubviews { @@ -210,12 +195,8 @@ - (void)removeItem:(CSLinearLayoutItem *)linearLayoutItem { return; } - [linearLayoutItem retain]; - - [_items removeObject:linearLayoutItem]; [linearLayoutItem.view removeFromSuperview]; - - [linearLayoutItem release]; + [_items removeObject:linearLayoutItem]; } - (void)removeAllItems { @@ -264,12 +245,10 @@ - (void)moveItem:(CSLinearLayoutItem *)movingItem beforeItem:(CSLinearLayoutItem return; } - [movingItem retain]; [_items removeObject:movingItem]; NSUInteger existingItemIndex = [_items indexOfObject:existingItem]; [_items insertObject:movingItem atIndex:existingItemIndex]; - [movingItem release]; [self setNeedsLayout]; } @@ -279,7 +258,6 @@ - (void)moveItem:(CSLinearLayoutItem *)movingItem afterItem:(CSLinearLayoutItem return; } - [movingItem retain]; [_items removeObject:movingItem]; if (existingItem == [_items lastObject]) { @@ -288,7 +266,6 @@ - (void)moveItem:(CSLinearLayoutItem *)movingItem afterItem:(CSLinearLayoutItem NSUInteger existingItemIndex = [_items indexOfObject:existingItem]; [_items insertObject:movingItem atIndex:++existingItemIndex]; } - [movingItem release]; [self setNeedsLayout]; } @@ -298,7 +275,6 @@ - (void)moveItem:(CSLinearLayoutItem *)movingItem toIndex:(NSUInteger)index { return; } - [movingItem retain]; [_items removeObject:movingItem]; if (index == ([_items count] - 1)) { @@ -306,7 +282,6 @@ - (void)moveItem:(CSLinearLayoutItem *)movingItem toIndex:(NSUInteger)index { } else { [_items insertObject:movingItem atIndex:index]; } - [movingItem release]; [self setNeedsLayout]; } @@ -329,14 +304,6 @@ - (void)swapItem:(CSLinearLayoutItem *)firstItem withItem:(CSLinearLayoutItem *) @implementation CSLinearLayoutItem -@synthesize view = _view; -@synthesize fillMode = _fillMode; -@synthesize horizontalAlignment = _horizontalAlignment; -@synthesize verticalAlignment = _verticalAlignment; -@synthesize padding = _padding; -@synthesize tag = _tag; -@synthesize userInfo = _userInfo; - #pragma mark - Factories - (id)init { @@ -361,19 +328,10 @@ - (id)initWithView:(UIView *)aView { } + (CSLinearLayoutItem *)layoutItemForView:(UIView *)aView { - CSLinearLayoutItem *item = [[[CSLinearLayoutItem alloc] initWithView:aView] autorelease]; + CSLinearLayoutItem *item = [[CSLinearLayoutItem alloc] initWithView:aView]; return item; } -#pragma mark - Memory Management - -- (void)dealloc { - self.view = nil; - self.userInfo = nil; - - [super dealloc]; -} - #pragma mark - Helpers @@ -388,3 +346,6 @@ CSLinearLayoutItemPadding CSLinearLayoutMakePadding(CGFloat top, CGFloat left, C } @end + + + diff --git a/Demo/CSLinearLayoutView.xcodeproj/project.pbxproj b/Demo/CSLinearLayoutView.xcodeproj/project.pbxproj index 5dcfa74..ed7821d 100644 --- a/Demo/CSLinearLayoutView.xcodeproj/project.pbxproj +++ b/Demo/CSLinearLayoutView.xcodeproj/project.pbxproj @@ -21,7 +21,7 @@ 15F8EF81151DACD100C6CEBF /* CSAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 15F8EF7D151DACD100C6CEBF /* CSAppDelegate.m */; }; 15F8EF82151DACD100C6CEBF /* CSMainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 15F8EF7F151DACD100C6CEBF /* CSMainViewController.m */; }; 15F8EF88151DACE100C6CEBF /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 15F8EF86151DACE100C6CEBF /* main.m */; }; - 15F8EF94151DAE5B00C6CEBF /* CSLinearLayoutView.m in Sources */ = {isa = PBXBuildFile; fileRef = 15F8EF92151DAE5B00C6CEBF /* CSLinearLayoutView.m */; }; + 15F8EF94151DAE5B00C6CEBF /* CSLinearLayoutView.m in Sources */ = {isa = PBXBuildFile; fileRef = 15F8EF92151DAE5B00C6CEBF /* CSLinearLayoutView.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; 15F8EFB0151ED34D00C6CEBF /* CSVerticalViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 15F8EFAF151ED34D00C6CEBF /* CSVerticalViewController.m */; }; 15F8EFB9151ED9ED00C6CEBF /* UIColor+RandomColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 15F8EFB8151ED9ED00C6CEBF /* UIColor+RandomColor.m */; }; 15F8EFBC151EDF6D00C6CEBF /* CSHorizontalViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 15F8EFBB151EDF6D00C6CEBF /* CSHorizontalViewController.m */; }; From e39bf56cdd80d85607dd1270e9fb39d41232ec99 Mon Sep 17 00:00:00 2001 From: Markus Emrich Date: Mon, 11 Feb 2013 22:41:08 +0100 Subject: [PATCH 2/7] fixed missing scroll indicators --- CSLinearLayoutView/CSLinearLayoutView.m | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CSLinearLayoutView/CSLinearLayoutView.m b/CSLinearLayoutView/CSLinearLayoutView.m index 90feab1..3cb9acc 100644 --- a/CSLinearLayoutView/CSLinearLayoutView.m +++ b/CSLinearLayoutView/CSLinearLayoutView.m @@ -200,10 +200,11 @@ - (void)removeItem:(CSLinearLayoutItem *)linearLayoutItem { } - (void)removeAllItems { - [_items removeAllObjects]; - for (UIView *subview in self.subviews) { - [subview removeFromSuperview]; + // only remove actual items, not scrollbars + for (CSLinearLayoutItem *item in self.items) { + [item.view removeFromSuperview]; } + [self.items removeAllObjects]; } - (void)insertItem:(CSLinearLayoutItem *)newItem beforeItem:(CSLinearLayoutItem *)existingItem { From 71b7f60f8b1ad6cc9bfafd7b4d6b1752a10c1928 Mon Sep 17 00:00:00 2001 From: Markus Emrich Date: Mon, 11 Feb 2013 22:46:57 +0100 Subject: [PATCH 3/7] use properties instead of ivars, where possible --- CSLinearLayoutView/CSLinearLayoutView.m | 87 ++++++++++++------------- 1 file changed, 43 insertions(+), 44 deletions(-) diff --git a/CSLinearLayoutView/CSLinearLayoutView.m b/CSLinearLayoutView/CSLinearLayoutView.m index 3cb9acc..08546ed 100644 --- a/CSLinearLayoutView/CSLinearLayoutView.m +++ b/CSLinearLayoutView/CSLinearLayoutView.m @@ -9,6 +9,7 @@ #import "CSLinearLayoutView.h" @interface CSLinearLayoutView() +@property (nonatomic, strong) NSMutableArray *items; - (void)setup; - (void)adjustFrameSize; - (void)adjustContentSize; @@ -43,10 +44,10 @@ - (id)initWithCoder:(NSCoder *)aDecoder { } - (void)setup { - _items = [[NSMutableArray alloc] init]; - _orientation = CSLinearLayoutViewOrientationVertical; - _autoAdjustFrameSize = NO; - _autoAdjustContentSize = YES; + self.items = [[NSMutableArray alloc] init]; + self.orientation = CSLinearLayoutViewOrientationVertical; + self.autoAdjustFrameSize = NO; + self.autoAdjustContentSize = YES; self.autoresizesSubviews = NO; } @@ -58,7 +59,7 @@ - (void)layoutSubviews { CGFloat relativePosition = 0.0; CGFloat absolutePosition = 0.0; - for (CSLinearLayoutItem *item in _items) { + for (CSLinearLayoutItem *item in self.items) { CGFloat startPadding = 0.0; CGFloat endPadding = 0.0; @@ -120,11 +121,11 @@ - (void)layoutSubviews { } - if (_autoAdjustFrameSize == YES) { + if (self.autoAdjustFrameSize == YES) { [self adjustFrameSize]; } - if (_autoAdjustContentSize == YES) { + if (self.autoAdjustContentSize == YES) { [self adjustContentSize]; } } @@ -150,8 +151,8 @@ - (void)adjustContentSize { - (CGFloat)layoutOffset { CGFloat currentOffset = 0.0; - for (CSLinearLayoutItem *item in _items) { - if (_orientation == CSLinearLayoutViewOrientationHorizontal) { + for (CSLinearLayoutItem *item in self.items) { + if (self.orientation == CSLinearLayoutViewOrientationHorizontal) { currentOffset += item.padding.left + item.view.frame.size.width + item.padding.right; } else { currentOffset += item.padding.top + item.view.frame.size.height + item.padding.bottom; @@ -169,11 +170,11 @@ - (void)setOrientation:(CSLinearLayoutViewOrientation)anOrientation { - (void)addSubview:(UIView *)view { [super addSubview:view]; - if (_autoAdjustFrameSize == YES) { + if (self.autoAdjustFrameSize == YES) { [self adjustFrameSize]; } - if (_autoAdjustContentSize == YES) { + if (self.autoAdjustContentSize == YES) { [self adjustContentSize]; } } @@ -182,21 +183,21 @@ - (void)addSubview:(UIView *)view { #pragma mark - Add, Remove, Insert, & Move - (void)addItem:(CSLinearLayoutItem *)linearLayoutItem { - if (linearLayoutItem == nil || [_items containsObject:linearLayoutItem] == YES || linearLayoutItem.view == nil) { + if (linearLayoutItem == nil || [self.items containsObject:linearLayoutItem] == YES || linearLayoutItem.view == nil) { return; } - [_items addObject:linearLayoutItem]; + [self.items addObject:linearLayoutItem]; [self addSubview:linearLayoutItem.view]; } - (void)removeItem:(CSLinearLayoutItem *)linearLayoutItem { - if (linearLayoutItem == nil || [_items containsObject:linearLayoutItem] == NO) { + if (linearLayoutItem == nil || [self.items containsObject:linearLayoutItem] == NO) { return; } [linearLayoutItem.view removeFromSuperview]; - [_items removeObject:linearLayoutItem]; + [self.items removeObject:linearLayoutItem]; } - (void)removeAllItems { @@ -208,93 +209,91 @@ - (void)removeAllItems { } - (void)insertItem:(CSLinearLayoutItem *)newItem beforeItem:(CSLinearLayoutItem *)existingItem { - if (newItem == nil || [_items containsObject:newItem] == YES || existingItem == nil || [_items containsObject:existingItem] == NO) { + if (newItem == nil || [self.items containsObject:newItem] == YES || existingItem == nil || [self.items containsObject:existingItem] == NO) { return; } - NSUInteger index = [_items indexOfObject:existingItem]; - [_items insertObject:newItem atIndex:index]; + [self.items insertObject:newItem atIndex:index]; [self addSubview:newItem.view]; } - (void)insertItem:(CSLinearLayoutItem *)newItem afterItem:(CSLinearLayoutItem *)existingItem { - if (newItem == nil || [_items containsObject:newItem] == YES || existingItem == nil || [_items containsObject:existingItem] == NO) { + if (newItem == nil || [self.items containsObject:newItem] == YES || existingItem == nil || [self.items containsObject:existingItem] == NO) { return; } - if (existingItem == [_items lastObject]) { - [_items addObject:newItem]; + if (existingItem == [self.items lastObject]) { + [self.items addObject:newItem]; } else { - NSUInteger index = [_items indexOfObject:existingItem]; - [_items insertObject:newItem atIndex:++index]; + NSUInteger index = [self.items indexOfObject:existingItem]; + [self.items insertObject:newItem atIndex:++index]; } [self addSubview:newItem.view]; } - (void)insertItem:(CSLinearLayoutItem *)newItem atIndex:(NSUInteger)index { - if (newItem == nil || [_items containsObject:newItem] == YES || index >= [_items count]) { + if (newItem == nil || [self.items containsObject:newItem] == YES || index >= [self.items count]) { return; } - [_items insertObject:newItem atIndex:index]; [self addSubview:newItem.view]; } - (void)moveItem:(CSLinearLayoutItem *)movingItem beforeItem:(CSLinearLayoutItem *)existingItem { - if (movingItem == nil || [_items containsObject:movingItem] == NO || existingItem == nil || [_items containsObject:existingItem] == NO || movingItem == existingItem) { + if (movingItem == nil || [self.items containsObject:movingItem] == NO || existingItem == nil || [self.items containsObject:existingItem] == NO || movingItem == existingItem) { return; } - [_items removeObject:movingItem]; + [self.items removeObject:movingItem]; - NSUInteger existingItemIndex = [_items indexOfObject:existingItem]; - [_items insertObject:movingItem atIndex:existingItemIndex]; + NSUInteger existingItemIndex = [self.items indexOfObject:existingItem]; + [self.items insertObject:movingItem atIndex:existingItemIndex]; [self setNeedsLayout]; } - (void)moveItem:(CSLinearLayoutItem *)movingItem afterItem:(CSLinearLayoutItem *)existingItem { - if (movingItem == nil || [_items containsObject:movingItem] == NO || existingItem == nil || [_items containsObject:existingItem] == NO || movingItem == existingItem) { + if (movingItem == nil || [self.items containsObject:movingItem] == NO || existingItem == nil || [self.items containsObject:existingItem] == NO || movingItem == existingItem) { return; } - [_items removeObject:movingItem]; + [self.items removeObject:movingItem]; - if (existingItem == [_items lastObject]) { - [_items addObject:movingItem]; + if (existingItem == [self.items lastObject]) { + [self.items addObject:movingItem]; } else { - NSUInteger existingItemIndex = [_items indexOfObject:existingItem]; - [_items insertObject:movingItem atIndex:++existingItemIndex]; + NSUInteger existingItemIndex = [self.items indexOfObject:existingItem]; + [self.items insertObject:movingItem atIndex:++existingItemIndex]; } [self setNeedsLayout]; } - (void)moveItem:(CSLinearLayoutItem *)movingItem toIndex:(NSUInteger)index { - if (movingItem == nil || [_items containsObject:movingItem] == NO || index >= [_items count] || [_items indexOfObject:movingItem] == index) { + if (movingItem == nil || [self.items containsObject:movingItem] == NO || index >= [self.items count] || [self.items indexOfObject:movingItem] == index) { return; } - [_items removeObject:movingItem]; + [self.items removeObject:movingItem]; - if (index == ([_items count] - 1)) { - [_items addObject:movingItem]; + if (index == ([self.items count] - 1)) { + [self.items addObject:movingItem]; } else { - [_items insertObject:movingItem atIndex:index]; + [self.items insertObject:movingItem atIndex:index]; } [self setNeedsLayout]; } - (void)swapItem:(CSLinearLayoutItem *)firstItem withItem:(CSLinearLayoutItem *)secondItem { - if (firstItem == nil || [_items containsObject:firstItem] == NO || secondItem == nil || [_items containsObject:secondItem] == NO || firstItem == secondItem) { + if (firstItem == nil || [self.items containsObject:firstItem] == NO || secondItem == nil || [self.items containsObject:secondItem] == NO || firstItem == secondItem) { return; } - NSUInteger firstItemIndex = [_items indexOfObject:firstItem]; - NSUInteger secondItemIndex = [_items indexOfObject:secondItem]; - [_items exchangeObjectAtIndex:firstItemIndex withObjectAtIndex:secondItemIndex]; + NSUInteger firstItemIndex = [self.items indexOfObject:firstItem]; + NSUInteger secondItemIndex = [self.items indexOfObject:secondItem]; + [self.items exchangeObjectAtIndex:firstItemIndex withObjectAtIndex:secondItemIndex]; [self setNeedsLayout]; } From ee2482a550c4d879093752fd1e133ce08c598410 Mon Sep 17 00:00:00 2001 From: Markus Emrich Date: Mon, 11 Feb 2013 22:53:09 +0100 Subject: [PATCH 4/7] respect scrollView content insets --- CSLinearLayoutView/CSLinearLayoutView.m | 30 +++++++++++++++---------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/CSLinearLayoutView/CSLinearLayoutView.m b/CSLinearLayoutView/CSLinearLayoutView.m index 08546ed..c7bf500 100644 --- a/CSLinearLayoutView/CSLinearLayoutView.m +++ b/CSLinearLayoutView/CSLinearLayoutView.m @@ -10,6 +10,7 @@ @interface CSLinearLayoutView() @property (nonatomic, strong) NSMutableArray *items; +@property (nonatomic, readonly) CGSize innerFrameSize; - (void)setup; - (void)adjustFrameSize; - (void)adjustContentSize; @@ -72,9 +73,9 @@ - (void)layoutSubviews { if (item.verticalAlignment == CSLinearLayoutItemVerticalAlignmentTop || item.fillMode == CSLinearLayoutItemFillModeStretch) { absolutePosition = item.padding.top; } else if (item.verticalAlignment == CSLinearLayoutItemVerticalAlignmentBottom) { - absolutePosition = self.frame.size.height - item.view.frame.size.height - item.padding.bottom; + absolutePosition = self.innerFrameSize.height - item.view.frame.size.height - item.padding.bottom; } else { // CSLinearLayoutItemVerticalCenter - absolutePosition = (self.frame.size.height / 2) - ((item.view.frame.size.height + (item.padding.bottom - item.padding.top)) / 2); + absolutePosition = (self.innerFrameSize.height / 2) - ((item.view.frame.size.height + (item.padding.bottom - item.padding.top)) / 2); } } else { @@ -85,9 +86,9 @@ - (void)layoutSubviews { if (item.horizontalAlignment == CSLinearLayoutItemHorizontalAlignmentLeft || item.fillMode == CSLinearLayoutItemFillModeStretch) { absolutePosition = item.padding.left; } else if (item.horizontalAlignment == CSLinearLayoutItemHorizontalAlignmentRight) { - absolutePosition = self.frame.size.width - item.view.frame.size.width - item.padding.right; + absolutePosition = self.innerFrameSize.width - item.view.frame.size.width - item.padding.right; } else { // CSLinearLayoutItemHorizontalCenter - absolutePosition = (self.frame.size.width / 2) - ((item.view.frame.size.width + (item.padding.right - item.padding.left)) / 2); + absolutePosition = (self.innerFrameSize.width / 2) - ((item.view.frame.size.width + (item.padding.right - item.padding.left)) / 2); } } @@ -99,7 +100,7 @@ - (void)layoutSubviews { CGFloat height = item.view.frame.size.height; if (item.fillMode == CSLinearLayoutItemFillModeStretch) { - height = self.frame.size.height - (item.padding.top + item.padding.bottom); + height = self.innerFrameSize.height - (item.padding.top + item.padding.bottom); } item.view.frame = CGRectMake(relativePosition, absolutePosition, item.view.frame.size.width, height); @@ -109,7 +110,7 @@ - (void)layoutSubviews { CGFloat width = item.view.frame.size.width; if (item.fillMode == CSLinearLayoutItemFillModeStretch) { - width = self.frame.size.width - (item.padding.left + item.padding.right); + width = self.innerFrameSize.width - (item.padding.left + item.padding.right); } item.view.frame = CGRectMake(absolutePosition, relativePosition, width, item.view.frame.size.height); @@ -132,22 +133,27 @@ - (void)layoutSubviews { - (void)adjustFrameSize { if (self.orientation == CSLinearLayoutViewOrientationHorizontal) { - self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.layoutOffset, self.frame.size.height); + self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.layoutOffset, self.innerFrameSize.height); } else { - self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, self.layoutOffset); + self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.innerFrameSize.width, self.layoutOffset); } } - (void)adjustContentSize { if (self.orientation == CSLinearLayoutViewOrientationHorizontal) { - CGFloat contentWidth = MAX(self.frame.size.width, self.layoutOffset); - self.contentSize = CGSizeMake(contentWidth, self.frame.size.height); + CGFloat contentWidth = MAX(self.innerFrameSize.width, self.layoutOffset); + self.contentSize = CGSizeMake(contentWidth, self.innerFrameSize.height); } else { - CGFloat contentHeight = MAX(self.frame.size.height, self.layoutOffset); - self.contentSize = CGSizeMake(self.frame.size.width, contentHeight); + CGFloat contentHeight = MAX(self.innerFrameSize.height, self.layoutOffset); + self.contentSize = CGSizeMake(self.innerFrameSize.width, contentHeight); } } +- (CGSize)innerFrameSize { + return CGSizeMake(self.frame.size.width - self.contentInset.left - self.contentInset.right, + self.frame.size.height - self.contentInset.top - self.contentInset.bottom); +} + - (CGFloat)layoutOffset { CGFloat currentOffset = 0.0; From 98ac5a21d5a127ae7583a64a2017b889ae5d3150 Mon Sep 17 00:00:00 2001 From: Markus Emrich Date: Mon, 11 Feb 2013 23:03:01 +0100 Subject: [PATCH 5/7] added adding shortcuts for text & images --- CSLinearLayoutView/CSLinearLayoutView.h | 34 +++++++++ CSLinearLayoutView/CSLinearLayoutView.m | 93 +++++++++++++++++++++++++ 2 files changed, 127 insertions(+) diff --git a/CSLinearLayoutView/CSLinearLayoutView.h b/CSLinearLayoutView/CSLinearLayoutView.h index 13729ac..cc4cee2 100644 --- a/CSLinearLayoutView/CSLinearLayoutView.h +++ b/CSLinearLayoutView/CSLinearLayoutView.h @@ -60,6 +60,40 @@ typedef enum { @end +/* + * Shortcuts, to easily add slightly formatted text & images + */ +@interface CSLinearLayoutView () + +// configuration + +@property (nonatomic, strong) UIColor *textColor; + +@property (nonatomic, strong) UIFont *defaultFont; +@property (nonatomic, strong) UIFont *subtitleFont; +@property (nonatomic, strong) UIFont *titleFont; + +@property (nonatomic, assign) NSUInteger defaultMargin; +@property (nonatomic, assign) NSUInteger subtitleMargin; +@property (nonatomic, assign) NSUInteger titleMargin; + +// shortcuts + +- (CSLinearLayoutItem*)addImageNamed:(NSString*)imageName; + +- (CSLinearLayoutItem*)addText:(NSString*)text; +- (CSLinearLayoutItem*)addText:(NSString*)text font:(UIFont*)font; +- (CSLinearLayoutItem*)addText:(NSString*)text frontMargin:(CGFloat)frontMargin; +- (CSLinearLayoutItem*)addText:(NSString*)text font:(UIFont*)font frontMargin:(CGFloat)frontMargin; + +- (CSLinearLayoutItem*)addTitle:(NSString*)text; +- (CSLinearLayoutItem*)addSubtitle:(NSString*)text; + +// restoring +- (void)restoreDefaultFormats; + +@end + typedef enum { CSLinearLayoutItemFillModeNormal, // Respects the view's frame size diff --git a/CSLinearLayoutView/CSLinearLayoutView.m b/CSLinearLayoutView/CSLinearLayoutView.m index c7bf500..ec78383 100644 --- a/CSLinearLayoutView/CSLinearLayoutView.m +++ b/CSLinearLayoutView/CSLinearLayoutView.m @@ -50,6 +50,19 @@ - (void)setup { self.autoAdjustFrameSize = NO; self.autoAdjustContentSize = YES; self.autoresizesSubviews = NO; + + [self restoreDefaultFormats]; +} + +- (void)restoreDefaultFormats { + // adding shortcut settings + self.textColor = [UIColor blackColor]; + self.defaultFont = [UIFont systemFontOfSize: 14]; + self.subtitleFont = [UIFont boldSystemFontOfSize: 14]; + self.titleFont = [UIFont boldSystemFontOfSize: 18]; + self.defaultMargin = 6; + self.subtitleMargin = 20; + self.titleMargin = 15; } @@ -219,6 +232,7 @@ - (void)insertItem:(CSLinearLayoutItem *)newItem beforeItem:(CSLinearLayoutItem return; } + NSUInteger index = [self.items indexOfObject:existingItem]; [self.items insertObject:newItem atIndex:index]; [self addSubview:newItem.view]; } @@ -243,6 +257,7 @@ - (void)insertItem:(CSLinearLayoutItem *)newItem atIndex:(NSUInteger)index { return; } + [self.items insertObject:newItem atIndex:index]; [self addSubview:newItem.view]; } @@ -304,6 +319,84 @@ - (void)swapItem:(CSLinearLayoutItem *)firstItem withItem:(CSLinearLayoutItem *) [self setNeedsLayout]; } +#pragma mark Content Shortcuts + +- (CSLinearLayoutItem*)addImageNamed:(NSString*)imageName; +{ + UIImage* image = [UIImage imageNamed:imageName]; + UIImageView* imageView = [[UIImageView alloc] initWithImage:image]; + + if (image && imageView) { + // create layout item + CSLinearLayoutItem *item = [CSLinearLayoutItem layoutItemForView:imageView]; + item.horizontalAlignment = CSLinearLayoutItemHorizontalAlignmentCenter; + item.verticalAlignment = CSLinearLayoutItemVerticalAlignmentCenter; + [self addItem:item]; + return item; + } + + return nil; +} + +- (CSLinearLayoutItem*)addText:(NSString*)text; +{ + return [self addText:text font:self.defaultFont]; +} + +- (CSLinearLayoutItem*)addText:(NSString*)text font:(UIFont*)font; +{ + return [self addText:text font:font frontMargin:self.defaultMargin]; +} + +- (CSLinearLayoutItem*)addText:(NSString*)text frontMargin:(CGFloat)frontMargin; +{ + return [self addText:text font:self.defaultFont frontMargin:frontMargin]; +} + +- (CSLinearLayoutItem*)addText:(NSString*)text font:(UIFont*)font frontMargin:(CGFloat)frontMargin; +{ + BOOL isVertical = (self.orientation == CSLinearLayoutViewOrientationVertical); + CGFloat maxSize = self.frame.size.width - self.contentInset.left - self.contentInset.right; + if (!isVertical) { + maxSize = self.frame.size.height - self.contentInset.top - self.contentInset.bottom; + } + + // create label + CGRect frame = CGRectMake(0, 0, isVertical ? maxSize : CGFLOAT_MAX, + !isVertical ? maxSize : CGFLOAT_MAX); + UILabel* label = [[UILabel alloc] initWithFrame:frame]; + label.backgroundColor = [UIColor clearColor]; + label.textColor = self.textColor; + label.font = font; + label.text = text; + label.numberOfLines = 0; + label.lineBreakMode = UILineBreakModeWordWrap; + [label sizeToFit]; + + // create layout item + CSLinearLayoutItem *item = [CSLinearLayoutItem layoutItemForView:label]; + item.padding = CSLinearLayoutMakePadding(isVertical ? frontMargin : 0, + !isVertical ? frontMargin : 0, + 0, 0); + item.verticalAlignment = CSLinearLayoutItemVerticalAlignmentCenter; + item.fillMode = CSLinearLayoutItemFillModeStretch; + [self addItem:item]; + + return item; +} + +- (CSLinearLayoutItem*)addTitle:(NSString*)text; +{ + CGFloat margin = (self.items.count > 0) ? self.titleMargin : 0; + return [self addText:text font:self.titleFont frontMargin:margin]; +} + +- (CSLinearLayoutItem*)addSubtitle:(NSString*)text; +{ + CGFloat margin = (self.items.count > 0) ? self.subtitleMargin : 0; + return [self addText:text font:self.subtitleFont frontMargin:margin]; +} + @end #pragma mark - From cda57edd87f653ade514084c364878ca39b3a657 Mon Sep 17 00:00:00 2001 From: Markus Emrich Date: Mon, 11 Feb 2013 23:13:37 +0100 Subject: [PATCH 6/7] performance increase | only relayout, if needed. Because layoutSubviews is called on every scroll movement... --- CSLinearLayoutView/CSLinearLayoutView.m | 33 ++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/CSLinearLayoutView/CSLinearLayoutView.m b/CSLinearLayoutView/CSLinearLayoutView.m index ec78383..85587c0 100644 --- a/CSLinearLayoutView/CSLinearLayoutView.m +++ b/CSLinearLayoutView/CSLinearLayoutView.m @@ -9,8 +9,9 @@ #import "CSLinearLayoutView.h" @interface CSLinearLayoutView() -@property (nonatomic, strong) NSMutableArray *items; -@property (nonatomic, readonly) CGSize innerFrameSize; +@property (nonatomic, strong) NSMutableArray *items; // private setter for items +@property (nonatomic, readonly) CGSize innerFrameSize; // available space for content without insets +@property (nonatomic) BOOL contentsDidChange; // saves, if relayout is needed - (void)setup; - (void)adjustFrameSize; - (void)adjustContentSize; @@ -68,7 +69,27 @@ - (void)restoreDefaultFormats { #pragma mark - Layout +- (void)setFrame:(CGRect)frame; +{ + [super setFrame: frame]; + self.contentsDidChange = YES; +} + +- (void)setNeedsLayout; +{ + [super setNeedsLayout]; + self.contentsDidChange = YES; +} + - (void)layoutSubviews { + [super layoutSubviews]; + + // only relayout if explicitly needed + // (because layout subviews is called on every contentOffset change) + if (!self.contentsDidChange) { + return; + } + self.contentsDidChange = NO; CGFloat relativePosition = 0.0; CGFloat absolutePosition = 0.0; @@ -146,9 +167,9 @@ - (void)layoutSubviews { - (void)adjustFrameSize { if (self.orientation == CSLinearLayoutViewOrientationHorizontal) { - self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.layoutOffset, self.innerFrameSize.height); + self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.layoutOffset, self.frame.size.height); } else { - self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.innerFrameSize.width, self.layoutOffset); + self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, self.layoutOffset); } } @@ -196,6 +217,8 @@ - (void)addSubview:(UIView *)view { if (self.autoAdjustContentSize == YES) { [self adjustContentSize]; } + + self.contentsDidChange = YES; } @@ -217,6 +240,7 @@ - (void)removeItem:(CSLinearLayoutItem *)linearLayoutItem { [linearLayoutItem.view removeFromSuperview]; [self.items removeObject:linearLayoutItem]; + self.contentsDidChange = YES; } - (void)removeAllItems { @@ -225,6 +249,7 @@ - (void)removeAllItems { [item.view removeFromSuperview]; } [self.items removeAllObjects]; + self.contentsDidChange = YES; } - (void)insertItem:(CSLinearLayoutItem *)newItem beforeItem:(CSLinearLayoutItem *)existingItem { From fc03990fed3ae1d12635fc40efaba5012a68660e Mon Sep 17 00:00:00 2001 From: Markus Emrich Date: Tue, 12 Feb 2013 23:35:49 +0100 Subject: [PATCH 7/7] added DEMO controller for adding shortcuts, added shadow settings --- CSLinearLayoutView/CSLinearLayoutView.h | 8 ++- CSLinearLayoutView/CSLinearLayoutView.m | 8 +++ .../project.pbxproj | 18 ++++-- Demo/Classes/CSMainViewController.m | 18 +++++- .../Tests/CSShortcutTestViewController.h | 13 ++++ .../Tests/CSShortcutTestViewController.m | 59 ++++++++++++++++++ Demo/{ => Resources}/Default-568h@2x.png | Bin Demo/Resources/github-logo@2x.png | Bin 0 -> 30680 bytes 8 files changed, 114 insertions(+), 10 deletions(-) create mode 100644 Demo/Classes/Tests/CSShortcutTestViewController.h create mode 100644 Demo/Classes/Tests/CSShortcutTestViewController.m rename Demo/{ => Resources}/Default-568h@2x.png (100%) create mode 100644 Demo/Resources/github-logo@2x.png diff --git a/CSLinearLayoutView/CSLinearLayoutView.h b/CSLinearLayoutView/CSLinearLayoutView.h index cc4cee2..6285fb4 100644 --- a/CSLinearLayoutView/CSLinearLayoutView.h +++ b/CSLinearLayoutView/CSLinearLayoutView.h @@ -68,14 +68,16 @@ typedef enum { // configuration @property (nonatomic, strong) UIColor *textColor; +@property (nonatomic, strong) UIColor *shadowColor; +@property (nonatomic, assign) CGSize shadowOffset; @property (nonatomic, strong) UIFont *defaultFont; @property (nonatomic, strong) UIFont *subtitleFont; @property (nonatomic, strong) UIFont *titleFont; -@property (nonatomic, assign) NSUInteger defaultMargin; -@property (nonatomic, assign) NSUInteger subtitleMargin; -@property (nonatomic, assign) NSUInteger titleMargin; +@property (nonatomic, assign) CGFloat defaultMargin; +@property (nonatomic, assign) CGFloat subtitleMargin; +@property (nonatomic, assign) CGFloat titleMargin; // shortcuts diff --git a/CSLinearLayoutView/CSLinearLayoutView.m b/CSLinearLayoutView/CSLinearLayoutView.m index 85587c0..f113d4d 100644 --- a/CSLinearLayoutView/CSLinearLayoutView.m +++ b/CSLinearLayoutView/CSLinearLayoutView.m @@ -58,6 +58,8 @@ - (void)setup { - (void)restoreDefaultFormats { // adding shortcut settings self.textColor = [UIColor blackColor]; + self.shadowColor = [UIColor clearColor]; + self.shadowOffset = CGSizeMake(1, 1); self.defaultFont = [UIFont systemFontOfSize: 14]; self.subtitleFont = [UIFont boldSystemFontOfSize: 14]; self.titleFont = [UIFont boldSystemFontOfSize: 18]; @@ -390,8 +392,14 @@ - (CSLinearLayoutItem*)addText:(NSString*)text font:(UIFont*)font frontMargin:(C CGRect frame = CGRectMake(0, 0, isVertical ? maxSize : CGFLOAT_MAX, !isVertical ? maxSize : CGFLOAT_MAX); UILabel* label = [[UILabel alloc] initWithFrame:frame]; + label.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin; + if (!isVertical) { + label.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleRightMargin; + } label.backgroundColor = [UIColor clearColor]; label.textColor = self.textColor; + label.shadowColor = self.shadowColor; + label.shadowOffset = self.shadowOffset; label.font = font; label.text = text; label.numberOfLines = 0; diff --git a/Demo/CSLinearLayoutView.xcodeproj/project.pbxproj b/Demo/CSLinearLayoutView.xcodeproj/project.pbxproj index ed7821d..fe183f2 100644 --- a/Demo/CSLinearLayoutView.xcodeproj/project.pbxproj +++ b/Demo/CSLinearLayoutView.xcodeproj/project.pbxproj @@ -30,7 +30,9 @@ 15F8EFC4151F911900C6CEBF /* CSAlignmentViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 15F8EFC3151F911900C6CEBF /* CSAlignmentViewController.m */; }; 15F8EFC6151F91D900C6CEBF /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15F8EFC5151F91D900C6CEBF /* QuartzCore.framework */; }; 15F8EFC8151F91F100C6CEBF /* CSAlignmentViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 15F8EFC7151F91F100C6CEBF /* CSAlignmentViewController.xib */; }; - E02E749616850224000A8279 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = E02E749516850224000A8279 /* Default-568h@2x.png */; }; + D286566D16CAE76800932E46 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D286566B16CAE76800932E46 /* Default-568h@2x.png */; }; + D286566E16CAE76800932E46 /* github-logo@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D286566C16CAE76800932E46 /* github-logo@2x.png */; }; + D2EE864816CAE56600AC369A /* CSShortcutTestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D2EE864716CAE56600AC369A /* CSShortcutTestViewController.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -73,7 +75,10 @@ 15F8EFC3151F911900C6CEBF /* CSAlignmentViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSAlignmentViewController.m; sourceTree = ""; }; 15F8EFC5151F91D900C6CEBF /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 15F8EFC7151F91F100C6CEBF /* CSAlignmentViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CSAlignmentViewController.xib; sourceTree = ""; }; - E02E749516850224000A8279 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "../Default-568h@2x.png"; sourceTree = ""; }; + D286566B16CAE76800932E46 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; + D286566C16CAE76800932E46 /* github-logo@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "github-logo@2x.png"; sourceTree = ""; }; + D2EE864616CAE56600AC369A /* CSShortcutTestViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSShortcutTestViewController.h; sourceTree = ""; }; + D2EE864716CAE56600AC369A /* CSShortcutTestViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSShortcutTestViewController.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -94,7 +99,8 @@ 15073375154DD47100DA2877 /* Resources */ = { isa = PBXGroup; children = ( - E02E749516850224000A8279 /* Default-568h@2x.png */, + D286566B16CAE76800932E46 /* Default-568h@2x.png */, + D286566C16CAE76800932E46 /* github-logo@2x.png */, 15073377154DD54400DA2877 /* lorem.txt */, ); path = Resources; @@ -194,6 +200,8 @@ 15F8EFC2151F911900C6CEBF /* CSAlignmentViewController.h */, 15F8EFC3151F911900C6CEBF /* CSAlignmentViewController.m */, 15F8EFC7151F91F100C6CEBF /* CSAlignmentViewController.xib */, + D2EE864616CAE56600AC369A /* CSShortcutTestViewController.h */, + D2EE864716CAE56600AC369A /* CSShortcutTestViewController.m */, ); name = Tests; path = Classes/Tests; @@ -269,7 +277,8 @@ 15073378154DD54400DA2877 /* lorem.txt in Resources */, 15F52BED154DDE260084DFB1 /* CSBulletListItemView.xib in Resources */, 15F52BF0154DEED40084DFB1 /* CSBulletListViewController.xib in Resources */, - E02E749616850224000A8279 /* Default-568h@2x.png in Resources */, + D286566D16CAE76800932E46 /* Default-568h@2x.png in Resources */, + D286566E16CAE76800932E46 /* github-logo@2x.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -294,6 +303,7 @@ 15F52BE5154DDD3E0084DFB1 /* CSBulletListViewController.m in Sources */, 15F52BE8154DDDA10084DFB1 /* CSBulletListView.m in Sources */, 15F52BEB154DDE000084DFB1 /* CSBulletListItemView.m in Sources */, + D2EE864816CAE56600AC369A /* CSShortcutTestViewController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Demo/Classes/CSMainViewController.m b/Demo/Classes/CSMainViewController.m index c6b4908..a624542 100644 --- a/Demo/Classes/CSMainViewController.m +++ b/Demo/Classes/CSMainViewController.m @@ -12,6 +12,7 @@ #import "CSOrientationSwitchViewController.h" #import "CSAlignmentViewController.h" #import "CSBulletListViewController.h" +#import "CSShortcutTestViewController.h" @implementation CSMainViewController @@ -21,6 +22,7 @@ - (id)init { self = [super init]; if (self) { self.title = @"CSLinearLayoutView"; + self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Back" style:UIBarButtonItemStyleBordered target:nil action:nil]; } return self; } @@ -66,9 +68,15 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath break; } + case 5: { + viewController = [[[CSShortcutTestViewController alloc] init] autorelease]; + break; + } + } if (viewController != nil) { + viewController.title = [tableView cellForRowAtIndexPath:indexPath].textLabel.text; [self.navigationController pushViewController:viewController animated:YES]; } @@ -78,7 +86,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath #pragma mark - UITableView Data Source Methods - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return 5; + return 6; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { @@ -108,8 +116,12 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N cell.textLabel.text = @"Alignment"; break; - case 4: - cell.textLabel.text = @"Sample Bullet List"; + case 4: + cell.textLabel.text = @"Sample Bullet List"; + break; + + case 5: + cell.textLabel.text = @"Adding Shortcuts"; break; } diff --git a/Demo/Classes/Tests/CSShortcutTestViewController.h b/Demo/Classes/Tests/CSShortcutTestViewController.h new file mode 100644 index 0000000..5997120 --- /dev/null +++ b/Demo/Classes/Tests/CSShortcutTestViewController.h @@ -0,0 +1,13 @@ +// +// CSShortcutTestViewController.h +// CSLinearLayoutView +// +// Created by Markus Emrich on 12.02.13. +// Copyright (c) 2013 Charles Scalesse. All rights reserved. +// + +#import + +@interface CSShortcutTestViewController : UIViewController + +@end diff --git a/Demo/Classes/Tests/CSShortcutTestViewController.m b/Demo/Classes/Tests/CSShortcutTestViewController.m new file mode 100644 index 0000000..12ebae2 --- /dev/null +++ b/Demo/Classes/Tests/CSShortcutTestViewController.m @@ -0,0 +1,59 @@ +// +// CSShortcutTestViewController.m +// CSLinearLayoutView +// +// Created by Markus Emrich on 12.02.13. +// Copyright (c) 2013 Charles Scalesse. All rights reserved. +// + +#import "CSLinearLayoutView.h" + +#import "CSShortcutTestViewController.h" + + +@interface CSShortcutTestViewController () +@property (nonatomic, readonly) CSLinearLayoutView* view; +@end + +@implementation CSShortcutTestViewController + + +- (void)loadView; +{ + self.view = [[CSLinearLayoutView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame]; + self.view.contentInset = UIEdgeInsetsMake(20, 20, 20, 20); + self.view.backgroundColor = [UIColor scrollViewTexturedBackgroundColor]; + self.view.textColor = [UIColor whiteColor]; + self.view.shadowColor = [UIColor colorWithWhite:0 alpha:0.3]; + self.view.shadowOffset = CGSizeMake(-1, -1); + self.view.titleMargin = 30; + + [self.view addImageNamed:@"github-logo"]; + [self.view addTitle:self.title]; + [self.view addSubtitle:@"Easily add text and images with only one line of code."]; + [self.view addText:@"The following code is all you need, to create the contents, of this view. The most important methods are addText: and addImageNamed:."]; + [self.view addTitle:@"Code"]; + + self.view.defaultMargin = -8; + [self addTextInCourier:@"CSLinearLayoutView *csView;"]; + [self addTextInCourier:@"csView = [CSLinearLayoutView new];"]; + [self addTextInCourier:@"[csView addImageNamed:@\"github-logo\"];"]; + [self addTextInCourier:@"[csView addTitle:titleText1];"]; + [self addTextInCourier:@"[csView addSubtitle:subtitleText];"]; + [self addTextInCourier:@"[csView addText:descriptionText];"]; + [self addTextInCourier:@"[csView addTitle:titleText2];"]; +} + +- (CSLinearLayoutView*)view; +{ + return (CSLinearLayoutView*)[super view]; +} + +- (void)addTextInCourier:(NSString*)text; +{ + UILabel *label = (UILabel*)[self.view addText:text].view; + label.font = [UIFont fontWithName:@"Courier" size:12]; + [label sizeToFit]; +} + +@end diff --git a/Demo/Default-568h@2x.png b/Demo/Resources/Default-568h@2x.png similarity index 100% rename from Demo/Default-568h@2x.png rename to Demo/Resources/Default-568h@2x.png diff --git a/Demo/Resources/github-logo@2x.png b/Demo/Resources/github-logo@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8c475aae74d775c88113ef9bfcd92d5a2775c232 GIT binary patch literal 30680 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 P00000NkvXXu0mjf`=@8$ literal 0 HcmV?d00001