iOS自定义Tab选择

使用Quarz2D绘图api进行绘制,不停的重新绘制会导致屏幕闪烁。(本来想在内存种绘图然后在存储到本地,可能效果好一点,没有实践)

头文件:

#import 

///
//	指示器
///
@interface SNSBottomTabIndicator : UIView {
@private
	BOOL _isLeft;
	CGFloat _radius;
}

- (void) setIsLeft:(BOOL)value;

@property (nonatomic) CGFloat radius;

@end

///
//	标签按钮
///
@interface SNSBottomTabButton : UIControl {
@private
	UIImageView *_ivPicture;
	UILabel *_lblText;
	NSString *_tab_id;
	NSInteger _buttonIndex;
	CGFloat _minWidth;
}

@property (nonatomic) NSInteger buttonIndex;
@property (nonatomic, copy) NSString *tab_id;


- (void)setLabelText:(NSString *)value;
- (NSString *)getLabelText;
- (void)setPictureName:(NSString *)value;

- (CGFloat)minWidth;

@end

///
//	选中背景View
///
@interface SNSBottomTabSelectBackgroundView : UIView {
@private
	
}


@end


///
//	标签View
///
@interface SNSBottomTabView : UIView  {
@private
	UIScrollView *_svContainer;	
	SNSBottomTabIndicator *_ciLeft;
	SNSBottomTabIndicator *_ciRight;
	BOOL _isShowIndicator;
	CGSize _oldSize;
	
	SNSBottomTabSelectBackgroundView *_selectBGView;
	SNSBottomTabButton *_selectButton;
	
	id _parentDelegate;
}

@property (nonatomic, assign) id parentDelegate;

- (void)setTabListFile:(NSString *)fileName;
- (void)setSelectWithButtonIndex:(NSInteger)value;
- (void)setSelectWithButtonID:(NSString *)value;
@end

@protocol SNSBottomTabViewDelegate
@optional
- (void)snsBottomTableViewSelect:(SNSBottomTabView *)sender withButtonIndex:(NSInteger)buttonIndex withButtonID:(NSString *)buttonID withButtonText:(NSString *)buttonText;

@end

.m文件

#import "SNSBottomTabView.h"
#import "FSGraphicsEx.h"
#import "CommonFuncs.h"
#import 

#define SNS_BOTTOM_TAB_BUTTON_COL_SPACE 8.0f
#define SNS_BOTTOM_TAB_SHADOW_HEIGHT 8.0f

#define TAB_ID_KEY @"TAB_ID"
#define TAB_TEXT_KEY @"TAB_Text"
#define TAB_PICTURE_KEY @"TAB_Picture"

#define SNS_BOTTOM_TAB_SELECT_ARROW_WIDTH 12.0f
#define SNS_BOTTOM_TAB_SELECT_ARROW_HEIGHT 8.0f

#define SNS_BOTTOM_TAB_SELECT_SEP_Y 6.0f
#define SNS_BOTTOM_TAB_SELECT_SEP_X_WIDTH 0.5

///
#define SNS_TAB_INDICATOR_WIDTH 8.0f
#define SNS_TAB_INDICATOR_HEIGHT 12.0f
#define SNS_TAB_LEFT_RIGHT_SPACE 6.0f
#define SNS_TAB_TOP_BOTTOM_SAPCE 0.0f
#define SNS_TAB_COL_SPACE 2.0f
#define SNS_TAB_CORNER_RADIUS 12.0f

#define EDGE_WIDTH 24.0f

#define SNS_TAB_RATE 3.5f


///
//	标签View
///
@interface SNSBottomTabView(Private) 
- (void)layoutTabButtons;
@end


@implementation SNSBottomTabView
@synthesize parentDelegate = _parentDelegate;

- (id)initWithFrame:(CGRect)frame {
    
    self = [super initWithFrame:frame];
    if (self) {
		NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
		
		_oldSize = CGSizeZero;
		_isShowIndicator = YES;
		[self setBackgroundColor:[UIColor clearColor]];

		CGSize sizeTmp = CGSizeZero;
		sizeTmp.width = frame.size.width - SNS_TAB_LEFT_RIGHT_SPACE * 2.0f - SNS_TAB_INDICATOR_WIDTH * 2.0f - SNS_TAB_COL_SPACE * 2.0f;
		sizeTmp.height = frame.size.height - SNS_TAB_TOP_BOTTOM_SAPCE - SNS_BOTTOM_TAB_SHADOW_HEIGHT;
		if (sizeTmp.width < 0) {
			sizeTmp.width = 0;
		}
		if (sizeTmp.height < 0) {
			sizeTmp.height = 0;
		}
		
		_svContainer = [[UIScrollView alloc] initWithFrame:CGRectMake(SNS_TAB_LEFT_RIGHT_SPACE + SNS_TAB_INDICATOR_WIDTH + SNS_TAB_COL_SPACE, 
																	  SNS_TAB_TOP_BOTTOM_SAPCE, 
																	  sizeTmp.width, 
																	  sizeTmp.height)];
		_svContainer.backgroundColor = [UIColor clearColor];
		[_svContainer setShowsVerticalScrollIndicator:NO];
		[_svContainer setShowsHorizontalScrollIndicator:NO];
		[_svContainer setDelegate:self];
		//_svContainer.layer.cornerRadius = SNS_TAB_CORNER_RADIUS;
		[self addSubview:_svContainer];
		
		//左右边的指示器
		sizeTmp.width = SNS_TAB_INDICATOR_WIDTH + SNS_TAB_COL_SPACE + EDGE_WIDTH;
		sizeTmp.height = frame.size.height - SNS_TAB_TOP_BOTTOM_SAPCE - SNS_BOTTOM_TAB_SHADOW_HEIGHT;
		if (sizeTmp.height < 0) {
			sizeTmp.height = 0;
		}
		
		_ciLeft = [[SNSBottomTabIndicator alloc] initWithFrame:CGRectMake(SNS_TAB_LEFT_RIGHT_SPACE, 
																		  SNS_TAB_TOP_BOTTOM_SAPCE, 
																		  sizeTmp.width, 
																		  sizeTmp.height)];
		[_ciLeft setRadius:SNS_TAB_CORNER_RADIUS];
		[_ciLeft setHidden:YES];
		[self addSubview:_ciLeft];
		
		_ciRight = [[SNSBottomTabIndicator alloc] initWithFrame:CGRectMake(frame.size.width - SNS_TAB_LEFT_RIGHT_SPACE - EDGE_WIDTH - SNS_TAB_COL_SPACE - SNS_TAB_INDICATOR_WIDTH, 
																		   SNS_TAB_TOP_BOTTOM_SAPCE, 
																		   sizeTmp.width, 
																		   sizeTmp.height)];
		[_ciRight setIsLeft:NO];
		[_ciRight setHidden:YES];
		[_ciRight setRadius:SNS_TAB_CORNER_RADIUS];
		[self addSubview:_ciRight];
		
		_selectBGView = [[SNSBottomTabSelectBackgroundView alloc] initWithFrame:CGRectZero];
		[_svContainer addSubview:_selectBGView];
		_selectBGView.alpha = 0.0f;
		
		_selectButton = nil;
		
		[pool release];
    }
    return self;
}

