使用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
#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
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];
图片: