您的位置:首页 > 编程语言

汽车之家代码片段

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: