From 638d1ec19ae8df469668eb3b4245e0cfb21c97f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Gra=CC=88tzer?= Date: Tue, 12 Jun 2012 00:43:14 +0200 Subject: [PATCH] Added cool demo and fixed some bugs --- Demo/SGTabs.xcodeproj/project.pbxproj | 14 +++- Demo/SGTabs/SGAppDelegate.h | 1 - Demo/SGTabs/SGAppDelegate.m | 24 ++---- Demo/SGTabs/SGViewController.m | 34 ++++++++ Demo/SGTabs/en.lproj/SGViewController.xib | 31 ++++++- README.md | 16 +++- Source/SGTabDefines.h | 41 ++++++++++ Source/SGTabView.h | 8 +- Source/SGTabView.m | 94 ++++++++-------------- Source/SGTabsView.m | 46 +++++------ Source/SGTabsViewController.m | 75 ++++++++++------- Source/SGToolbar.m | 24 ++---- Source/cross.png | Bin 0 -> 1394 bytes screen.png | Bin 0 -> 20123 bytes screen_Toolbar.png | Bin 0 -> 24367 bytes 15 files changed, 248 insertions(+), 160 deletions(-) create mode 100644 Source/SGTabDefines.h create mode 100644 Source/cross.png create mode 100644 screen.png create mode 100644 screen_Toolbar.png diff --git a/Demo/SGTabs.xcodeproj/project.pbxproj b/Demo/SGTabs.xcodeproj/project.pbxproj index 6dbf0fc..6d56e31 100644 --- a/Demo/SGTabs.xcodeproj/project.pbxproj +++ b/Demo/SGTabs.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + F450946C15856EC800B7B1C6 /* cross.png in Resources */ = {isa = PBXBuildFile; fileRef = F450946B15856EC800B7B1C6 /* cross.png */; }; F470D27F1580EA5100ED3644 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F470D27E1580EA5100ED3644 /* UIKit.framework */; }; F470D2811580EA5100ED3644 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F470D2801580EA5100ED3644 /* Foundation.framework */; }; F470D2831580EA5100ED3644 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F470D2821580EA5100ED3644 /* CoreGraphics.framework */; }; @@ -22,6 +23,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + F450946B15856EC800B7B1C6 /* cross.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = cross.png; sourceTree = ""; }; F470D27A1580EA5100ED3644 /* SGTabs.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SGTabs.app; sourceTree = BUILT_PRODUCTS_DIR; }; F470D27E1580EA5100ED3644 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; F470D2801580EA5100ED3644 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; @@ -41,16 +43,17 @@ F470D2AB1580ECDB00ED3644 /* SGTabsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGTabsView.m; sourceTree = ""; }; F470D2AD1580ECE700ED3644 /* SGTabView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGTabView.h; sourceTree = ""; }; F470D2AE1580ECE700ED3644 /* SGTabView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGTabView.m; sourceTree = ""; }; - F470D2B01580ED3000ED3644 /* SGToolbar.h */ = {isa = PBXFileReference; fileEncoding = 4; path = SGToolbar.h; sourceTree = ""; }; + F470D2B01580ED3000ED3644 /* SGToolbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGToolbar.h; sourceTree = ""; }; F470D2B11580ED3000ED3644 /* SGToolbar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGToolbar.m; sourceTree = ""; }; F476BFBF15816C8E00BABEEB /* SGTabView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGTabView.h; sourceTree = ""; }; F476BFC015816C8E00BABEEB /* SGTabView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGTabView.m; sourceTree = ""; }; - F476BFC115816C8E00BABEEB /* SGToolbar.h */ = {isa = PBXFileReference; fileEncoding = 4; path = SGToolbar.h; sourceTree = ""; }; - F476BFC215816C8E00BABEEB /* SGToolbar.m */ = {isa = PBXFileReference; fileEncoding = 4; path = SGToolbar.m; sourceTree = ""; }; + F476BFC115816C8E00BABEEB /* SGToolbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGToolbar.h; sourceTree = ""; }; + F476BFC215816C8E00BABEEB /* SGToolbar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGToolbar.m; sourceTree = ""; }; F476BFC315816C8E00BABEEB /* SGTabsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGTabsView.h; sourceTree = ""; }; F476BFC415816C8E00BABEEB /* SGTabsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGTabsView.m; sourceTree = ""; }; F476BFC515816C8E00BABEEB /* SGTabsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGTabsViewController.h; sourceTree = ""; }; F476BFC615816C8E00BABEEB /* SGTabsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGTabsViewController.m; sourceTree = ""; }; + F493636B158686E200FBD5F3 /* SGTabDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SGTabDefines.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -124,6 +127,7 @@ F470D2A61580EAD700ED3644 /* Source */ = { isa = PBXGroup; children = ( + F450946B15856EC800B7B1C6 /* cross.png */, F470D2A71580EAD700ED3644 /* SGTabsViewController.h */, F470D2A81580EAD700ED3644 /* SGTabsViewController.m */, F470D2AA1580ECDB00ED3644 /* SGTabsView.h */, @@ -132,6 +136,7 @@ F470D2AE1580ECE700ED3644 /* SGTabView.m */, F470D2B01580ED3000ED3644 /* SGToolbar.h */, F470D2B11580ED3000ED3644 /* SGToolbar.m */, + F493636B158686E200FBD5F3 /* SGTabDefines.h */, ); name = Source; path = ../Source; @@ -207,6 +212,7 @@ files = ( F470D2891580EA5100ED3644 /* InfoPlist.strings in Resources */, F470D2951580EA5100ED3644 /* SGViewController.xib in Resources */, + F450946C15856EC800B7B1C6 /* cross.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -303,6 +309,7 @@ GCC_PREFIX_HEADER = "SGTabs/SGTabs-Prefix.pch"; INFOPLIST_FILE = "SGTabs/SGTabs-Info.plist"; PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = 2; WRAPPER_EXTENSION = app; }; name = Debug; @@ -314,6 +321,7 @@ GCC_PREFIX_HEADER = "SGTabs/SGTabs-Prefix.pch"; INFOPLIST_FILE = "SGTabs/SGTabs-Info.plist"; PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = 2; WRAPPER_EXTENSION = app; }; name = Release; diff --git a/Demo/SGTabs/SGAppDelegate.h b/Demo/SGTabs/SGAppDelegate.h index 5d1a06b..addba77 100644 --- a/Demo/SGTabs/SGAppDelegate.h +++ b/Demo/SGTabs/SGAppDelegate.h @@ -25,7 +25,6 @@ @class SGTabsViewController; @interface SGAppDelegate : UIResponder { - NSTimer *timer; } @property (strong, nonatomic) UIWindow *window; diff --git a/Demo/SGTabs/SGAppDelegate.m b/Demo/SGTabs/SGAppDelegate.m index 1f500d6..7b7d8a1 100644 --- a/Demo/SGTabs/SGAppDelegate.m +++ b/Demo/SGTabs/SGAppDelegate.m @@ -34,32 +34,24 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. -// if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { -// self.viewController = [[SGViewController alloc] initWithNibName:@"SGViewController_iPhone" bundle:nil]; -// } else { -// self.viewController = [[SGViewController alloc] initWithNibName:@"SGViewController_iPad" bundle:nil]; -// } self.tabController = [[SGTabsViewController alloc] initEditable:YES]; self.window.rootViewController = self.tabController; [self.window makeKeyAndVisible]; - [self openTab]; - timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(openTab) userInfo:nil repeats:YES]; + + [self performSelector:@selector(openTab) withObject:nil afterDelay:1]; return YES; } - (void)openTab { - if (4 > self.tabController.count) { // You can add up to tabController.maxCount Tabs - SGViewController *vc = [[SGViewController alloc] - initWithNibName:NSStringFromClass([SGViewController class]) - bundle:nil]; - vc.title = [NSString stringWithFormat:@"Tab %i content", self.tabController.count+1]; - [self.tabController addTab:vc]; - } else if (self.tabController.count == 4){ - [self.tabController setToolbarHidden:NO animated:YES]; - } + [self.tabController setToolbarHidden:NO animated:YES]; + SGViewController *vc = [[SGViewController alloc] + initWithNibName:NSStringFromClass([SGViewController class]) + bundle:nil]; + vc.title = [NSString stringWithFormat:@"Tab %i content", self.tabController.count+1]; + [self.tabController addTab:vc]; } @end diff --git a/Demo/SGTabs/SGViewController.m b/Demo/SGTabs/SGViewController.m index b48d9f9..925a83e 100644 --- a/Demo/SGTabs/SGViewController.m +++ b/Demo/SGTabs/SGViewController.m @@ -34,6 +34,16 @@ - (void)viewDidLoad [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. self.label.text = self.title; + + UIBarButtonItem *space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace + target:nil action:nil]; + UIBarButtonItem *trash = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemTrash + target:self + action:@selector(remove:)]; + UIBarButtonItem *add = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd + target:self + action:@selector(add:)]; + self.toolbarItems = [NSArray arrayWithObjects:space, trash, add, nil]; } - (void)viewDidUnload @@ -43,6 +53,14 @@ - (void)viewDidUnload // Release any retained subviews of the main view. } +- (void)viewWillDisappear:(BOOL)animated { + NSLog(@"viewWillDisappear"); +} + +- (void)viewDidDisappear:(BOOL)animated { + NSLog(@"ViewDidDisappear"); +} + - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { @@ -51,5 +69,21 @@ - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interface return YES; } } + +- (IBAction)remove:(id)sender { + SGTabsViewController *tabs = (SGTabsViewController *) self.parentViewController; + [tabs removeViewController:self]; +} + +- (IBAction)add:(id)sender { + SGTabsViewController *tabs = (SGTabsViewController *) self.parentViewController; + + SGViewController *vc = [[SGViewController alloc] + initWithNibName:NSStringFromClass([SGViewController class]) + bundle:nil]; + vc.title = [NSString stringWithFormat:@"Tab %i content", tabs.count+1]; + [tabs addTab:vc]; + +} @end diff --git a/Demo/SGTabs/en.lproj/SGViewController.xib b/Demo/SGTabs/en.lproj/SGViewController.xib index 78cf45e..5c32c46 100644 --- a/Demo/SGTabs/en.lproj/SGViewController.xib +++ b/Demo/SGTabs/en.lproj/SGViewController.xib @@ -38,8 +38,10 @@ 274 - {{77, 83}, {167, 142}} + {{77, 159}, {167, 142}} + + _NS:9 NO YES @@ -54,6 +56,7 @@ 0 10 + 1 1 35 @@ -67,6 +70,8 @@ {{0, 20}, {320, 460}} + + 3 MQA @@ -143,7 +148,29 @@ 10 - + + + + SGViewController + UIViewController + + label + UILabel + + + label + + label + UILabel + + + + IBProjectSource + ./Classes/SGViewController.h + + + + 0 IBCocoaTouchFramework diff --git a/README.md b/README.md index a41f199..c1213c8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,20 @@ # SGTabs -Tab component for iOS 5+. You can show your ViewControllers in tabs, it is possible to add and remove tabs on the fly +Tab component for iOS 5+. You can show your ViewControllers in tabs, it is possible to add and remove tabs on the fly. + +# Features +- Uses iOS 5 UIViewController Container API +- Add and remove tabs on the fly with animations +- User can remove tabs by pressing an X on a tab. TODO +- Dynamically show and hide a UIToolbar at the top +- Show the UIBarButtonItems in viewController.toolbarItems in the toolbar +- It should be possible to create Safari style apps + +# Screenshots + +![Multiple Tabs open][screen.png "Multiple Tabs open"] + +![Toolbar visible][screen_Toolbar.png "A Toolbar with one element visible"] diff --git a/Source/SGTabDefines.h b/Source/SGTabDefines.h new file mode 100644 index 0000000..c225b4a --- /dev/null +++ b/Source/SGTabDefines.h @@ -0,0 +1,41 @@ +// +// SGTabDefines.h +// SGTabs +// +// Created by simon on 11.06.12. +// +// +// Copyright (c) 2012 Simon Grätzer +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef SGTabs_SGTabConstants_h +#define SGTabs_SGTabConstants_h + +#define kAddTabDuration 0.4 +#define kRemoveTabDuration 0.4 + +#define kTabsToolbarHeigth 10.0 +#define kTabsToolbarHeigthFull 44.0 +#define kTabsHeigth 30.0 + +#define kCornerRadius 7.5 + +#define kShadowRadius 6.0 + +#define kTabColor [[UIColor alloc] initWithWhite:0.85 alpha:1] +#define kTabUnselectedColor [[UIColor alloc] initWithWhite:0.7 alpha:1] +//[[UIColor alloc] initWithWhite:0.6 alpha:1] + +#endif diff --git a/Source/SGTabView.h b/Source/SGTabView.h index c62fa97..202d9ac 100644 --- a/Source/SGTabView.h +++ b/Source/SGTabView.h @@ -23,14 +23,12 @@ #import -@interface SGTabView : UIView { - UIColor *topColor; - UIColor *bottomColor; -} +@interface SGTabView : UIView @property (nonatomic, strong) UILabel *titleLabel; @property (nonatomic, strong) UIButton *closeButton; -@property (nonatomic, assign) BOOL editable; + +@property (nonatomic, strong) UIColor *tabColor; - (id)initWithFrame:(CGRect)frame title:(NSString *)title; diff --git a/Source/SGTabView.m b/Source/SGTabView.m index a038750..7f32ac7 100644 --- a/Source/SGTabView.m +++ b/Source/SGTabView.m @@ -21,14 +21,16 @@ // #import "SGTabView.h" +#import "SGTabDefines.h" + #import -#define kRadius 10.0 -#define kMargin 2*kRadius + @implementation SGTabView -@synthesize titleLabel, editable, closeButton; +@synthesize titleLabel, closeButton; +@synthesize tabColor; - (CGRect)tabRect { return CGRectMake(self.bounds.origin.x, @@ -55,12 +57,14 @@ - (id)initWithFrame:(CGRect)frame title:(NSString *)title self.titleLabel.shadowColor = [UIColor colorWithWhite:1 alpha:0.5]; self.titleLabel.shadowOffset = CGSizeMake(0, 0.5); [self addSubview:self.titleLabel]; - topColor = [[UIColor alloc] initWithWhite:0.9 alpha:1]; - bottomColor = [[UIColor alloc] initWithWhite:0.8 alpha:1]; - self.closeButton = [UIButton buttonWithType:UIButtonTypeCustom]; -// [self.closeButton setImage:[UIImage imageNamed:@"button_close"] +// self.closeButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; +// [self.closeButton setTitle:@"Hello" forState:UIControlStateNormal]; +// [self.closeButton setImage:[UIImage imageNamed:@"cross.png"] // forState:UIControlStateNormal]; + [self addSubview:self.closeButton]; + + self.tabColor = kTabColor; } return self; } @@ -68,9 +72,9 @@ - (id)initWithFrame:(CGRect)frame title:(NSString *)title - (void)layoutSubviews { CGRect inner = [self tabRect]; self.titleLabel.frame = inner; - CGSize size = self.closeButton.frame.size; - self.closeButton.center = CGPointMake(inner.size.width - size.width, - inner.size.height/2); +// inner.origin.x -= 10; +// inner.size.width -=10; +// self.closeButton.frame = inner; } - (void)drawRect:(CGRect)rect { @@ -78,69 +82,39 @@ - (void)drawRect:(CGRect)rect { CGFloat tabLeft = tabRect.origin.x; CGFloat tabRight = tabRect.origin.x + tabRect.size.width; CGFloat tabTop = tabRect.origin.y; - CGFloat tabBottom = tabRect.origin.y + tabRect.size.height + 0.5; + CGFloat tabBottom = tabRect.origin.y + tabRect.size.height; - UIBezierPath *bPath = [UIBezierPath bezierPath]; + CGMutablePathRef path = CGPathCreateMutable(); - [bPath moveToPoint:CGPointMake(tabLeft, tabTop)]; + CGPathMoveToPoint(path, NULL, tabLeft, tabTop); // Top left - [bPath addArcWithCenter:CGPointMake(tabLeft, tabTop + kRadius) radius:kRadius startAngle:3*M_PI_2 endAngle:0 clockwise:YES]; + CGPathAddArc(path, NULL, tabLeft, tabTop + kCornerRadius, kCornerRadius, -M_PI_2, 0, NO); + CGPathAddLineToPoint(path, NULL, tabLeft + kCornerRadius, tabBottom - kCornerRadius); - [bPath addLineToPoint:CGPointMake(tabLeft + kRadius, tabBottom - kRadius)]; // Bottom left - [bPath addArcWithCenter:CGPointMake(tabLeft + 2*kRadius, tabBottom - kRadius) radius:kRadius startAngle:M_PI endAngle:M_PI_2 clockwise:NO]; + CGPathAddArc(path, NULL, tabLeft + 2*kCornerRadius, tabBottom - kCornerRadius, kCornerRadius, M_PI, M_PI_2, YES); + CGPathAddLineToPoint(path, NULL, tabRight - 2*kCornerRadius, tabBottom); - [bPath addLineToPoint:CGPointMake(tabRight - 2*kRadius, tabBottom)]; // Bottom rigth - [bPath addArcWithCenter:CGPointMake(tabRight - 2*kRadius, tabBottom - kRadius) radius:kRadius startAngle:M_PI_2 endAngle:0 clockwise:NO]; + CGPathAddArc(path, NULL, tabRight - 2*kCornerRadius, tabBottom - kCornerRadius, kCornerRadius, M_PI_2, 0, YES); + CGPathAddLineToPoint(path, NULL, tabRight - kCornerRadius, tabTop + kCornerRadius); - [bPath addLineToPoint:CGPointMake(tabRight - kRadius, tabTop + kRadius)]; // Top rigth - [bPath addArcWithCenter:CGPointMake(tabRight, tabTop + kRadius) radius:kRadius startAngle:M_PI endAngle:3*M_PI_2 clockwise:YES]; - - [bPath addLineToPoint:CGPointMake(tabRight, tabTop)]; - [bPath closePath]; - - CGPathRef path = [bPath CGPath]; - - CGContextRef context = UIGraphicsGetCurrentContext(); + CGPathAddArc(path, NULL, tabRight, tabTop + kCornerRadius, kCornerRadius, M_PI, -M_PI_2, NO); + CGPathAddLineToPoint(path, NULL, tabRight, tabTop); + CGPathCloseSubpath(path); + CGContextRef ctx = UIGraphicsGetCurrentContext(); // Fill with current tab color - CGColorRef startColor = [topColor CGColor]; - - CGContextSaveGState(context); - CGContextAddPath(context, path); - CGContextSetFillColorWithColor(context, startColor); - CGContextSetShadow(context, CGSizeMake(0, 5), 3.0); - CGContextFillPath(context); - CGContextRestoreGState(context); - - // Render the interior of the tab path using the gradient. - - // Configure a linear gradient which adds a simple white highlight on the top. - - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - CGFloat locations[] = { 0.0, 0.5 }; - - - CGColorRef endColor = [bottomColor CGColor]; - - const void* colors[] = {startColor, endColor}; - - CFArrayRef colorArray = CFArrayCreate(NULL, colors, 2, &kCFTypeArrayCallBacks); - CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, colorArray, locations); - CFRelease(colorArray); + CGColorRef startColor = [self.tabColor CGColor]; - CGPoint startPoint = CGPointMake(CGRectGetMidX(tabRect), tabRect.origin.y); - CGPoint endPoint = CGPointMake(CGRectGetMidX(tabRect), tabRect.origin.y + tabRect.size.height); + CGContextSaveGState(ctx); + CGContextAddPath(ctx, path); + CGContextSetFillColorWithColor(ctx, startColor); + CGContextSetShadow(ctx, CGSizeMake(0, -1), kShadowRadius); + CGContextFillPath(ctx); + CGContextRestoreGState(ctx); - CGContextSaveGState(context); - CGContextAddPath(context, path); - CGContextClip(context); - CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0); - CGContextRestoreGState(context); - CGGradientRelease(gradient); - CGColorSpaceRelease(colorSpace); } @end diff --git a/Source/SGTabsView.m b/Source/SGTabsView.m index 7a582bf..e522789 100644 --- a/Source/SGTabsView.m +++ b/Source/SGTabsView.m @@ -23,6 +23,7 @@ #import "SGTabsView.h" #import "SGTabView.h" #import "SGTabsViewController.h" +#import "SGTabDefines.h" #define kMARGIN 2.5 @@ -37,7 +38,7 @@ - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { - self.backgroundColor = [UIColor clearColor]; + self.backgroundColor = [UIColor grayColor]; self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin| UIViewAutoresizingFlexibleLeftMargin; self.autoresizesSubviews = YES; } @@ -51,13 +52,17 @@ - (NSMutableArray *)tabs { return _tabs; } +- (void)layoutSubviews{ + [self resizeTabs]; +} + #pragma mark - Tab operations - (void)addTab:(NSString *)title { CGFloat width = [self tabWidth:self.tabs.count+1]; CGRect frame = CGRectMake(self.bounds.size.width, 0, width, self.bounds.size.height - kMARGIN); SGTabView *newTab = [[SGTabView alloc] initWithFrame:frame title:title]; - newTab.editable = self.tabsController.editable; + newTab.closeButton.hidden = !self.tabsController.editing; UITapGestureRecognizer *tapG = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]; @@ -83,8 +88,10 @@ - (void)addTab:(NSString *)title { if (i == self.tabs.count-1) { tab.alpha = 1.0; [self bringSubviewToFront:tab]; - } else - tab.alpha = 0.6; + } else { + tab.alpha = 0.7; + } + [tab setNeedsDisplay]; } } @@ -94,29 +101,20 @@ - (void)removeTab:(NSUInteger)index { [self.tabs removeObjectAtIndex:index]; [oldTab removeFromSuperview]; [self resizeTabs]; -// [UIView transitionWithView:self -// duration:0.3 -// options:UIViewAnimationOptionCurveEaseInOut -// animations:^{ -// [oldTab removeFromSuperview]; -// [self resizeTabs]; -// } -// completion:NULL]; } } - (void)setSelected:(NSUInteger)selected { - if (_selected != selected) { - _selected = selected; - for (int i = 0; i < self.tabs.count; i++) { - SGTabView *tab = [self.tabs objectAtIndex:i]; - if (i == selected) { - tab.alpha = 1.0; - [self bringSubviewToFront:tab]; - } else { - tab.alpha = 0.6; - } + _selected = selected; + for (int i = 0; i < self.tabs.count; i++) { + SGTabView *tab = [self.tabs objectAtIndex:i]; + if (i == selected) { + tab.alpha = 1.0; + [self bringSubviewToFront:tab]; + } else { + tab.alpha = 0.7; } + [tab setNeedsDisplay]; } } @@ -126,8 +124,8 @@ - (CGFloat)tabWidth:(NSUInteger)count { if (count > 0) width = (self.bounds.size.width - 2*kMARGIN)/count; else - width = 300.0; - return MIN(width, 300.0); + width = 360.0; + return MIN(width, 360.0); } diff --git a/Source/SGTabsViewController.m b/Source/SGTabsViewController.m index 15c1966..3e773ba 100644 --- a/Source/SGTabsViewController.m +++ b/Source/SGTabsViewController.m @@ -24,10 +24,8 @@ #import "SGToolbar.h" #import "SGTabsView.h" #import "SGTabView.h" +#import "SGTabDefines.h" -#define kTabsTopViewHeigth 10.0 -#define kTabsTopViewHeigthFull 44.0 -#define kTabsHeigth 30.0 @interface SGTabsViewController () @property (nonatomic, strong) UIView *headerView; @@ -67,7 +65,6 @@ - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interface } - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { - [self.tabsView resizeTabs]; CGRect head = self.headerView.frame; CGRect bounds = self.view.bounds; _contentFrame = CGRectMake(bounds.origin.x, @@ -82,14 +79,14 @@ - (void)loadView { CGRect bounds = self.view.bounds; - CGRect head = CGRectMake(bounds.origin.x, bounds.origin.y, bounds.size.width, kTabsTopViewHeigth + kTabsHeigth); + CGRect head = CGRectMake(bounds.origin.x, bounds.origin.y, bounds.size.width, kTabsToolbarHeigth + kTabsHeigth); self.headerView = [[UIView alloc] initWithFrame:head]; self.headerView.autoresizingMask = UIViewAutoresizingFlexibleWidth; - CGRect frame = CGRectMake(head.origin.x, head.origin.y, head.size.width, kTabsTopViewHeigth); + CGRect frame = CGRectMake(head.origin.x, head.origin.y, head.size.width, kTabsToolbarHeigth); _toolbar = [[SGToolbar alloc] initWithFrame:frame]; - frame = CGRectMake(head.origin.x, kTabsTopViewHeigth, head.size.width, kTabsHeigth); + frame = CGRectMake(head.origin.x, kTabsToolbarHeigth, head.size.width, kTabsHeigth); _tabsView = [[SGTabsView alloc] initWithFrame:frame]; _tabsView.tabsController = self; @@ -118,9 +115,12 @@ - (void)addTab:(UIViewController *)viewController { [self addChildViewController:viewController]; viewController.view.frame = _contentFrame; + if (_toobarVisible) + [self.toolbar setItems:viewController.toolbarItems animated:YES]; + // Add tab selects automatically the new tab [UIView transitionWithView:self.view - duration:0.5 + duration:kAddTabDuration options:UIViewAnimationOptionAllowAnimatedContent animations:^{ [self.tabsView addTab:viewController.title]; @@ -150,14 +150,16 @@ - (void)showViewController:(UIViewController *)viewController index:(NSUInteger) if ([self.delegate respondsToSelector:@selector(willShowTab:)]) { [self.delegate willShowTab:viewController]; } - self.tabsView.selected = index; + + if (_toobarVisible) + [self.toolbar setItems:viewController.toolbarItems animated:YES]; [self transitionFromViewController:self.currentViewController toViewController:viewController duration:0 options:UIViewAnimationOptionAllowAnimatedContent animations:^{ - + self.tabsView.selected = index; viewController.view.frame = _contentFrame; } completion:^(BOOL finished) { @@ -180,40 +182,47 @@ - (void)removeViewController:(UIViewController *)viewController index:(NSUIntege [self.delegate willRemoveTab:viewController]; } - if (self.currentViewController == viewController) { - if (index < self.count - 1) - index++; - else if (index > 0) - index--; - else {// View controller is the last one - [viewController willMoveToParentViewController:nil]; - [viewController viewWillDisappear:NO]; - [viewController.view removeFromSuperview]; - [viewController viewDidDisappear:NO]; - [viewController removeFromParentViewController]; - _currentViewController = nil; - return; - } + [self.tabContents removeObjectAtIndex:index]; + if (self.tabContents.count == 0) {//View controller was the last one + [viewController willMoveToParentViewController:nil]; + _currentViewController = nil; + [UIView transitionWithView:self.tabsView + duration:kRemoveTabDuration + options:0 + animations:^{ + [viewController viewWillDisappear:NO]; + [viewController.view removeFromSuperview]; + [viewController viewDidDisappear:NO]; + [self.tabsView removeTab:index]; + [self.toolbar setItems:nil animated:NO]; + } + completion:^(BOOL finished){ + [viewController removeFromParentViewController]; + }]; + return; + } else if (index >= self.tabContents.count) { + index = self.tabContents.count-1; } UIViewController *to = [self.tabContents objectAtIndex:index]; - [self.tabContents removeObjectAtIndex:index]; [viewController willMoveToParentViewController:nil]; [UIView transitionWithView:self.view - duration:0.5 + duration:kRemoveTabDuration options:UIViewAnimationOptionAllowAnimatedContent | UIViewAnimationOptionCurveEaseInOut animations:^{ [self.tabsView removeTab:index]; - to.view.frame = _contentFrame; if (self.currentViewController == viewController) { [viewController viewWillDisappear:YES]; [viewController.view removeFromSuperview]; [viewController viewDidDisappear:YES]; + self.tabsView.selected = index; to.view.frame = _contentFrame; [self.view addSubview:to.view]; + if (_toobarVisible) + [self.toolbar setItems:to.toolbarItems animated:NO]; } } completion:^(BOOL finished){ @@ -234,21 +243,25 @@ - (void)removeIndex:(NSUInteger)index { } - (void)setToolbarHidden:(BOOL)hidden animated:(BOOL)animated { - if (_toobarVisible != hidden) { + if (_toobarVisible != hidden) return; - } - _toobarVisible = !hidden; CGRect head = self.headerView.frame; CGRect toolbar = self.toolbar.frame; CGRect tabs = self.tabsView.frame; - CGFloat toolbarHeight = hidden ? kTabsTopViewHeigth : kTabsTopViewHeigthFull; + CGFloat toolbarHeight = hidden ? kTabsToolbarHeigth : kTabsToolbarHeigthFull; head.size.height = toolbarHeight+kTabsHeigth; toolbar.size.height = toolbarHeight; tabs.origin.y = toolbarHeight; _contentFrame.origin.y = head.size.height; + _toobarVisible = !hidden; + if (_toobarVisible) + [self.toolbar setItems:self.currentViewController.toolbarItems animated:animated]; + else + [self.toolbar setItems:nil animated:animated]; + [UIView animateWithDuration:animated ? 0.3 : 0 animations:^{ self.currentViewController.view.frame = _contentFrame; diff --git a/Source/SGToolbar.m b/Source/SGToolbar.m index 08b45d3..895132a 100644 --- a/Source/SGToolbar.m +++ b/Source/SGToolbar.m @@ -21,6 +21,7 @@ // #import "SGToolbar.h" +#import "SGTabDefines.h" @implementation SGToolbar @@ -36,23 +37,12 @@ - (id)initWithFrame:(CGRect)frame - (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); - - CGFloat shadowRadius = 3.0; - - // We don't want to see the shadow anywhere but above the top edge. - // But the shadow only looks good when we _fill_ a path so we just - // use a rect whose left/right/bottom aren't visible. - - CGFloat bigValue = 1e6; - - CGRect r = CGRectMake(-bigValue, shadowRadius - 0.5, - self.frame.size.width + bigValue, bigValue); - - CGContextSaveGState(context); - CGContextSetShadow(context, CGSizeZero, shadowRadius); - CGContextSetFillColorWithColor(context, [[UIColor alloc] initWithWhite:0.9 alpha:1].CGColor); - CGContextFillRect(context, r); - CGContextRestoreGState(context); + + //CGContextSaveGState(context); + //CGContextSetShadow(context, CGSizeZero, kShadowRadius); + CGContextSetFillColorWithColor(context, [kTabColor CGColor]); + CGContextFillRect(context, self.bounds); + //CGContextRestoreGState(context); } @end diff --git a/Source/cross.png b/Source/cross.png new file mode 100644 index 0000000000000000000000000000000000000000..a912052e147ca346af1c25538c45f28a52d1b8be GIT binary patch literal 1394 zcmV-&1&#WNP)=000F!Nkl1mxJdUi2C87^ZfSOXYak%yU75spU~u=ZQ!HYFX(q` zzo6f({TNWCu>(4t4ogc*+=&zl1sfO`V4j|yGO?y=YirTl+shrV)oR(`;2^WGurRI- z;LSceI}5p74#pUF&(6+ncy@LMS65e(a6&?YV9=?lDU#NoKYy^dw|#SB-pO5E|NxMWF$$0D`;zL3pO@3BqQzZ?c65x zdObWmJh*dPSXf|nb(M4?xdZF#>q(&Q?(Wd*^;~9ZYHCQiD=I3;KMn3cgTa8HpdgZ= zy1Ke|4ILaDz}D85JEyO&FK%vb%m)g9O;1llCX%*Fm8aA;_Vl%uDoM=+#dPyj43F_C0+W@hHqsKH=>pPwK1*yQA7QIMiQ zH#Rn4ZEekMHYzIW)ofE!6Zbf^T8-`P?au=R!0PJiNVD4C-;dMNQ#d+0a*t_fXb=r4 z8ub4D9)W>@+@}5f{7_U>#2p_V9*&2HhtCHEo>v@{XDe@4DwU#_e3F6!V0n3Yl7p6% zlt>0C8R*H$37nmsC4=<#_Qv(~_16Ohz&blSB?BEFAD0wTQcwUaK0aPFq!jy3W(Qqg zUx$^Im0(DXM)U3>;7fo4VAa*tfD3}l}aV6 zs;VN73l9&M+RA^MInG{eY%F<3RVo$M*4F+%mu`D|yWrnwbaXVHo}SDCD`~Q$qa)G_ z`&+%Ot?lcBW@TlGevUdgINU1Z zg_R^pX=$mXkc>UQ*z<0He+cOE@-mc4rR1QDF_e{+eGSmZ$462HOs!TUG&GbuUa3@K zWo1PYSW$y1n_P@Nmni1u=14md)T)`}pu4-fu(Pw{Htgf$gWKC%0AQJ!nWPic($eyI zpsA^;B(uZA!>?wyx3@{lIeUA1?C#l^+u1--w&Cs(|?ySv{tH8?m(%BfH&u&}T|hUE^V)>&d= zVz|vv7wSSv66Mk0BrV3C zYp$X}sh3k&SeU36@XO0f(uW|7JwL)OE-v2HGow4Wdgy-hwOzOY+$MW)Wl8~L99S#l-Bmo7$ zMn*=+vl0T{BatAWT)y8r+H07*qoM6N<$f`Lb= AuK)l5 literal 0 HcmV?d00001 diff --git a/screen.png b/screen.png new file mode 100644 index 0000000000000000000000000000000000000000..288d7aec039e041f999b71ddb8dc302dcf0493c4 GIT binary patch literal 20123 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 literal 0 HcmV?d00001 diff --git a/screen_Toolbar.png b/screen_Toolbar.png new file mode 100644 index 0000000000000000000000000000000000000000..ba98e91d1062589cd7d2194cfe440039dc0be8cb GIT binary patch literal 24367 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 G`M&_ubd;