- (void)layoutSubviews {
	[super layoutSubviews];
	
	if (_oldSize.width == self.frame.size.width || [[_svContainer subviews] count] == 0) {
		return;
	}
	
	_oldSize = self.frame.size;
	
	CGSize sizeTmp = CGSizeZero;
	sizeTmp.width = self.frame.size.width - SNS_TAB_LEFT_RIGHT_SPACE * 2.0f - (_isShowIndicator ? SNS_TAB_INDICATOR_WIDTH * 2.0f + SNS_TAB_COL_SPACE * 2.0f : 0.0f);
	sizeTmp.height = self.frame.size.height - SNS_TAB_TOP_BOTTOM_SAPCE - SNS_BOTTOM_TAB_SHADOW_HEIGHT;
	if (sizeTmp.width < 0) {
		sizeTmp.width = 0;
	}
	if (sizeTmp.height < 0) {
		sizeTmp.height = 0;
	}
	
	_svContainer.frame = CGRectMake(SNS_TAB_LEFT_RIGHT_SPACE + (_isShowIndicator ? SNS_TAB_INDICATOR_WIDTH + SNS_TAB_COL_SPACE : 0.0f), 
									SNS_TAB_TOP_BOTTOM_SAPCE, 
									sizeTmp.width, 
									sizeTmp.height);
	
	[self layoutTabButtons];
	
	if (_isShowIndicator) {
		//左右边的指示器
		sizeTmp.width = SNS_TAB_INDICATOR_WIDTH + SNS_TAB_COL_SPACE + EDGE_WIDTH;
		sizeTmp.height = self.frame.size.height - SNS_TAB_TOP_BOTTOM_SAPCE - SNS_BOTTOM_TAB_SHADOW_HEIGHT;
		if (sizeTmp.height < 0) {
			sizeTmp.height = 0;
		}
		
		
		_ciLeft.frame = CGRectMake(SNS_TAB_LEFT_RIGHT_SPACE, 
								   SNS_TAB_TOP_BOTTOM_SAPCE, 
								   sizeTmp.width, 
								   sizeTmp.height);
		_ciRight.frame = CGRectMake(self.frame.size.width - SNS_TAB_LEFT_RIGHT_SPACE - EDGE_WIDTH - SNS_TAB_COL_SPACE - SNS_TAB_INDICATOR_WIDTH, 
									SNS_TAB_TOP_BOTTOM_SAPCE, 
									sizeTmp.width, 
									sizeTmp.height);
	} else {
		_ciLeft.frame = CGRectZero;
		_ciRight.frame = CGRectZero;
	}
	
	[_svContainer.delegate scrollViewDidScroll:_svContainer];
}


// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
	CGContextRef context = UIGraphicsGetCurrentContext();
	CGRect rClient = rect;
	rClient.size.height -= SNS_BOTTOM_TAB_SHADOW_HEIGHT;
	CGRect rShadow = rect;
	rShadow.origin.y += rClient.size.height;
	rShadow.size.height = SNS_BOTTOM_TAB_SHADOW_HEIGHT;
	CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
	
	//STEP 1.
	CGContextSaveGState(context);
	CGContextSetRGBFillColor(context, 98.0f / 255.0f, 98.0f / 255.0f, 98.0f / 255.0f, 1.0f);
	CGContextSetRGBStrokeColor(context, 98.0f / 255.0f, 98.0f / 255.0f, 98.0f / 255.0f, 1.0f);
	buildPathForRect(context, rClient, 0.0f, FS_DRAW_REGION_RECT);
	CGContextDrawPath(context, kCGPathFillStroke);
	CGContextRestoreGState(context);
	
	//STEP 2.
	CGContextSaveGState(context);
	CGRect rTop = rClient;
	rTop.size.height = rClient.size.height / 2.0f;
	drawTopGradientInRect(rTop, context, rgb);
	CGContextRestoreGState(context);
	
	//STEP 3.
	CGContextSaveGState(context);
	CGRect rBottom = rTop;
	rBottom.origin.y += rTop.size.height;
	drawBottomGradientInRect(rBottom, context, rgb);
	CGContextRestoreGState(context);
	
	//STEP 4.
	CGContextSaveGState(context);
#ifdef MYDEBUG
	NSLog(@"rShadow.y=%f;h=%f[%f]", rShadow.origin.y, rShadow.size.height, rect.size.height);
