用标签页TitleSwitch切换不通的控制器
教程效果:
项目开发中效果:
各种源码:
TitleSwitch.h 与 TitleSwitch.m (这个是修改过的升级版本)
//
// TitleSwitch.h
// TitleSwitch
//
// Created by YouXianMing on 14/11/4.
// Copyright (c) 2014年 YouXianMing. All rights reserved.
//
#import <UIKit/UIKit.h>
/**
* 使用细节
*
TitleSwitch *titleSwitch = [[TitleSwitch alloc] initWithFrame:CGRectMake(0, 100, 320, 40)];
titleSwitch.titles = @[@"YouXianMing", @"NoZuoNoDie", @"BlueShit"];
titleSwitch.titleFont = [UIFont systemFontOfSize:15.f];
titleSwitch.lineWidth = 1.f;
titleSwitch.canTouchOnlyButtonOneTime = YES;
titleSwitch.delegate = self;
[titleSwitch createTitleSwitchView];
[self.view addSubview:titleSwitch];
*
*
*/
@protocol TitleSwitchDelegate <NSObject>
@optional
- (void)willSelectIndex:(NSInteger)index;
- (void)didSelectIndex:(NSInteger)index;
@end
@interface TitleSwitch : UIView
/**
* 协议
*/
@property (nonatomic, assign) id<TitleSwitchDelegate> delegate;
/**
* 作为按钮的标题
*/
@property (nonatomic, strong) NSArray *titles;
/**
* 线的宽度
*/
@property (nonatomic, assign) CGFloat lineWidth;
/**
* 线的颜色
*/
@property (nonatomic, strong) UIColor *lineColor;
/**
* 标题字体
*/
@property (nonatomic, strong) UIFont *titleFont;
/**
* 普通标题颜色
*/
@property (nonatomic, strong) UIColor *normalTitleColor;
/**
* 选中标题的颜色
*/
@property (nonatomic, strong) UIColor *selectedTitleColor;
/**
* 一次只能按一个按钮触发动画效果
*/
@property (nonatomic, assign) BOOL canTouchOnlyButtonOneTime;
/**
* 开启按钮点击时高亮颜色的效果 & 高亮颜色
*/
@property (nonatomic, assign) BOOL enableButtonTitleHighlighted;
@property (nonatomic, strong) UIColor *highlightedTitleColor;
/**
* 小横线条的X方向的位移值(可以设置动画)
*/
@property (nonatomic, assign) CGFloat linePositionX;
/**
* 根据linePositionX重设标题颜色
*/
- (void)resetTilte;
/**
* 创建TitleSwitch的view出来
*/
- (void)createTitleSwitchView;
@end
//
// TitleSwitch.m
// TitleSwitch
//
// Created by YouXianMing on 14/11/4.
// Copyright (c) 2014年 YouXianMing. All rights reserved.
//
#import "TitleSwitch.h"
typedef enum : NSUInteger {
NORMAL_BUTTON = 0x11,
LINE_VIEW = 0x1122,
} ENUM_VIEWTAG;
@implementation TitleSwitch
- (void)createTitleSwitchView {
// 如果没有title,则直接返回
if (_titles.count == 0) {
return;
}
// 获取尺寸
CGFloat frameWidth = self.bounds.size.width;
CGFloat frameHeight = self.bounds.size.height;
// 计算按钮的宽度&高度
CGFloat buttonWidth = frameWidth / _titles.count;
CGFloat buttonHeight = 0;
CGFloat defaultLineWidth = 2.f;
if (_lineWidth == 0) {
buttonHeight = frameHeight - defaultLineWidth; // 默认线条占用一个像素
} else {
buttonHeight = frameHeight - _lineWidth;
}
// 初始化所有按钮
for (int i = 0; i < _titles.count; i++) {
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(buttonWidth * i,
0,
buttonWidth,
buttonHeight)];
button.tag = NORMAL_BUTTON + i;
[self addSubview:button];
[button setTitle:_titles[i] forState:UIControlStateNormal];
// 普通颜色
if (i == 0) {
[self selectButtonStyle:button];
} else {
[self normalButtonStyle:button];
}
// 高亮颜色
if (_enableButtonTitleHighlighted == YES && _highlightedTitleColor) {
[button setTitleColor:_highlightedTitleColor forState:UIControlStateHighlighted];
}
// 添加事件
[button addTarget:self action:@selector(buttonsEvent:) forControlEvents:UIControlEventTouchUpInside];
// 设置字体
if (_titleFont) {
button.titleLabel.font = _titleFont;
}
}
// 初始化横线view
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, buttonHeight + 1, buttonWidth,
(_lineWidth == 0 ? defaultLineWidth : _lineWidth))];
lineView.tag = LINE_VIEW;
[self addSubview:lineView];
if (_lineColor) {
lineView.backgroundColor = _lineColor;
} else {
lineView.backgroundColor = [UIColor redColor];
}
}
/**
* 按钮事件
*
* @param button 触摸事件中的按钮
*/
- (void)buttonsEvent:(UIButton *)button {
// 获取到lineView
UIView *lineView = [self viewWithTag:LINE_VIEW];
// 哪一个button
NSInteger whichButton = button.tag - NORMAL_BUTTON;
// 计算按钮的宽度&高度
CGFloat frameWidth = self.bounds.size.width;
CGFloat buttonWidth = frameWidth / _titles.count;
[[self subviews] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
UIButton *tmp = (UIButton *)obj;
if ([tmp isKindOfClass:[UIButton class]]) {
if (tmp == button) {
[self selectButtonStyle:tmp];
} else {
[self normalButtonStyle:tmp];
}
}
}];
// 做动画
if (_canTouchOnlyButtonOneTime == YES) {
self.userInteractionEnabled = NO;
}
if (_delegate && [_delegate respondsToSelector:@selector(willSelectIndex:)]) {
[_delegate willSelectIndex:whichButton];
}
[UIView animateWithDuration:0.25f animations:^{
CGRect rect = lineView.frame;
rect.origin.x = whichButton * buttonWidth;
lineView.frame = rect;
} completion:^(BOOL finished) {
if (_canTouchOnlyButtonOneTime == YES) {
self.userInteractionEnabled = YES;
}
if (_delegate && [_delegate respondsToSelector:@selector(didSelectIndex:)]) {
[_delegate didSelectIndex:whichButton];
}
}];
}
/**
* 选中按钮的样式
*
* @param button 按钮
*/
- (void)selectButtonStyle:(UIButton *)button {
if (_selectedTitleColor) {
[button setTitleColor:_selectedTitleColor
forState:UIControlStateNormal];
} else {
[button setTitleColor:[UIColor redColor]
forState:UIControlStateNormal];
}
}
/**
* 普通按钮样式
*
* @param button 按钮
*/
- (void)normalButtonStyle:(UIButton *)button {
if (_normalTitleColor) {
[button setTitleColor:_normalTitleColor
forState:UIControlStateNormal];
} else {
[button setTitleColor:[UIColor colorWithRed:0.369 green:0.369 blue:0.369 alpha:1]
forState:UIControlStateNormal];
}
}
- (void)resetTilte {
// 获取尺寸
CGFloat frameWidth = self.bounds.size.width;
// 计算按钮的宽度&高度
CGFloat buttonWidth = frameWidth / _titles.count;
// 获取到位置
NSInteger index = _linePositionX / buttonWidth + 1;
[[self subviews] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
UIButton *tmp = (UIButton *)obj;
if ([tmp isKindOfClass:[UIButton class]]) {
if (idx == index) {
[self selectButtonStyle:tmp];
} else {
[self normalButtonStyle:tmp];
}
}
}];
}
#pragma mark - 重写各种setter,getter方法
@synthesize linePositionX = _linePositionX;
- (void)setLinePositionX:(CGFloat)linePositionX {
_linePositionX = linePositionX;
// 获取到lineView
UIView *lineView = [self viewWithTag:LINE_VIEW];
if (lineView) {
CGRect rect = lineView.frame;
rect.origin.x = linePositionX;
lineView.frame = rect;
}
}
- (CGFloat)linePositionX {
return _linePositionX;
}
@end
WxHxD.h 与 WxHxD.m
//
// WxHxD.h
// PM2.5
//
// Created by YouXianMing on 14/10/29.
// Copyright (c) 2014年 YouXianMing. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface WxHxD : NSObject
/**
* 应用程序中可以放置view的区间的高度(部分区域会被导航栏控制器的高度占有而不计算在类)
*
* @return 高度
*/
+ (CGFloat)appHeight;
/**
* 屏幕高度
*
* @return 屏幕高度
*/
+ (CGFloat)screenHeight;
/**
* 屏幕宽度
*
* @return 屏幕宽度
*/
+ (CGFloat)screenWidth;
/**
* 状态栏高度
*
* @return 状态栏高度
*/
+ (CGFloat)statusBarHeight;
/**
* 导航栏控制器的高度
*
* @return 导航栏控制器的高度
*/
+ (CGFloat)navigationBarHeight;
/**
* 标签栏控制器的高度
*
* @return 标签栏控制器的高度
*/
+ (CGFloat)tabbarHeight;
/**
* 状态栏与导航栏控制器一起的高度
*
* @return 状态栏与导航栏控制器一起的高度
*/
+ (CGFloat)statusBarAndNavigationBarHeight;
@end
//
// WxHxD.m
// PM2.5
//
// Created by YouXianMing on 14/10/29.
// Copyright (c) 2014年 YouXianMing. All rights reserved.
//
#import "WxHxD.h"
@implementation WxHxD
+ (CGFloat)appHeight {
return [UIScreen mainScreen].applicationFrame.size.height;
}
+ (CGFloat)screenHeight {
return [UIScreen mainScreen].bounds.size.height;
}
+ (CGFloat)screenWidth {
return [UIScreen mainScreen].bounds.size.width;
}
+ (CGFloat)statusBarHeight {
return 20.f;
}
+ (CGFloat)navigationBarHeight {
return 44.f;
}
+ (CGFloat)tabbarHeight {
return 49.f;
}
+ (CGFloat)statusBarAndNavigationBarHeight {
return (20.f + 44.f);
}
@end
控制器源码:
//
// FirstController.m
// SwitchController
//
// Created by YouXianMing on 14/11/5.
// Copyright (c) 2014年 YouXianMing. All rights reserved.
//
#import "FirstController.h"
@interface FirstController ()
@end
@implementation FirstController
- (void)viewDidLoad {
[super viewDidLoad];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 40)];
label.center = self.view.center;
label.text = @"FirstController";
label.font = [UIFont fontWithName:@"HelveticaNeue-Thin" size:35.f];
label.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:label];
}
@end
//
// SecondController.m
// SwitchController
//
// Created by YouXianMing on 14/11/5.
// Copyright (c) 2014年 YouXianMing. All rights reserved.
//
#import "SecondController.h"
@interface SecondController ()
@end
@implementation SecondController
- (void)viewDidLoad {
[super viewDidLoad];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 40)];
label.center = self.view.center;
label.text = @"SecondController";
label.font = [UIFont fontWithName:@"HelveticaNeue-Thin" size:35.f];
label.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:label];
}
@end
主控制器源码:
//
// ViewController.m
// SwitchController
//
// Created by YouXianMing on 14/11/5.
// Copyright (c) 2014年 YouXianMing. All rights reserved.
//
#import "ViewController.h"
#import "TitleSwitch.h"
#import "WxHxD.h"
#import "FirstController.h"
#import "SecondController.h"
@interface ViewController ()<TitleSwitchDelegate, UIScrollViewDelegate>
{
TitleSwitch *titleSwitch;
}
@property (nonatomic, strong) UIScrollView *mainScrollView; // 滑动用的ScrollView
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 隐藏状态栏(需要先设置plist文件)
[UIApplication sharedApplication].statusBarHidden = YES; // 关闭状态栏
// 初始化UIScrollView
[self initScrollView];
// 初始化标签控制器
[self initTitleSwitch];
// 初始化两个控制器
FirstController *first = [FirstController new];
[self addChildViewController:first]; // 将控制器first变为当前控制器的子控制器
CGRect firstRect = first.view.frame;
firstRect.origin.x = [WxHxD screenWidth] * 0; // view值偏移量为 0*screenWidth
first.view.frame = firstRect;
SecondController *second = [SecondController new];
[self addChildViewController:second]; // 将控制器second变为当前控制器的子控制器
CGRect secondRect = second.view.frame;
secondRect.origin.x = [WxHxD screenWidth] * 1; // view值偏移量为 1*screenWidth
second.view.frame = secondRect;
// 加载控制器的view
[_mainScrollView addSubview:first.view];
[_mainScrollView addSubview:second.view];
}
/**
* 初始化UIScrollView
*/
- (void)initScrollView {
// 当前显示艺术品的控制器
_mainScrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
_mainScrollView.contentSize = CGSizeMake([WxHxD screenWidth] * 2, [WxHxD screenHeight]);
_mainScrollView.pagingEnabled = YES;
_mainScrollView.delegate = self;
_mainScrollView.bounces = NO;
_mainScrollView.showsHorizontalScrollIndicator = NO;
[self.view addSubview:_mainScrollView];
}
#pragma mark - UIScrollView的代理
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
titleSwitch.linePositionX = scrollView.contentOffset.x / 2.f;
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
[titleSwitch resetTilte];
}
/**
* 初始化标签控制器
*/
- (void)initTitleSwitch {
// 标题切换用
titleSwitch = [[TitleSwitch alloc] initWithFrame:CGRectMake(0, 0, [WxHxD screenWidth], 40)];
titleSwitch.tag = 0x112244;
// 添加灰色的线条
UIView *grayLine = [[UIView alloc] initWithFrame:CGRectMake(0, 40, [WxHxD screenWidth], 1)];
grayLine.backgroundColor = [UIColor colorWithRed:0.827 green:0.827 blue:0.827 alpha:1];
[titleSwitch addSubview:grayLine];
titleSwitch.backgroundColor = [UIColor colorWithRed:0.949 green:0.949 blue:0.949 alpha:1];
titleSwitch.selectedTitleColor = [UIColor colorWithRed:0.843 green:0.000 blue:0.000 alpha:1];
titleSwitch.titles = @[@"YouXianMing",
@"NoZuoNoDie"];
titleSwitch.lineWidth = 1.f;
titleSwitch.titleFont = [UIFont systemFontOfSize:15.f];
titleSwitch.canTouchOnlyButtonOneTime = YES;
titleSwitch.delegate = self;
[titleSwitch createTitleSwitchView];
[self.view addSubview:titleSwitch];
}
#pragma mark - TitleSwitch的代理
- (void)willSelectIndex:(NSInteger)index {
if (index == 0) {
CGPoint point = _mainScrollView.contentOffset;
point.x = 0;
[UIView animateWithDuration:0.25f animations:^{
_mainScrollView.contentOffset = point;
}];
[self bringTitleToFrount];
} else {
CGPoint point = _mainScrollView.contentOffset;
point.x = [WxHxD screenWidth];
[UIView animateWithDuration:0.25f animations:^{
_mainScrollView.contentOffset = point;
}];
[self bringTitleToFrount];
}
}
/**
* 将标题提到最前面
*/
- (void)bringTitleToFrount {
UIView *tmpView = [self.view viewWithTag:0x112244];
[self.view bringSubviewToFront:tmpView];
}
@end
解析: