用标签页TitleSwitch切换不通的控制器

用标签页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

解析:

原文地址:https://www.cnblogs.com/YouXianMing/p/4077153.html