#endif
	buildPathForRect(context, rShadow, 0.0f, FS_DRAW_REGION_RECT);
	CGContextSetRGBFillColor(context, 0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 1.0f);
	CGContextSetRGBStrokeColor(context, 0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 1.0f);
	CGContextSetLineWidth(context, 0.0f);
	CGContextDrawPath(context, kCGPathFillStroke);
	CGContextRestoreGState(context);
	
	CGColorSpaceRelease(rgb);
	
}


- (void)dealloc {
	[_svContainer release];
	[_ciLeft release];
	[_ciRight release];
	[_selectBGView release];
    [super dealloc];
}

#pragma mark -
#pragma mark Public
- (void)setTabListFile:(NSString *)fileName {
	//移除所有数据
	NSArray *childViews = [_svContainer subviews];
	for (UIView *childView in childViews) {
		if ([childView isKindOfClass:[SNSBottomTabButton class]]) {
			SNSBottomTabButton *crbv = (SNSBottomTabButton *)childView;
			[crbv removeTarget:self action:@selector(snsBottomButtonAction:) forControlEvents:UIControlEventTouchUpInside];
			[childView removeFromSuperview];
		}
		
	}
	
	//复位
	_svContainer.contentSize = CGSizeZero;
	_ciLeft.hidden = YES;
	_ciRight.hidden = YES;
	
	if (![[NSFileManager defaultManager] fileExistsAtPath:fileName]) {
		return;
	}
	
	NSArray *tabs = [[NSArray alloc] initWithContentsOfFile:fileName];

	NSInteger tabCount = 0;
	for (NSDictionary *dicTab in tabs) {
		NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
		
		tabCount++;
		SNSBottomTabButton *tabBtn = [[SNSBottomTabButton alloc] initWithFrame:CGRectZero];
		[tabBtn setLabelText:[dicTab objectForKey:TAB_TEXT_KEY]];
		NSString *fileName = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:[dicTab objectForKey:TAB_PICTURE_KEY]];
		[tabBtn setPictureName:fileName];
		[tabBtn setButtonIndex:tabCount];
		[tabBtn setTab_id:[dicTab objectForKey:TAB_ID_KEY]];
		[_svContainer addSubview:tabBtn];
		[tabBtn addTarget:self action:@selector(snsBottomButtonAction:) forControlEvents:UIControlEventTouchUpInside];
		[tabBtn release];
		
		[pool release];
	}
	
	[self layoutTabButtons];

}

- (void)setSelectWithButtonIndex:(NSInteger)value {
	NSArray *childViews = [_svContainer subviews];
	for (UIView *childView in childViews) {
		if ([childView isKindOfClass:[SNSBottomTabButton class]]) {
			SNSBottomTabButton *crbv = (SNSBottomTabButton *)childView;
			if (crbv.buttonIndex == value) {
				[crbv sendActionsForControlEvents:UIControlEventTouchUpInside];
				break;
			}
		}
	}
}

- (void)setSelectWithButtonID:(NSString *)value {
	NSArray *childViews = [_svContainer subviews];
	for (UIView *childView in childViews) {
		if ([childView isKindOfClass:[SNSBottomTabButton class]]) {
			SNSBottomTabButton *crbv = (SNSBottomTabButton *)childView;
			if ([crbv.tab_id isEqualToString:value]) {
				[crbv sendActionsForControlEvents:UIControlEventTouchUpInside];
				break;
			}
		}
	}
}

#pragma mark -
#pragma mark Private
- (void)snsBottomButtonAction:(id)sender {
	//动画,回调
	if ([sender isKindOfClass:[SNSBottomTabButton class]] && ![sender isEqual:_selectBGView]) {
		SNSBottomTabButton *btn = (SNSBottomTabButton *)sender;
		[UIView beginAnimations:nil context:NULL];
		[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
		[UIView setAnimationDuration:0.3];
		[UIView setAnimationDelegate:self];
		[UIView setAnimationDidStopSelector:@selector(selectCompelet)];
		CGRect rSelect = _selectBGView.frame;
		rSelect.origin.x = btn.frame.origin.x;
		rSelect.size.width = btn.frame.size.width;
		_selectBGView.alpha = 1.0f;
		_selectBGView.frame = rSelect;
		[UIView commitAnimations];
		
		_selectButton = sender;
#ifdef MYDEBUG
		NSLog(@"_selectBGView:%@", _selectBGView);
#endif
	}
}

- (void)selectCompelet {
	if ([_parentDelegate respondsToSelector:@selector(snsBottomTableViewSelect:withButtonIndex:withButtonID:withButtonText:)]) {
		[_parentDelegate snsBottomTableViewSelect:self withButtonIndex:_selectButton.buttonIndex withButtonID:_selectButton.tab_id withButtonText:[_selectButton getLabelText]];
	}
}

- (void)layoutTabButtons {
	CGFloat totalWidth = 0.0f;
	CGFloat maxWidth = 0.0f;
	NSInteger tabCount = 0;
	NSArray *childViews = [_svContainer subviews];
	
	//先计算宽度
	for (UIView *childView in childViews) {
		if ([childView isKindOfClass:[SNSBottomTabButton class]]) {
			SNSBottomTabButton *crbv = (SNSBottomTabButton *)childView;
			CGFloat curBtnWidth = [crbv minWidth];
			if (curBtnWidth > maxWidth) {
				maxWidth = curBtnWidth;
			}
			tabCount++;
		}
	}
	totalWidth = tabCount * maxWidth;
	
	CGFloat colSpace = SNS_BOTTOM_TAB_BUTTON_COL_SPACE;
	
	if (totalWidth + SNS_BOTTOM_TAB_BUTTON_COL_SPACE * (tabCount + 1) < _svContainer.frame.size.width) {
		colSpace = (_svContainer.frame.size.width - totalWidth) / (tabCount + 1);
	}
	
	//布局
	CGFloat left = colSpace;
	CGFloat top = SNS_TAB_TOP_BOTTOM_SAPCE;
	for (UIView *childView in childViews) {
		if ([childView isKindOfClass:[SNSBottomTabButton class]]) {
			SNSBottomTabButton *crbv = (SNSBottomTabButton *)childView;
			crbv.frame = CGRectMake(left, top, maxWidth, _svContainer.frame.size.height - SNS_TAB_TOP_BOTTOM_SAPCE * 2.0f);
			left += (colSpace + maxWidth);
		}
	}
	
	_svContainer.contentSize = CGSizeMake(left, _svContainer.frame.size.height);
	[_svContainer.delegate scrollViewDidScroll:_svContainer];
	CGRect rSelect = _selectBGView.frame;
	rSelect.origin.y = 0.0f;
	rSelect.size.height = _svContainer.frame.size.height;
	rSelect.size.width = maxWidth;
	_selectBGView.frame = rSelect;
}

#pragma mark -
#pragma mark UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
	if (!_isShowIndicator) {
		return;
	}
	if (scrollView.contentSize.width <= scrollView.frame.size.width) {
		[_ciLeft setHidden:YES];
		[_ciRight setHidden:YES];
		return;
	}
	[_ciLeft setHidden:scrollView.contentOffset.x <= 0];
	[_ciRight setHidden:scrollView.contentOffset.x + scrollView.frame.size.width >= scrollView.contentSize.width];	
	[_ciLeft setNeedsDisplay];
	[_ciRight setNeedsDisplay];
}

