汽车之家代码片段
2015-10-30 15:43
302 查看
// // TFScrollNavigationBar.h // 2015506-02ScrollNavigation框架 // // Created by appple on 15-5-6. // Copyright (c) 2015年 appple. All rights reserved. // #import <UIKit/UIKit.h> //自定义导航栏 @class TFScrollNavigationBar; @protocol TFScrollNavigationBar <NSObject> @optional /** 选中一个按钮后告诉代理 */ - (void)scrollNavigationBar:(TFScrollNavigationBar *)scrollNavigationBar DidSelectedButton : (UIButton *)button; @end @interface TFScrollNavigationBar : UIView /** 代理 */ @property (nonatomic , weak) id<TFScrollNavigationBar> delegate; /** 标题scrollView */ @property (nonatomic , weak , readonly) UIScrollView * titleScrollView; /** 右侧辅助按钮数组 */ @property (nonatomic , strong , readonly) NSArray * accessoryButtons; /** 标题显示字体的大小 (根据字体计算标题长度 , 该参数为nil时默认跟随系统)*/ @property (nonatomic , strong) UIFont *title_font; /** 标题显示文字及下划线的颜色 */ @property (nonatomic , strong) UIColor * titleSelectedColor; /** 标题显示文字常规颜色 */ @property (nonatomic , strong) UIColor * titleNomalColor; /** 当前选中的按钮 */ @property (nonatomic , weak , readonly) UIButton * selectedButton; /** 标题按钮数组 */ @property (nonatomic , strong , readonly) NSMutableArray * titleButtons; /** 根据传进来的控制器数组进行初始化 (本方法只为了拿到控制器的标题,不强引用控制器) */ - (instancetype)initWithControllers : (NSArray *) controllers; /** 添加右侧辅助按钮 (数组形式 , 建议最多添加2个 ) */ - (void)addAccessoryButtons:(NSArray *) accessoryButtons; /** 设置导航栏中的控制器标题按钮字体颜色及尺寸 */ - (void)setButtonTitleWithNomalColor : (UIColor *)nomalColor AndSelectedColor : (UIColor *)selectedColor AndTitleFont : (UIFont *)font; /** 设置按钮点击事件 (外部调用该方法只为了选中传入的按钮) */ - (void)clickButton : (UIButton *)button; /** 根据数组item的位置及比例滚动下划线 */ - (void)scrollUnderLineToItemAtIndex : (NSInteger)index WithScale : (CGFloat)scale; @end // // TFScrollNavigationBar.m // 2015506-02ScrollNavigation框架 // // Created by appple on 15-5-6. // Copyright (c) 2015年 appple. All rights reserved. // #import "TFScrollNavigationBar.h" #define Default_Selected_Color [UIColor colorWithRed:0/255.0 green:122/255.0 blue:255/255.0 alpha:1] #define Default_Nomal_Color [UIColor whiteColor] #define DurationTime 0.3 #define titleFont [UIFont systemFontOfSize:13.0] #define subTitleFont [UIFont systemFontOfSize:5.0] #define commentFont [UIFont systemFontOfSize:5.0] /** 按钮标题文字之间的间距 */ #define Button_Inset 20.0 @interface TFScrollNavigationBar () /** 标题scrollView (重写属性的目的 : 外界只读 , 内部可读可写) */ @property (nonatomic , weak , readwrite) UIScrollView * titleScrollView; /** 右侧辅助按钮数组 (重写属性的目的 : 外界只读 , 内部可读可写) */ @property (nonatomic , strong , readwrite) NSArray * accessoryButtons; /** 标题按钮数组 */ @property (nonatomic , strong , readwrite) NSMutableArray * titleButtons; /** 底部滑动下划线 */ @property (nonatomic , weak) CALayer * underLine; /** 当前选中的按钮 */ @property (nonatomic , weak , readwrite) UIButton * selectedButton; @end @implementation TFScrollNavigationBar #pragma mark - 初始化方法 /** 根据传进来的控制器数组进行初始化 , 实际目的只是为了获取控制器的标题 */ - (instancetype)initWithControllers : (NSArray *) controllers { self = [super init]; if (self) { /** 添加子控制器的标题 */ [self addTitlesFromChildViewControllers: controllers]; /** 默认初始选中按钮为第一个 */ if (self.titleButtons.count > 0) self.selectedButton = [self.titleButtons firstObject]; } return self; } #pragma mark - 参数懒加载 /** 标题scrollView */ - (UIScrollView *)titleScrollView { if(_titleScrollView == nil) { UIScrollView * temp = [[UIScrollView alloc] init]; /** 隐藏contentScrollView的垂直与水平的滚动条 */ // temp.showsVerticalScrollIndicator = NO; // temp.showsHorizontalScrollIndicator = NO; [self addSubview:temp]; _titleScrollView = temp ; } return _titleScrollView; } /** 标题按钮数组 */ - (NSMutableArray *)titleButtons { if(_titleButtons == nil) { NSMutableArray * temp = [NSMutableArray array]; _titleButtons = temp ; } return _titleButtons; } /** 底部滑动下划线 */ - (CALayer *)underLine { if(_underLine == nil) { CALayer * temp = [[CALayer alloc] init]; /** 设置线段端点样式 */ temp.cornerRadius = 3.0; temp.backgroundColor = Default_Selected_Color.CGColor; [self.titleScrollView.layer addSublayer:temp]; _underLine = temp ; } return _underLine; } #pragma mark - 参数重写set,get方法 /** 重写setSelectedButton set方法 */ - (void)setSelectedButton:(UIButton *)selectedButton { _selectedButton = selectedButton; _selectedButton.enabled = NO; _selectedButton.userInteractionEnabled = NO; /** 滚动选中的按钮到scrollView中心位置 */ [self scrollSelectedButtonToCenter]; //计算滚动的标题按钮滚动的距离 /*================================================================= 提示: 1. 在这里可以给控件写一个代理 , 然后将控件当前选中的按钮用代理的方式传出去. 2. 也可以用KVO方法监听选中的按钮. 3. 在本框架中我就用KVO来监听按钮的变化了,就不用代理了(可见RootViewController的初始化方法). 4. 如果要完美移植本控件, 建议可以给控件添加一个代理. 如下: =================================================================*/ /** 选中一个按钮后告诉代理 */ if ([self.delegate respondsToSelector:@selector(scrollNavigationBar:DidSelectedButton:)]) { [self.delegate scrollNavigationBar:self DidSelectedButton:self.selectedButton]; } } /** 重写setTitleNomalColor set方法 */ - (void)setTitleNomalColor:(UIColor *)titleNomalColor { _titleNomalColor = titleNomalColor; for (UIButton * obj in self.titleButtons) { [obj setTitleColor:titleNomalColor forState:UIControlStateNormal]; } } /** 重写setTitleSelectedColor set方法 */ - (void)setTitleSelectedColor:(UIColor *)titleSelectedColor { _titleSelectedColor = titleSelectedColor; for (UIButton * obj in self.titleButtons) { [obj setTitleColor:titleSelectedColor forState:UIControlStateDisabled]; [obj setTitleColor:titleSelectedColor forState:UIControlStateSelected]; } self.underLine.backgroundColor = titleSelectedColor.CGColor; } /** 重写setTitleFont set方法 */ - (void)setTitleFont:(UIFont *)title_font { _title_font = title_font; for (UIButton * obj in self.titleButtons) { obj.titleLabel.font = titleFont; } } #pragma mark - 重写系统方法 /** 重写设置背景颜色的方法 , 目的是为了让顶部状态栏的颜色跟导航栏的颜色一样. */ - (void)setBackgroundColor:(UIColor *)backgroundColor { [super setBackgroundColor:backgroundColor]; /** 如果这个自定义导航栏在屏幕最顶部时 , 则给系统的状态栏也染同色 */ [self colourStatusBarInSelfColorWhenSelfAtTop]; } #pragma mark - 按钮点击事件 /** 设置按钮点击事件 */ - (void)clickButton : (UIButton *)button { if (self.selectedButton == button) return; self.selectedButton.enabled = YES; self.selectedButton.userInteractionEnabled = YES; self.selectedButton = button; //根据按钮所在的位置调整按钮所在控制器的view的位置 [self layoutUnderLine]; } #pragma mark - 内部方法 /** 添加子控制器的标题 */ - (void)addTitlesFromChildViewControllers : (NSArray *)controllers { for (UIViewController * obj in controllers) { if (obj.title.length < 1) { NSLog(@"[%s--第%d行]--[错误:没有设置控制器的标题!]",__func__,__LINE__); return; } /** 根据标题添加按钮 */ [self addButtonWithTitle:obj.title]; } }
<img src="http://img.blog.csdn.net/20151030154326765?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" /> /** 添加标题scrollView内的按钮 */ - (void)addButtonWithTitle : (NSString *)title { UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom]; /** 设置按钮标题 */ [button setTitle:title forState:UIControlStateNormal]; /** 设置按钮默认正常状态颜色 */ [button setTitleColor:Default_Nomal_Color forState:UIControlStateNormal]; /** 设置按钮默认选中颜色 */ [button setTitleColor:Default_Selected_Color forState:UIControlStateDisabled]; [button setTitleColor:Default_Selected_Color forState:UIControlStateSelected]; /** 设置按钮点击事件 */ [button addTarget:self action:@selector(clickButton:) forControlEvents:UIControlEventTouchUpInside]; /** 将按钮添加到scrollView里面 */ [self.titleScrollView addSubview:button]; //将每个标题按钮添加到自定义的scrollView里面 [self.titleButtons addObject:button]; //添加到按钮数组中进行管理 } /** 如果这个自定义导航栏在屏幕最顶部时 , 则给系统的状态栏也染同色 */ - (void)colourStatusBarInSelfColorWhenSelfAtTop { /** 如果本控件的frame不为空值 */ if(![[NSValue valueWithCGRect:self.frame] isEqualToValue:[NSValue valueWithCGRect:CGRectZero]]) { CGRect rect = [self convertRect:self.bounds toView:[UIApplication sharedApplication].keyWindow]; /** 判断本控件是否正好在状态栏下面 */ if (rect.origin.y <= 20.0) { /** 设置顶部状态栏的背景颜色跟导航栏一样 */ [[UIApplication sharedApplication] setValue:self.backgroundColor forKeyPath:@"statusBar.backgroundColor"]; } } } #pragma mark - 内部 Frame 计算方法 /** 系统自动调用布局方法 */ - (void)layoutSubviews { [super layoutSubviews]; /** 如果这个自定义导航栏在屏幕最顶部时 , 则给系统的状态栏也染同色 */ [self colourStatusBarInSelfColorWhenSelfAtTop]; /** 布局辅助按钮 */ [self layoutAccessoryButtons]; /** 布局标题scrollView */ [self layoutTitleScrollView]; /** 布局下划线layer */ [self layoutUnderLine]; } /** 布局辅助按钮 */ - (void)layoutAccessoryButtons { if (self.accessoryButtons.count < 1) return; CGFloat height = self.bounds.size.height; CGFloat width = height; CGFloat x = self.bounds.size.width - width; CGFloat y = 0; for (UIButton * obj in self.accessoryButtons) { obj.frame = CGRectMake(x, y, width, height); x = x - width; } } /** 布局标题scrollView */ - (void)layoutTitleScrollView { CGFloat x = 0; CGFloat y = 0; CGFloat height = self.bounds.size.height; /** 标题scrollView的宽度 根据辅助按钮的位置进行判断 */ CGFloat width = 0; if (self.accessoryButtons.count > 0) { UIButton * button = [self.accessoryButtons lastObject]; width = CGRectGetMinX(button.frame); } else { width = self.bounds.size.width; } self.titleScrollView.frame = CGRectMake(x, y, width, height); /** 设置标题ScrollView的内容Size */ CGFloat sizeHeight = height; CGFloat sizeWidth = [self layoutTitleButtons]; self.titleScrollView.contentSize = CGSizeMake(sizeWidth, sizeHeight); } /** 布局标题ScrollView内部的按钮 , 并返回最后一个按钮的最大X值*/ - (CGFloat)layoutTitleButtons { for( NSInteger i = 0 ; i < self.titleButtons.count ; i++) { UIButton * tempButton = self.titleButtons[i]; /** 计算第一个按钮的frame */ if (i == 0) { CGFloat x = 0; CGFloat y = 0; CGSize size = [self sizeWithButton:tempButton]; tempButton.frame = CGRectMake(x, y, size.width, size.height); continue; } /** 根据前一个按钮计算后面按钮的位置 */ UIButton * lastButton = self.titleButtons[i-1]; CGFloat x = CGRectGetMaxX(lastButton.frame); CGFloat y = lastButton.frame.origin.y; CGSize size = [self sizeWithButton:tempButton]; tempButton.frame = CGRectMake(x, y, size.width, size.height); } /** 获取最后一个按钮 */ UIButton * button = [self.titleButtons lastObject]; return CGRectGetMaxX(button.frame); } /** 布局下划线layer */ - (void)layoutUnderLine { self.underLine.frame = CGRectMake(self.selectedButton.frame.origin.x, self.bounds.size.height - 2, self.selectedButton.frame.size.width, 2); } #pragma mark - 内部 自定义 计算方法 /** 根据按钮标题字体属性计算每个button的大小 */ - (CGSize)sizeWithButton : (UIButton *)button { NSMutableDictionary * attributes = [NSMutableDictionary dictionary]; UIFont * font = button.titleLabel.font; /** 设置按钮标题的字体属性 */ if (self.title_font) { font = self.title_font; [button.titleLabel setFont:font]; } attributes[NSFontAttributeName] = button.titleLabel.font; /** 计算按钮标题的size */ CGRect rect = [button.titleLabel.text boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, self.titleScrollView.bounds.size.height ) options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil]; CGSize size = CGSizeMake(rect.size.width + Button_Inset, self.titleScrollView.bounds.size.height); /** 设置按钮内部label的大小 */ button.titleLabel.frame = CGRectMake(0, 0, size.width, size.height); /** 设置文字居中 */ button.titleLabel.textAlignment = NSTextAlignmentCenter; return size; } /** 滚动选中的按钮到scrollView中心位置 */ - (void)scrollSelectedButtonToCenter { /** 如果titleView的内容长度小于frame , 就不滚动 */ if (self.titleScrollView.contentSize.width <= self.titleScrollView.bounds.size.width) return; CGFloat scrollViewCenterX = self.titleScrollView.center.x; CGFloat selectedButtonCenterX = self.selectedButton.center.x; CGFloat scrollOffset = selectedButtonCenterX - scrollViewCenterX ; /** 如果滚动会超过起始位置 , 则偏移置0 */ if (scrollOffset < 0 ) scrollOffset = 0; /** 如果滚动会超过最末位置 , 则偏移置为最末 */ else if (scrollOffset > (self.titleScrollView.contentSize.width - self.titleScrollView.bounds.size.width)) scrollOffset = self.titleScrollView.contentSize.width - self.titleScrollView.bounds.size.width; /** 以动画形式滚动 */ [UIView animateWithDuration:DurationTime animations:^{ self.titleScrollView.contentOffset = CGPointMake(scrollOffset, self.titleScrollView.contentOffset.y); } completion:^(BOOL finished) { }]; } /** 滚动下划线的时候根据滚动位置自动选中对应的button */ - (void)selectedButtonWhenUnderLineScroll { for (UIButton * obj in self.titleButtons) { //if (fabs(self.underLine.frame.origin.x - obj.frame.origin.x) <= obj.frame.size.width * 0.2) if (self.underLine.frame.origin.x == obj.frame.origin.x) { [self clickButton:obj]; } } } #pragma mark - 外部调用方法 /** 添加右侧辅助按钮 (数组形式 , 建议最多添加2个 ) */ - (void)addAccessoryButtons:(NSArray *) accessoryButtons { if (accessoryButtons.count<1) { NSLog(@"[%s--第%d行]--[警告:按钮数组为空,请确认是否传入空数组!]",__func__,__LINE__); self.accessoryButtons = nil; return; } if (accessoryButtons.count > 3) { NSLog(@"[%s--第%d行]--[警告:您传入的辅助按钮数量超过3个,建议最多只添加2个!]",__func__,__LINE__); } self.accessoryButtons = nil; NSMutableArray * array = [NSMutableArray array]; for (UIButton * obj in accessoryButtons) { if (![obj isKindOfClass:[UIButton class]]) { NSLog(@"[%s--第%d行]--[错误:请添加UIButton类型的按钮!如果需要自定义,可修改此处的代码!]",__func__,__LINE__); return; } [array addObject:obj]; [self addSubview:obj]; } self.accessoryButtons = array; } /** 设置导航栏中的控制器标题按钮字体颜色及尺寸 */ - (void)setButtonTitleWithNomalColor : (UIColor *)nomalColor AndSelectedColor : (UIColor *)selectedColor AndTitleFont : (UIFont *)font { if (nomalColor) self.titleNomalColor = nomalColor; if (selectedColor) self.titleSelectedColor = selectedColor; if (font) self.title_font = font; } /** 根据数组item的位置及比例滚动下划线 */ - (void)scrollUnderLineToItemAtIndex : (NSInteger)index WithScale : (CGFloat)scale { /** 参数边界值判断 */ if (index >= self.titleButtons.count || index < 0 ) { NSLog(@"[%s--第%d行]--[错误:输入的index有误!]",__func__,__LINE__); return; } UIButton * tempButton = self.titleButtons[index]; CGRect tempFrame = tempButton.frame; self.underLine.frame = CGRectMake(tempFrame.origin.x + tempFrame.size.width * scale , self.bounds.size.height - 2, self.underLine.frame.size.width, 2); } @end
相关文章推荐
- lua的类
- 关于Eclipse如何加入Gradle文件与Android Studio两个平台一起开发,工作目录不发生变化 转来的
- java字符串的各种编码转换
- Java中使用正则表达式处理文本数据
- php 字符串
- 主元素(LintCode)
- Myeclipse应用------常用快捷键
- 如何使用Python3读写INI配置文件
- [Python]python环境配置
- Mockito java学习
- 第一行代码Andorid——登录记住密码
- [转]PHP 应用性能分析 - Davey Shafik(全)
- spring3简单例子
- 验证码的种类与实现 C#封装类 - .NET MVC WEBFORM
- java实现二叉树
- java中char和byte的转换
- phpmyadmin中将字段整理latin1_swedish_ci更改表为utf8_chinese_ci
- JavasScript基数排序
- Go语言中函数的参数传递与调用的基本方法
- Java注解(Annotation)详解(三)——解析注解