@end

///
//	指示器
///
@implementation SNSBottomTabIndicator

@synthesize radius = _radius;

- (id)initWithFrame:(CGRect)frame {
    
    self = [super initWithFrame:frame];
    if (self) {
		NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
		
		[self setBackgroundColor:[UIColor clearColor]];
		[self setUserInteractionEnabled:NO];
		_isLeft = YES;
		
		[pool release];
    }
    return self;
}


// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code.
	CGContextRef context = UIGraphicsGetCurrentContext();
	CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
	
	CGRect rrect = CGRectZero;
	CGRect rArrow = CGRectZero;
	CGSize sizeOffset = CGSizeZero;
	CGSize sizeArrow = CGSizeZero;
	CGFloat r = 0.0f;
	
	if (_isLeft) {
		rrect = CGRectMake(SNS_TAB_INDICATOR_WIDTH + SNS_TAB_COL_SPACE, 
						   0.0f, 
						   rect.size.width - SNS_TAB_INDICATOR_WIDTH - SNS_TAB_COL_SPACE, 
						   rect.size.height);
		rArrow = CGRectMake(CGRectGetMinX(rrect), CGRectGetMinY(rrect) + 0.0f, rrect.size.width, rrect.size.height - 0.0f);
	} else {
		rrect = CGRectMake(0.0f, 
						   0.0f, 
						   rect.size.width - SNS_TAB_INDICATOR_WIDTH - SNS_TAB_COL_SPACE, 
						   rect.size.height);
		rArrow = CGRectMake(CGRectGetMinX(rrect), CGRectGetMinY(rrect) + 0.0f, rrect.size.width, rrect.size.height - 0.0f);
	}
	
	CGPoint pt1 = CGPointMake(CGRectGetMinX(rArrow), CGRectGetMidY(rArrow));
	CGPoint pt2 = CGPointMake(CGRectGetMaxX(rArrow) + rArrow.size.width, CGRectGetMidY(rArrow));
	CGPoint pt3 = CGPointMake(CGRectGetMaxX(rArrow), CGRectGetMinY(rArrow));
	r = [CommonFuncs computRadiusWithPoint1:pt1 withPoint2:pt2 withPoint3:pt3];
	CGFloat rH = rArrow.size.height / 2.0f;
	CGFloat angle = atan(rH / rArrow.size.width);
	
	sizeOffset.width = rArrow.size.width - r * sin(angle);
	sizeOffset.height = rH - sizeOffset.width * rH / rArrow.size.width;
	sizeArrow.width = rArrow.size.width - r * sin(angle * 1.5);
	sizeArrow.height = rH - sizeArrow.width * rH / rArrow.size.width;
		
	CGFloat colors[] =
	{
		0.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, 0.95,
		0.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, 0.85,
		0.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, 0.65,
		0.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, 0.45,
		0.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, 0.25,
		0.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, 0.15,
		0.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, 0.05,
		0.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, 0.00,
	};
	
	//STEP 1.渐变
	if (_isLeft) {
		CGContextSaveGState(context);
		//buildPathForRect(context, rArrow, 0.0f, FS_DRAW_REGION_RECT);
		CGContextAddArc(context, CGRectGetMaxX(rArrow), CGRectGetMaxY(rArrow) - r, r, M_PI * 0.5, M_PI * 0.5 + angle * 2.0f, 0);
		CGContextAddArc(context, CGRectGetMaxX(rArrow), CGRectGetMinY(rArrow) + r, r, M_PI * 1.5 - angle * 2.0f, M_PI * 1.5, 0);
		CGContextSetLineWidth(context, 0.0f);
		CGContextClip(context);
		drawGradientInRect(rArrow, context, rgb, colors, sizeof(colors) / sizeof(CGFloat), GRADIENT_RECT_FROM_LEFT_TO_RIGHT);
		CGContextRestoreGState(context);
	} else {
		CGContextSaveGState(context);
		CGContextAddArc(context, CGRectGetMinX(rArrow), CGRectGetMaxY(rArrow) - r, r, M_PI * 0.5 - angle * 2.0f, M_PI * 0.5, 0);
		CGContextAddArc(context, CGRectGetMinX(rArrow), CGRectGetMinY(rArrow) + r, r, M_PI * 1.5, M_PI * 1.5 + angle * 2.0f, 0);
		CGContextSetLineWidth(context, 0.0f);
		CGContextClip(context);
		drawGradientInRect(rArrow, context, rgb, colors, sizeof(colors) / sizeof(CGFloat), GRADIENT_RECT_FROM_RIGHT_TO_LEFT);
		CGContextRestoreGState(context);
	}

	
	//STEP 2
	if (_isLeft) {
		//底色(逆时针加弧)
		CGContextSaveGState(context);		
		CGContextAddArc(context, CGRectGetMaxX(rArrow), CGRectGetMaxY(rArrow) - r, r, M_PI * 0.5, M_PI * 0.5 + angle * 2.0f, 0);
		CGContextAddArc(context, CGRectGetMaxX(rArrow), CGRectGetMinY(rArrow) + r, r, M_PI * 1.5 - angle * 2.0f, M_PI * 1.5, 0);
		CGContextAddLineToPoint(context, CGRectGetMaxX(rArrow), CGRectGetMinY(rArrow));
		CGContextAddLineToPoint(context, CGRectGetMinX(rect), CGRectGetMinY(rect));
		CGContextAddLineToPoint(context, CGRectGetMinX(rect), CGRectGetMaxY(rect));
		CGContextAddLineToPoint(context, CGRectGetMaxX(rect), CGRectGetMaxY(rect));
		CGContextClosePath(context);
		
		CGContextSetRGBFillColor(context, 98.0f / 255.0f, 98.0f / 255.0f, 98.0f / 255.0f, 1.0f);
		CGContextSetRGBStrokeColor(context, 98.0f / 255.0f, 98.0f / 255.0f, 98.0f / 255.0f, 1.0f);
		CGContextSetLineWidth(context, 0.0f);
		CGContextDrawPath(context, kCGPathFillStroke);
		CGContextRestoreGState(context);

		//箭头
		CGContextSaveGState(context);
		CGContextAddArc(context, CGRectGetMaxX(rArrow), CGRectGetMaxY(rArrow) - r, r, M_PI * 0.5 + angle, M_PI * 0.5 + angle * 2.0f, 0);
		CGContextAddArc(context, CGRectGetMaxX(rArrow), CGRectGetMinY(rArrow) + r, r, M_PI * 1.5 - angle * 2.0f, M_PI * 1.5 - angle, 0);
		//CGContextAddLineToPoint(context, CGRectGetMaxX(rArrow), CGRectGetMinY(rArrow));
		CGContextAddLineToPoint(context, CGRectGetMinX(rect), CGRectGetMidY(rect));
		CGContextClosePath(context);
		
		CGContextSetLineWidth(context, 0.0f);
		CGContextSetRGBFillColor(context, 0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 1.0f);
		CGContextSetRGBStrokeColor(context, 50.0f / 255.0f, 50.0f / 255.0f, 50.0f / 255.0f, 1.0f);
		CGContextDrawPath(context, kCGPathFillStroke);
		CGContextRestoreGState(context);
		
		//上部
		CGContextSaveGState(context);
		CGContextAddArc(context, CGRectGetMaxX(rArrow), CGRectGetMinY(rArrow) + r, r, M_PI * 1.5 - angle * 2.0f, M_PI * 1.5, 0);
		CGContextAddLineToPoint(context, CGRectGetMaxX(rArrow), CGRectGetMinY(rArrow));
		CGContextAddLineToPoint(context, CGRectGetMinX(rect), CGRectGetMinY(rect));
		CGContextAddLineToPoint(context, CGRectGetMinX(rect), CGRectGetMidY(rect));
		CGContextClosePath(context);
		CGContextClip(context);
		CGRect rTop = rect;
		rTop.size.height /= 2.0f;
		
		
		CGContextSetRGBFillColor(context, 198.0f / 255.0f, 98.0f / 255.0f, 98.0f / 255.0f, 1.0f);
		CGContextSetRGBStrokeColor(context, 198.0f / 255.0f, 98.0f / 255.0f, 98.0f / 255.0f, 1.0f);
		drawTopGradientInRect(rTop, context, rgb);
		CGContextRestoreGState(context);

		//下部
		CGContextSaveGState(context);
		CGContextAddArc(context, CGRectGetMaxX(rArrow), CGRectGetMaxY(rArrow) - r, r, M_PI * 0.5, M_PI * 0.5 + angle * 2.0f, 0);
		CGContextAddLineToPoint(context, CGRectGetMinX(rect), CGRectGetMidY(rect));
		CGContextAddLineToPoint(context, CGRectGetMinX(rect), CGRectGetMaxY(rect));
		CGContextClosePath(context);
		CGContextClip(context);
		CGRect rBottom = rTop;
		rBottom.origin.y += rTop.size.height;
		drawBottomGradientInRect(rBottom, context, rgb);
		CGContextRestoreGState(context);
		
	} else {
		//底色(逆时针加弧)
		CGContextSaveGState(context);		
		CGContextAddArc(context, CGRectGetMinX(rArrow), CGRectGetMinY(rArrow) + r, r, M_PI * 1.5, M_PI * 1.5 + angle * 2.0f, 0);
		CGContextAddArc(context, CGRectGetMinX(rArrow), CGRectGetMaxY(rArrow) - r, r, M_PI * 0.5 - angle * 2.0f, M_PI * 0.5, 0);
		CGContextAddLineToPoint(context, CGRectGetMaxX(rect), CGRectGetMaxY(rect));
		CGContextAddLineToPoint(context, CGRectGetMaxX(rect), CGRectGetMinY(rect));
		CGContextClosePath(context);
		
		CGContextSetRGBFillColor(context, 98.0f / 255.0f, 98.0f / 255.0f, 98.0f / 255.0f, 1.0f);
		CGContextSetRGBStrokeColor(context, 98.0f / 255.0f, 98.0f / 255.0f, 98.0f / 255.0f, 1.0f);
		CGContextSetLineWidth(context, 0.0f);
		CGContextDrawPath(context, kCGPathFillStroke);
		CGContextRestoreGState(context);
		
		//箭头
		CGContextSaveGState(context);
		CGContextAddArc(context, CGRectGetMinX(rArrow), CGRectGetMinY(rArrow) + r, r, M_PI * 1.5 + angle, M_PI * 1.5 + angle * 2.0f, 0);
		CGContextAddArc(context, CGRectGetMinX(rArrow), CGRectGetMaxY(rArrow) - r, r, M_PI * 0.5 - angle * 2.0f, M_PI * 0.5 - angle, 0);
		CGContextAddLineToPoint(context, CGRectGetMaxX(rect), CGRectGetMidY(rect));
		CGContextClosePath(context);
		
		CGContextSetLineWidth(context, 0.0f);
		CGContextSetRGBFillColor(context, 0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 1.0f);
		CGContextSetRGBStrokeColor(context, 50.0f / 255.0f, 50.0f / 255.0f, 50.0f / 255.0f, 1.0f);
		CGContextDrawPath(context, kCGPathFillStroke);
		CGContextRestoreGState(context);
		
		//上部
		CGContextSaveGState(context);
		CGContextAddArc(context, CGRectGetMinX(rArrow), CGRectGetMinY(rArrow) + r, r, M_PI * 1.5, M_PI * 1.5 + angle * 2.0f, 0);
		CGContextAddLineToPoint(context, CGRectGetMaxX(rect), CGRectGetMidY(rect));
		CGContextAddLineToPoint(context, CGRectGetMaxX(rect), CGRectGetMinY(rect));
		CGContextClosePath(context);
		CGContextClip(context);
		CGRect rTop = rect;
		rTop.size.height /= 2.0f;
		
		CGContextSetRGBFillColor(context, 198.0f / 255.0f, 98.0f / 255.0f, 98.0f / 255.0f, 1.0f);
		CGContextSetRGBStrokeColor(context, 198.0f / 255.0f, 198.0f / 255.0f, 98.0f / 255.0f, 1.0f);
		CGContextSetLineWidth(context, 2.0f);
		//CGContextDrawPath(context, kCGPathFillStroke);
		drawTopGradientInRect(rTop, context, rgb);
		CGContextRestoreGState(context);
		
		//下部
		CGContextSaveGState(context);
		CGContextAddArc(context, CGRectGetMinX(rArrow), CGRectGetMaxY(rArrow) - r, r, M_PI * 0.5 - angle * 2.0f, M_PI * 0.5, 0);
		CGContextAddLineToPoint(context, CGRectGetMaxX(rect), CGRectGetMaxY(rect));
		CGContextAddLineToPoint(context, CGRectGetMaxX(rect), CGRectGetMidY(rect));
		CGContextClosePath(context);
		CGContextClip(context);
		CGRect rBottom = rTop;
		rBottom.origin.y += rTop.size.height;
		drawBottomGradientInRect(rBottom, context, rgb);
		CGContextRestoreGState(context);
	
	}

	
	CGColorSpaceRelease(rgb);
}


- (void) setIsLeft:(BOOL)value {
	if (value != _isLeft) {
		_isLeft = value;
		[self setNeedsDisplay];
	}
}

- (void)dealloc {
    [super dealloc];
}

@end

///
//	标签按钮
///

#define SNSTAB_BTN_LEFT_RIGHT 4.0f
#define SNSTAB_BTN_TOP_BOTTOM 4.0f
#define SNSTAB_BTN_COL_SPACE 4.0f

@implementation SNSBottomTabButton
@synthesize tab_id = _tab_id;
@synthesize buttonIndex = _buttonIndex;

- (id)initWithFrame:(CGRect)frame {
	self = [super initWithFrame:frame];
	if (self) {
		NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
		
		_minWidth = 0.0f;
		[self setBackgroundColor:[UIColor clearColor]];
		_ivPicture = [[UIImageView alloc] initWithFrame:CGRectZero];
		[self addSubview:_ivPicture];
		
		_lblText = [[UILabel alloc] initWithFrame:CGRectZero];
		[_lblText setBackgroundColor:[UIColor clearColor]];
		[_lblText setTextColor:[UIColor whiteColor]];
		[_lblText setFont:[UIFont boldSystemFontOfSize:16.0f]];
		[self addSubview:_lblText];
		
		[pool release];
	}
	return self;
}

- (void)setLabelText:(NSString *)value {
	_lblText.text = value;
}

- (NSString *)getLabelText {
	return _lblText.text;
}

- (void)setPictureName:(NSString *)value {
	if ([[NSFileManager defaultManager] fileExistsAtPath:value]) {
		UIImage *btnImage = [[UIImage alloc] initWithContentsOfFile:value];
		_ivPicture.image = btnImage;
		[btnImage release]; 
	} else {
		_ivPicture.image = nil;
	}
}

- (CGFloat)minWidth {
	if (_minWidth == 0.0f) {
		_minWidth = SNSTAB_BTN_LEFT_RIGHT * 2.0f + SNSTAB_BTN_COL_SPACE;
		CGSize sizeTmp = [_lblText.text sizeWithFont:_lblText.font];
		_minWidth += sizeTmp.width;
		_minWidth += _ivPicture.image.size.width;
	}

	return _minWidth;
}

- (void)layoutSubviews {
	[super layoutSubviews];
	CGSize sizeTmp = [_lblText.text sizeWithFont:_lblText.font];
	
	CGFloat clientWith = sizeTmp.width + (_ivPicture.image == nil || _ivPicture.image.size.width == 0 || _ivPicture.image.size.height == 0 ? 0.0f : (SNSTAB_BTN_COL_SPACE + _ivPicture.image.size.width));
	CGFloat left = (self.frame.size.width - clientWith) / 2.0f;
#ifdef MYDEBUG
	NSLog(@"SNSBottomTabButton.left:%f", left);
#endif
	
	//STEP 1.图片
	if (_ivPicture.image == nil || 
		_ivPicture.image.size.width == 0 ||
		_ivPicture.image.size.height == 0) {
		_ivPicture.frame = CGRectZero;
	} else {
		_ivPicture.frame = CGRectMake(left, 
									  (self.frame.size.height - _ivPicture.image.size.height) / 2.0f, 
									  _ivPicture.image.size.width, 
									  _ivPicture.image.size.height);
		left += (_ivPicture.frame.size.width + SNSTAB_BTN_COL_SPACE);
	}

	//文字
	_lblText.frame = CGRectMake(left, 0.0f, sizeTmp.width, self.frame.size.height);
}

@end

///
//	选中背景View
///
@implementation SNSBottomTabSelectBackgroundView

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
		NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];		
		[self setBackgroundColor:[UIColor clearColor]];
		[pool release];
    }
    return self;
}

- (void)layoutSubviews {
	[super layoutSubviews];
}

- (void)dealloc {
	[super dealloc];
}

- (void)drawRect:(CGRect)rect {
	CGContextRef context = UIGraphicsGetCurrentContext();
	CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
	
	//求圆的半径以及圆心所在位置,进行渐变绘制
	CGPoint pt1 = CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect));
	CGPoint pt2 = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
	CGPoint pt3 = CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(rect));

	CGFloat r = [CommonFuncs computRadiusWithPoint1:pt1 withPoint2:pt2 withPoint3:pt3];
#ifdef MYDEBUG
	NSLog(@"r = %f", r);
#endif
	CGPoint pt = CGPointMake(CGRectGetMidX(rect), r);
	
	//STEP 1.
	CGFloat colors[] = 
	{
		0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 1.0f,
		0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 1.0f,
		0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 1.0f,
		0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 0.95f,
		0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 0.90f,
		0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 0.85f,
		0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 0.80f,
		0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 0.75f,
		0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 0.70f,
		0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 0.60f,
		0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 0.50f,
		0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 0.40f,
		0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 0.30f,
		0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 0.20f,
		0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 0.10f,
		0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 0.05f,
		0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 0.0f
	};
	CGGradientRef gradient = CGGradientCreateWithColorComponents(rgb, colors, NULL, sizeof(colors) / (4 * sizeof(CGFloat)));
	CGContextDrawRadialGradient(context, 
								gradient, 
								pt,//CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect)), 
								0.0f, 
								pt,//CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect)), 
								r,//MIN(rect.size.width / 2.0f, rect.size.height), 
								0);
	CGGradientRelease(gradient);
	

	
	//STEP 2.
	CGFloat leftColors[] = 
	{
		13.0f / 255.0f, 13.0f / 255.0f, 13.0f / 255.0f, 0.0f,
		13.0f / 255.0f, 13.0f / 255.0f, 13.0f / 255.0f, 0.55f,
		13.0f / 255.0f, 13.0f / 255.0f, 13.0f / 255.0f, 0.85f,
		13.0f / 255.0f, 13.0f / 255.0f, 13.0f / 255.0f, 1.0f,
	};
	
	CGFloat rightColors[] = 
	{
		209.0f / 255.0f, 209.0f / 255.0f, 209.0f / 255.0f, 0.0f,
		209.0f / 255.0f, 209.0f / 255.0f, 209.0f / 255.0f, 0.55f,
		209.0f / 255.0f, 209.0f / 255.0f, 209.0f / 255.0f, 0.85f,
		209.0f / 255.0f, 209.0f / 255.0f, 209.0f / 255.0f, 1.0f,
	};
	
	CGGradientRef gradientLeft = CGGradientCreateWithColorComponents(rgb, leftColors, NULL, sizeof(leftColors) / (4 * sizeof(CGFloat)));
	CGGradientRef gradientRight = CGGradientCreateWithColorComponents(rgb, rightColors, NULL, sizeof(rightColors) / (4 * sizeof(CGFloat)));
	CGRect rLeft = CGRectZero;
	CGRect rRight = CGRectZero;
	
	//STEP 2.1
	rLeft = CGRectMake(CGRectGetMinX(rect) + SNS_BOTTOM_TAB_SELECT_SEP_X_WIDTH, 
					   CGRectGetMinY(rect) + SNS_BOTTOM_TAB_SELECT_SEP_Y, 
					   SNS_BOTTOM_TAB_SELECT_SEP_X_WIDTH, 
					   rect.size.height);
	rRight = CGRectMake(CGRectGetMinX(rect) + SNS_BOTTOM_TAB_SELECT_SEP_X_WIDTH * 2.0f, 
						CGRectGetMinY(rect) + SNS_BOTTOM_TAB_SELECT_SEP_Y, 
						SNS_BOTTOM_TAB_SELECT_SEP_X_WIDTH, 
						rect.size.height);
	
	CGContextSaveGState(context);
	buildPathForRect(context, rLeft, 0.0f, FS_DRAW_REGION_RECT);
	CGContextClip(context);
	CGContextDrawLinearGradient(context, gradientLeft, CGPointMake(CGRectGetMinX(rLeft), CGRectGetMinY(rLeft)), CGPointMake(CGRectGetMinX(rLeft), CGRectGetMaxY(rLeft)), 0);
	CGContextRestoreGState(context);
	
	CGContextSaveGState(context);
	buildPathForRect(context, rRight, 0.0f, FS_DRAW_REGION_RECT);
	CGContextClip(context);
	CGContextDrawLinearGradient(context, gradientRight, CGPointMake(CGRectGetMinX(rRight), CGRectGetMinY(rRight)), CGPointMake(CGRectGetMinX(rRight), CGRectGetMaxY(rRight)), 0);
	CGContextRestoreGState(context);
	
	
	//STEP 2.2
	
	rLeft = CGRectMake(CGRectGetMaxX(rect) - SNS_BOTTOM_TAB_SELECT_SEP_X_WIDTH * 3.0f, 
					   CGRectGetMinY(rect) + SNS_BOTTOM_TAB_SELECT_SEP_Y, 
					   SNS_BOTTOM_TAB_SELECT_SEP_X_WIDTH, 
					   rect.size.height);
	rRight = CGRectMake(CGRectGetMaxX(rect) - SNS_BOTTOM_TAB_SELECT_SEP_X_WIDTH * 2.0f, 
						CGRectGetMinY(rect) + SNS_BOTTOM_TAB_SELECT_SEP_Y, 
						SNS_BOTTOM_TAB_SELECT_SEP_X_WIDTH, 
						rect.size.height);
	
	CGContextSaveGState(context);
	buildPathForRect(context, rLeft, 0.0f, FS_DRAW_REGION_RECT);
	CGContextClip(context);
	CGContextDrawLinearGradient(context, gradientLeft, CGPointMake(CGRectGetMinX(rLeft), CGRectGetMinY(rLeft)), CGPointMake(CGRectGetMinX(rLeft), CGRectGetMaxY(rLeft)), 0);
	CGContextRestoreGState(context);
	
	CGContextSaveGState(context);
	buildPathForRect(context, rRight, 0.0f, FS_DRAW_REGION_RECT);
	CGContextClip(context);
	CGContextDrawLinearGradient(context, gradientRight, CGPointMake(CGRectGetMinX(rRight), CGRectGetMinY(rRight)), CGPointMake(CGRectGetMinX(rRight), CGRectGetMaxY(rRight)), 0);
	CGContextRestoreGState(context);
	
	CGGradientRelease(gradientLeft);
	CGGradientRelease(gradientRight);
	
	//STEP 3.
	CGFloat lineWidth = 2.0f;
	CGContextSaveGState(context);
	CGContextSetRGBFillColor(context, 0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 1.0f);
	CGContextSetRGBStrokeColor(context, 50.0f / 255.0f, 50.0f / 255.0f, 50.0f / 255.0f, 1.0f);
	CGContextSetLineWidth(context, 0.0f);
	//CGContextMoveToPoint(context, CGRectGetMinX(rect), CGRectGetMaxY(rect) - lineWidth / 2.0f);
	CGContextMoveToPoint(context, CGRectGetMidX(rect) - SNS_BOTTOM_TAB_SELECT_ARROW_WIDTH / 2.0f, CGRectGetMaxY(rect) - lineWidth / 2.0f);
	CGContextAddLineToPoint(context, CGRectGetMidX(rect), CGRectGetMaxY(rect) - SNS_BOTTOM_TAB_SELECT_ARROW_HEIGHT);
	CGContextAddLineToPoint(context, CGRectGetMidX(rect) + SNS_BOTTOM_TAB_SELECT_ARROW_WIDTH / 2.0f, CGRectGetMaxY(rect) - lineWidth / 2.0f);
	//CGContextAddLineToPoint(context, CGRectGetMaxX(rect), CGRectGetMaxY(rect) - lineWidth / 2.0f);
	CGContextClosePath(context);
	CGContextDrawPath(context, kCGPathFillStroke);
	CGContextRestoreGState(context);
	
	//STEP 4.
	CGContextSaveGState(context);
	CGContextSetRGBFillColor(context, 0.0f / 255.0f, 132.0f / 255.0f, 188.0f / 255.0f, 1.0f);
	CGContextSetRGBStrokeColor(context, 50.0f / 255.0f, 50.0f / 255.0f, 50.0f / 255.0f, 1.0f);
	CGContextSetLineWidth(context, 2.0f);
	CGContextMoveToPoint(context, CGRectGetMinX(rect), CGRectGetMaxY(rect) - lineWidth / 2.0f);
	CGContextAddLineToPoint(context, CGRectGetMidX(rect) - SNS_BOTTOM_TAB_SELECT_ARROW_WIDTH / 2.0f, CGRectGetMaxY(rect) - lineWidth / 2.0f);
	CGContextAddLineToPoint(context, CGRectGetMidX(rect), CGRectGetMaxY(rect) - SNS_BOTTOM_TAB_SELECT_ARROW_HEIGHT);
	CGContextAddLineToPoint(context, CGRectGetMidX(rect) + SNS_BOTTOM_TAB_SELECT_ARROW_WIDTH / 2.0f, CGRectGetMaxY(rect) - lineWidth / 2.0f);
	CGContextAddLineToPoint(context, CGRectGetMaxX(rect), CGRectGetMaxY(rect) - lineWidth / 2.0f);
	CGContextDrawPath(context, kCGPathStroke);
	CGContextRestoreGState(context);
	

	CGColorSpaceRelease(rgb);
}

@end

使用plist文件来做,plist的文件为数组列表。每个数组是个字典:字典的形式为:

TAB_ID:tab按钮的id

TAB_Text:tab按钮上的文字

TAB_Picture:tab按钮上的图标

赋值即可。

这个功能还有很多没有完善的。


使用方法:

	_toolView = [[SNSBottomTabView alloc] initWithFrame:CGRectMake(0.0f, self.view.frame.size.height - SNS_PERSONAL_TOOL_VIEW_HEIGHT, self.view.frame.size.width, SNS_PERSONAL_TOOL_VIEW_HEIGHT)];
	_toolView.parentDelegate = self;
	NSString *fileName = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"SNS_Tab_Personal_HomePage.plist"];
	[_toolView setTabListFile:fileName];
	[self.view addSubview:_toolView];


图片:



你可能感兴趣的:(程序人生)