菜单滑块切换控制器控件代码示例

//  AppDelegate.h
#import 
@interface AppDelegate : UIResponder 
@property (strong, nonatomic) UIWindow *window;
@end
//  AppDelegate.m
#import "AppDelegate.h"
#import "ViewController.h"
@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
    ViewController *mainView = [[ViewController alloc]init];
    UINavigationController *navi = [[UINavigationController alloc]initWithRootViewController:mainView];
    navi.navigationBar.backgroundColor = [UIColor blueColor];
    [self.window setRootViewController:navi];
    [self.window makeKeyAndVisible];
    return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
}
- (void)applicationWillTerminate:(UIApplication *)application {
}

@end
//  ViewController.h
#import 
#import "QHNavSliderMenu.h"
@interface ViewController : UIViewController
@property (nonatomic)QHNavSliderMenuType menuType;

@end
//  ViewController.m
#import "ViewController.h"
#import "macrodefine.h"
#import "UIView+Extension.h"
#import "FirstController.h"
#import "SecondController.h"

@interface ViewController()
@property (nonatomic, copy) NSArray * array;
@property (nonatomic, assign) NSInteger selectedIndex;

@end

@implementation ViewController{
    QHNavSliderMenu *navSliderMenu;
    NSMutableDictionary  *listVCQueue;
    UIScrollView *contentScrollView;
    int menuCount;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    // 设置导航栏标题文字颜色和字体大小
    NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
    attrs[NSForegroundColorAttributeName] = [UIColor whiteColor];
    attrs[NSFontAttributeName] = [UIFont systemFontOfSize:20];
    [self.navigationController.navigationBar setTitleTextAttributes:attrs];
    
    self.title = @"根控制器";
    menuCount = 2;
    self.array = @[@"第一控制器",@"第二控制器"];
    [self initView];
    self.selectedIndex = 1;
}

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    [self.navigationController setNavigationBarHidden:NO animated:NO];
}

-(void)initView{
    QHNavSliderMenuStyleModel *model = [QHNavSliderMenuStyleModel new];
    model.menuTitles = [self.array copy];
    model.menuWidth = screenWidth/2;
    model.sliderMenuTextColorForSelect = [UIColor greenColor];
    model.sliderMenuTextColorForNormal = [UIColor greenColor];
    model.titleLableFont = [UIFont systemFontOfSize:15];
    
    navSliderMenu = [[QHNavSliderMenu alloc] initWithFrame:(CGRect){0,64,screenWidth,44} andStyleModel:model andDelegate:self showType:self.menuType];
    navSliderMenu.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:navSliderMenu];
    contentScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, navSliderMenu.bottom, screenWidth, screenHeight-navSliderMenu.bottom)];
    contentScrollView.contentSize = (CGSize){screenWidth*menuCount,contentScrollView.contentSize.height};
    contentScrollView.pagingEnabled = YES;
    contentScrollView.delegate      = self;
    contentScrollView.scrollsToTop  = NO;
    contentScrollView.showsHorizontalScrollIndicator = NO;
    contentScrollView.scrollEnabled = NO;
    [self.view addSubview:contentScrollView];
    [self addListVCWithIndex:0];
}
-(void)addListVCWithIndex:(NSInteger)index{
    if (!listVCQueue) {
        listVCQueue=[[NSMutableDictionary alloc] init];
    }
    if (index < 0||index >= menuCount) {
        return;
    }
    if (![listVCQueue objectForKey:@(index)]) {
        if(index == 0){
            FirstController *first = [[FirstController alloc]init];
            //addChildViewController:给控制器添加子控制器
            [self addChildViewController:first];
            first.view.left = index * screenWidth;
            first.view.top = 1;
            [contentScrollView addSubview:first.view];
            [listVCQueue setObject:first forKey:@(index)];
        }else if(index == 1){
            SecondController *secind = [[SecondController alloc]init];
            [self addChildViewController:secind];
            secind.view.left = index * screenWidth;
            secind.view.top = 1;
            [contentScrollView addSubview:secind.view];
            [listVCQueue setObject:secind forKey:@(index)];
        }
    }
}

#pragma mark -QHNavSliderMenuDelegate
- (void)navSliderMenuDidSelectAtRow:(NSInteger)row {
    self.selectedIndex = row;
    //让scrollview滚到相应的位置
    [contentScrollView setContentOffset:CGPointMake(row*screenWidth, contentScrollView.contentOffset.y)  animated:NO];
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    self.selectedIndex = (int)((scrollView.contentOffset.x+screenWidth/2.f)/screenWidth);
    //用scrollView的滑动大小与屏幕宽度取整数 得到滑动的页数
    [navSliderMenu selectAtRow:(int)((scrollView.contentOffset.x+screenWidth/2.f)/screenWidth) andDelegate:NO];
    //根据页数添加相应的视图
    [self addListVCWithIndex:(int)(scrollView.contentOffset.x/screenWidth)];
    [self addListVCWithIndex:(int)(scrollView.contentOffset.x/screenWidth)+1];
    
}

@end
/  QHNavSliderMenu.h

#import 
//结构体,定义了滑块导航的类型
typedef NS_ENUM(NSInteger, QHNavSliderMenuType) {
    QHNavSliderMenuTypeTitleOnly = 0,//导航滑块菜单类型仅标题
    QHNavSliderMenuTypeTitleAndImage//导航滑块菜单类型标题和图片
};
//声明协议
@protocol QHNavSliderMenuDelegate;

@class QHNavSliderMenuStyleModel;
@interface QHNavSliderMenu : UIView{
    
@protected QHNavSliderMenuStyleModel *styleModel;
__weak idsliderDelegate;
    
}

@property (nonatomic,readonly)NSInteger currentSelectIndex;

//init
- (instancetype)initWithFrame:(CGRect)frame
                andStyleModel:(QHNavSliderMenuStyleModel *)styleModel
                  andDelegate:(id)delegate
                     showType:(QHNavSliderMenuType)type;

/*!
 *  @author imqiuhang, 15-08-12
 *  @brief  如果外部的视图是可以滑动的  那么滑动了以后 调用这个方法来更改被选中的btn
 *  @param row      第几个 是从0开始的
 *  @param delegate 是否回调 在外部调用的话一般都是no 如果想再次调起delegate则设置为yes 那么就会调起navSliderMenuDidSelectAtRow:(NSInteger)row;
 */
- (void)selectAtRow:(NSInteger)row andDelegate:(BOOL)delegate;

- (float)countWidthOfString:(NSString *)string WithHeight:(float)height Font:(UIFont *)font;

@end



@interface QHNavSliderMenuStyleModel : NSObject
/*menu的标题数组,必传*/
@property (nonatomic,strong) NSArray *menuTitles;

///>>>>>>>>>QHNavSliderMenuType为QHNavSliderMenuTypeTitleAndImage类型需要设置的4个属性
/*未选中显示的图片数组*/
@property (nonatomic,strong) NSArray *menuImagesNormal;
/*选中时显示的图片数组*/
@property (nonatomic,strong) NSArray *menuImagesSelect;
/*未选中时候按钮的颜色*/
@property (nonatomic,strong) UIColor *sliderMenuBtnBgColorForSelect;
/*选中时候按钮的图片*/
@property (nonatomic,strong) UIColor *sliderMenuBtnBgColorForNormal;
///<<<<<<<<<<<<<<<<<<<<<<<<

/*选中时候文字的颜色*/
@property (nonatomic,strong) UIColor *sliderMenuTextColorForSelect;
/*未选中时候文字的颜色*/
@property (nonatomic,strong) UIColor *sliderMenuTextColorForNormal;

@property (nonatomic,strong)UIColor *lineColor;
@property (nonatomic)float lineHeight;
/*文字的font 默认是system size10*/
@property (nonatomic,strong) UIFont  *titleLableFont;

/*按钮之间的间距 默认是0*/
@property (nonatomic       ) float   menuHorizontalSpacing;
/*按钮的宽度   默认是屏幕宽度/4 */
@property (nonatomic       ) float   menuWidth;

/*适应屏幕,居中显示,只有当一个屏幕能全部显示的下的时候才有效*/
@property (nonatomic)BOOL sizeToFitScreenWidth;

//居中显示
@property (nonatomic)BOOL sizeInMiddle;

//是否根据文本的长短自动调整线条的长度
@property (nonatomic)BOOL autoSuitLineViewWithdForBtnTitle;
//点击滑块菜单时菜单是否滚动
@property (nonatomic)BOOL donotScrollTapViewWhileScroll;
//是否隐藏滑块菜单的下分割线
@property (nonatomic)BOOL hideViewBottomLineView;


+ (instancetype)menuStyleModelForHome;


@end

@protocol QHNavSliderMenuDelegate 

@required
///点击了某个按钮
- (void)navSliderMenuDidSelectAtRow:(NSInteger)row;

@optional
///重复点击了某个按钮
- (void)navSliderMenuDidReSelectAtRow:(NSInteger)row;
- (void)navScrollViewDidScroll:(float)offsetX;

@end
//  QHNavSliderMenu.m
#import "QHNavSliderMenu.h"
#import "UIView+Extension.h"
#import "macrodefine.h"

#define sliderBtnTagStartPoint 10102

@implementation QHNavSliderMenu
{
    NSInteger curSelectRow;//选择的行
    UIView *bottomTabLine;//视图下分割线
    QHNavSliderMenuType menuType;//滑块导航类型
    UIScrollView *contentScrollView;//滚动视图
}

- (instancetype)initWithFrame:(CGRect)frame andStyleModel:(QHNavSliderMenuStyleModel *)aStyleModel andDelegate:(id)delegate  showType:(QHNavSliderMenuType)type;{
    if (self=[super initWithFrame:frame]) {
        styleModel     = aStyleModel;
        curSelectRow   = -1;
        menuType       = type;
        sliderDelegate = delegate;
        [self initSliderTopNavView:type];
    }
    return self;
}

- (void)selectAtRow:(NSInteger)row andDelegate:(BOOL)delegate {
    //如果传入的行大于菜单标题的数量或者小于0
    if (row>styleModel.menuTitles.count-1||row<0) {
        //则结束方法
        return;
    }
    //如果选择了同一个菜单
    if (row==curSelectRow) {
        //判断代理是否存在并且响应了方法
        if (delegate&&[sliderDelegate respondsToSelector:@selector(navSliderMenuDidReSelectAtRow:)]) {
            [sliderDelegate navSliderMenuDidReSelectAtRow:row];
        }
        //结束方法
        return;
    }
    //未选择同一菜单
    if(delegate&&[sliderDelegate respondsToSelector:@selector(navSliderMenuDidSelectAtRow:)]) {
        [sliderDelegate navSliderMenuDidSelectAtRow:row];
    }
    
    
    //一般在一个View 下想调用其下多个子View时,为了方便可以通过给每个子View标记tag然后使用viewWithTag:tag方法直接调用
    UIButton *unSelectBtn =(UIButton *)[contentScrollView viewWithTag:curSelectRow+sliderBtnTagStartPoint];
    UIButton *selectBtn=(UIButton *)[contentScrollView viewWithTag:row+sliderBtnTagStartPoint];
    if (menuType==QHNavSliderMenuTypeTitleOnly) {
        //animateWithDuration方法来实现动画效果,duration为动画持续的时间,delay为动画开始执行前等待的时间,options为动画执行的选项,animations为动画效果的代码块,completion为动画执行完毕以后执行的代码块
        [UIView animateWithDuration:ABS(row-curSelectRow)*0.1 delay:0.f options:UIViewAnimationOptionCurveEaseInOut animations:^{
            //是否根据文本的长短自动调整线条的长度
            if (self->styleModel.autoSuitLineViewWithdForBtnTitle) {
                float width = [self countWidthOfString:self->styleModel.menuTitles[row] WithHeight:100 Font:self->styleModel.titleLableFont];
                self->bottomTabLine.width = width;
            }
            self->bottomTabLine.centerX=selectBtn.centerX;
        } completion:^(BOOL finished) {
            unSelectBtn.selected=NO;
            selectBtn.selected=YES;
        }];
        
    }else {
        unSelectBtn.selected=NO;
        selectBtn.selected=YES;
    }
    
    
    curSelectRow=row;
    _currentSelectIndex = curSelectRow;
    [self adjustToScrollView:curSelectRow];
}

//点击后适当滚动以适应
- (void)adjustToScrollView :(NSInteger)row {
    //点击滑块菜单时菜单是否滚动
    if (styleModel.donotScrollTapViewWhileScroll) {
        return;
    }
    
    UIButton *selectBtn=(UIButton *)[contentScrollView viewWithTag:row+sliderBtnTagStartPoint];
    
    if(styleModel.sizeToFitScreenWidth) {
        
    }else {
        
        
        float offsetx = selectBtn.left - contentScrollView.width/2.f+ styleModel.menuWidth/2.f;
        
        offsetx=offsetx<0?0:offsetx;
        offsetx = offsetx+contentScrollView.width>(contentScrollView.contentSize.width)?contentScrollView.contentSize.width-contentScrollView.width:offsetx;
        
        [contentScrollView setContentOffset:CGPointMake(offsetx, contentScrollView.contentOffset.y) animated:YES];
    }
    
    
    
}
//滑块菜单按钮的点击事件
- (void)sliderBtnSelectEvent:(UIButton *)sender {
    
    [self selectAtRow:sender.tag-sliderBtnTagStartPoint andDelegate:YES];
}

//scrollview滚动过程中,自动调用的方法
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if ([sliderDelegate respondsToSelector:@selector(navScrollViewDidScroll:)]) {
        [sliderDelegate navScrollViewDidScroll:scrollView.contentOffset.x];
    }
}
//初始化滑块导航顶部视图:传入滑块导航类型
- (void)initSliderTopNavView:(QHNavSliderMenuType)type {
    //初始化滚动视图
    contentScrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
    //添加滚动视图
    [self addSubview:contentScrollView];
    //NSAssert:NSAssert是一个预处理宏, 他的主要作用就是可以让开发者比较便捷的捕获一个错误, 让程序崩溃, 同时报出错误提示。例如:NSAssert(x != nil, @"错误提示"),当你的程序在运行到这个宏时, 如果变量x的值为nil, 此时程序就会崩溃, 并且抛出一个异常, 异常提示就是你后面写的提示。
    NSAssert(styleModel.menuTitles, @"顶部滑动栏标题为空?");
    if (type==QHNavSliderMenuTypeTitleAndImage) {
        if(!styleModel.menuImagesNormal) {
            NSAssert(0, @"QHNavSliderMenuTypeTitleAndImage却未传入未选中的显示图片数组?");
        }
        if (!styleModel.menuImagesSelect) {
            NSAssert(0, @"QHNavSliderMenuTypeTitleAndImage却未传入选中时的显示图片数组?");
        }
        
        if(styleModel.menuTitles.count0?styleModel.lineHeight:2)];
        //设置底部视图的底部位置
        bottomTabLine.bottom = contentScrollView.height;
        //设置底部视图的背景颜色
        bottomTabLine.backgroundColor = styleModel.lineColor?styleModel.lineColor:styleModel.sliderMenuTextColorForSelect;
        //将底部视图添加到滚动视图
        [contentScrollView addSubview:bottomTabLine];
        //如果一个屏幕能全部显示菜单
        if (styleModel.sizeToFitScreenWidth) {
            //设置底部视图的左部位置
            bottomTabLine.left = ((UIButton *)[contentScrollView viewWithTag:0+sliderBtnTagStartPoint]).left;
        }
        
        [self selectAtRow:0 andDelegate:NO];
    }
    //是否隐藏滑块菜单的下分割线
    if (!styleModel.hideViewBottomLineView) {
        UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, self.height, self.width, 1.0f)];
        lineView.backgroundColor = YMSLineViewColor;
        //clipsToBounds 决定了子视图的显示范围。具体的说,就是当它取值为 YES 时,剪裁超出父视图范围的子视图部分;当它取值为 NO 时,不剪裁子视图。默认值为 NO,但是在 UIScrollView 中,它的默认值是 YES,也就是说默认裁剪的。
        self.clipsToBounds = NO;
        [self addSubview:lineView];
        
    }
    
}
//字符串宽度计算
- (float)countWidthOfString:(NSString *)string WithHeight:(float)height Font:(UIFont *)font {
    if (![string isNotEmptyCtg]) {
        string = @"";
    }
    
    NSDictionary *attribute = @{NSFontAttributeName: font};
    //- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(nullable NSDictionary *)attributes context:(nullable NSStringDrawingContext *)context;
    // 参数1: 自适应尺寸,提供一个宽度,去自适应高度
    // 参数2:自适应设置 (以行为矩形区域自适应,以字体字形自适应)
    // 参数3:文字属性,通常这里面需要知道是字体大小,需要字典存储
    // 参数4:绘制文本上下文,做底层排版时使用,填nil即可
    // NSStringDrawingTruncatesLastVisibleLine:当文本不能适合的放进指定的边界之内,则自动在最后一行添加省略符号。如果NSStringDrawingUsesLineFragmentOrigin没有设置,则该选项不生效
    //NSStringDrawingUsesLineFragmentOrigin:// 整个文本将以每行组成的矩形为单位计算整个文本的尺寸
    //NSStringDrawingUsesFontLeading:使用字体的行间距来计算文本占用的范围,即每一行的底部到下一行的底部的距离计算
    CGSize labelSize = [string boundingRectWithSize:CGSizeMake(height, MAXFLOAT) options: NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:attribute context:nil].size;
    return labelSize.width;
#pragma clang diagnostic pop
}

@end

@implementation QHNavSliderMenuStyleModel

+ (instancetype)menuStyleModelForHome {
    QHNavSliderMenuStyleModel *model       = [QHNavSliderMenuStyleModel new];
    model.sizeToFitScreenWidth             = YES;
    model.hideViewBottomLineView           = YES;
    model.titleLableFont                   = defaultFont(17);
    model.lineHeight                       = 4.f;
    model.sliderMenuTextColorForNormal     = YMSNavTitleColor;
    model.sliderMenuTextColorForSelect     = YMSNavTitleColor;
    model.lineColor                        = YMSBrandColor;
    model.autoSuitLineViewWithdForBtnTitle = YES;
    model.sizeInMiddle                     = YES;
    model.menuHorizontalSpacing            = 40.f;
    
    return model;
}

@end

//  UIView+Extension.h

#import 

@interface UIView (Extension)

/**  起点x坐标  */
@property (nonatomic, assign) CGFloat x;
/**  起点y坐标  */
@property (nonatomic, assign) CGFloat y;
/**  中心点x坐标  */
@property (nonatomic, assign) CGFloat centerX;
/**  中心点y坐标  */
@property (nonatomic, assign) CGFloat centerY;
/**  宽度  */
@property (nonatomic, assign) CGFloat width;
/**  高度  */
@property (nonatomic, assign) CGFloat height;
/**  顶部  */
@property (nonatomic, assign) CGFloat top;
/**  底部  */
@property (nonatomic, assign) CGFloat bottom;
/**  左边  */
@property (nonatomic, assign) CGFloat left;
/**  右边  */
@property (nonatomic, assign) CGFloat right;
/**  size  */
@property (nonatomic, assign) CGSize size;
/**  origin */
@property (nonatomic, assign) CGPoint origin;


/**  设置圆角  */
- (void)rounded:(CGFloat)cornerRadius;

/**  设置圆角和边框  */
- (void)rounded:(CGFloat)cornerRadius width:(CGFloat)borderWidth color:(UIColor *)borderColor;

/**  设置边框  */
- (void)border:(CGFloat)borderWidth color:(UIColor *)borderColor;

/**   给哪几个角设置圆角  */
-(void)round:(CGFloat)cornerRadius RectCorners:(UIRectCorner)rectCorner;

/**  设置阴影  */
-(void)shadow:(UIColor *)shadowColor opacity:(CGFloat)opacity radius:(CGFloat)radius offset:(CGSize)offset;

- (UIViewController *)viewController;

+ (CGFloat)getLabelHeightByWidth:(CGFloat)width Title:(NSString *)title font:(UIFont *)font;
    

@end

//  UIView+Extension.m

#import "UIView+Extension.h"

@implementation UIView (Extension)
#pragma mark - frame
//起点x坐标
- (void)setX:(CGFloat)x {
    CGRect frame = self.frame;
    frame.origin.x = x;
    self.frame = frame;
}
//起点y坐标
- (void)setY:(CGFloat)y {
    CGRect frame = self.frame;
    frame.origin.y = y;
    self.frame = frame;
}

- (CGFloat)x {
    return self.frame.origin.x;
}

- (CGFloat)y {
    return self.frame.origin.y;
}
//中心点x坐标
- (void)setCenterX:(CGFloat)centerX {
    
    CGPoint center = self.center;
    center.x = centerX;
    self.center = center;
    
}

- (CGFloat)centerX {
    return self.center.x;
}
//中心点y坐标
- (void)setCenterY:(CGFloat)centerY{
    CGPoint center = self.center;
    center.y = centerY;
    self.center = center;
}

- (CGFloat)centerY {
    return self.center.y;
}
//宽度
- (void)setWidth:(CGFloat)width {
    CGRect frame = self.frame;
    frame.size.width = width;
    self.frame = frame;
}
//高度
- (void)setHeight:(CGFloat)height {
    CGRect frame = self.frame;
    frame.size.height = height;
    self.frame = frame;
}

- (CGFloat)height {
    return self.frame.size.height;
}

- (CGFloat)width {
    return self.frame.size.width;
}

- (void)setSize:(CGSize)size {
    CGRect frame = self.frame;
    frame.size = size;
    self.frame = frame;
}

- (CGSize)size {
    return self.frame.size;
}

- (void)setOrigin:(CGPoint)origin {
    CGRect frame = self.frame;
    frame.origin = origin;
    self.frame = frame;
}

- (CGPoint)origin {
    return self.frame.origin;
}

//顶部
- (CGFloat)top {
    return self.frame.origin.y;
}

- (void)setTop:(CGFloat)top {
    CGRect frame = self.frame;
    frame.origin.y = top;
    self.frame = frame;
}
//左部
- (CGFloat)left {
    return self.frame.origin.x;
}

- (void)setLeft:(CGFloat)left {
    CGRect frame = self.frame;
    frame.origin.x = left;
    self.frame = frame;
}

//下部
- (CGFloat)bottom {
    return self.frame.size.height + self.frame.origin.y;
}

- (void)setBottom:(CGFloat)bottom {
    CGRect frame = self.frame;
    frame.origin.y = bottom - frame.size.height;
    self.frame = frame;
}
//右部
- (CGFloat)right {
    return self.frame.size.width + self.frame.origin.x;
}

- (void)setRight:(CGFloat)right {
    CGRect frame = self.frame;
    frame.origin.x = right - frame.size.width;
    self.frame = frame;
}

#pragma mark - layer
//设置圆角
- (void)rounded:(CGFloat)cornerRadius {
    [self rounded:cornerRadius width:0 color:nil];
}

- (void)border:(CGFloat)borderWidth color:(UIColor *)borderColor {
    [self rounded:0 width:borderWidth color:borderColor];
}
//设置圆角和边框
- (void)rounded:(CGFloat)cornerRadius width:(CGFloat)borderWidth color:(UIColor *)borderColor {
    //设置圆角
    self.layer.cornerRadius = cornerRadius;
    //设置边框宽度
    self.layer.borderWidth = borderWidth;
    //设置边框画颜色
    self.layer.borderColor = [borderColor CGColor];
    //masksToBounds:根据设置的边框进行剪裁,背景或内容超出边框则不显示,如果不设置为yes,那么超出设置边框的部分是不会有影响的
    self.layer.masksToBounds = YES;
}

//给哪几个角设置圆角
-(void)round:(CGFloat)cornerRadius RectCorners:(UIRectCorner)rectCorner {
    
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:rectCorner cornerRadii:CGSizeMake(cornerRadius, cornerRadius)];
    CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
    maskLayer.frame = self.bounds;
    maskLayer.path = maskPath.CGPath;
    self.layer.mask = maskLayer;
}

//阴影
-(void)shadow:(UIColor *)shadowColor opacity:(CGFloat)opacity radius:(CGFloat)radius offset:(CGSize)offset {
    //给Cell设置阴影效果
    self.layer.masksToBounds = NO;
    //阴影颜色
    self.layer.shadowColor = shadowColor.CGColor;
    //shadowOpacity:设置了阴影的不透明度,取值范围在0~1,如果view没有设置背景色阴影也是不会显示的,默认0
    self.layer.shadowOpacity = opacity;
    //阴影半径,默认3
    self.layer.shadowRadius = radius;
    //阴影偏移量,默认(0, -3),这个跟shadowRadius配合使用
    self.layer.shadowOffset = offset;
}


#pragma mark - base
- (UIViewController *)viewController {
    //UIResponder具有nextResponder属性,也就是其SuperView或是UIViewConterller等。UIView是UIResponder的子类,所以UIView及其子类都能使用此属性。UIResponder是不会自动存储和设置这个nextResponder指针,默认都是返回nil。UIResponder的子类,必须重写这个方法去设置下一个响应者。(在这里需要理解:苹果其实已经帮我们把UIView、UIViewController、UIWindow和UIApplication都默认实现了nextResponder方法);
    //UIView实现这个方法,它返回的下一个响应者要分两种情况:如果这个视图有一个UIViewController对象管理它,它就会返回这个UIViewController对象;如果这个视图没有一个UIViewController对象管理它,它就会返回它的父视图的指针;
    //UIViewController实现这个方法,它返回它的视图管理器的指针;
    //UIWindow则返回UIApplication的指针;
    //UIApplication则返回的是nil;
    id nextResponder = [self nextResponder];
    while (nextResponder != nil) {
        //isKindOfClass:判断一个对象或一个类是否为某个类或者某个类的子类.
        if ([nextResponder isKindOfClass:[UIViewController class]]) {
            UIViewController *vc = (UIViewController *)nextResponder;
            return vc;
        }
        nextResponder = [nextResponder nextResponder];
    }
    return nil;
}

+ (CGFloat)getLabelHeightByWidth:(CGFloat)width Title:(NSString *)title font:(UIFont *)font {
    
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, width, 0)];
    label.text = title;
    label.font = font;
    label.numberOfLines = 0;
    [label sizeToFit];
    CGFloat height = label.frame.size.height;
    return height;
}

@end

//  macrodefine.h

#import "Util.h"

#ifndef macrodefine_h
#define macrodefine_h

//keyWindow,屏幕宽 屏幕高
#define KEY_WINDOW                [[UIApplication sharedApplication] keyWindow]
#define screenWidth               [[UIScreen mainScreen] bounds].size.width
#define screenHeight              [[UIScreen mainScreen] bounds].size.height

//RGB
#define QHRGBA(r, g, b,a) [UIColor colorWithRed:(r)/255.f green:(g)/255.f blue:(b)/255.f alpha:a]
#define QHRGB(r, g, b) QHRGBA(r,g,b,1)
//导航栏的标题颜色
#define YMSNavTitleColor        [Util colorWithHexString:@"333333" alpha:1.0f]
//品牌色
#define YMSBrandColor           [Util colorWithHexString:@"ff807a" alpha:1.0f]
//统一的列表线条颜色
#define YMSLineViewColor        [Util colorWithHexString:@"#E8E8E8" alpha:1.0f]

#define defaultFont(s) [UIFont fontWithName:@"HYQiHei-DZS" size:s]
//判断是否是iPhoneX系列机型
#define kIsFullScreen ((([[[UIDevice currentDevice] systemVersion] floatValue] >= 11.0f) && ([[[[UIApplication sharedApplication] delegate] window] safeAreaInsets].bottom > 0.0))? YES : NO)

#endif
//  FirstController.h
#import 
@interface FirstController : UIViewController
@end

//  FirstController.m

#import "FirstController.h"

@interface FirstController ()

@end

@implementation FirstController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor yellowColor];
    CGRect screen = [UIScreen mainScreen].bounds;
    CGFloat labelWidth = 200;
    CGFloat labelHeight = 60;
    UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake((screen.size.width - labelWidth) /2, (screen.size.height - labelHeight) /2,labelWidth,labelHeight)];
    label.text = @"第一控制器";
    label.textAlignment = NSTextAlignmentCenter;
    label.textColor = [UIColor redColor];
    //boldSystemFontOfSize设置字体大小并加粗
    label.font = [UIFont boldSystemFontOfSize:20];
    [self.view addSubview:label];
}
//  SecondController.h
#import 
@interface SecondController : UIViewController
@end

//  SecondController.m
#import "SecondController.h"
@interface SecondController ()

@end

@implementation SecondController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor cyanColor];
    CGRect screen = [UIScreen mainScreen].bounds;
    CGFloat labelWidth = 200;
    CGFloat labelHeight = 60;
    UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake((screen.size.width - labelWidth) /2, (screen.size.height - labelHeight) /2,labelWidth,labelHeight)];
    label.text = @"第二控制器";
    label.textAlignment = NSTextAlignmentCenter;
    label.textColor = [UIColor orangeColor];
    label.font = [UIFont boldSystemFontOfSize:20];
    [self.view addSubview:label];
}

@end

//  Util.h
#import 
#import 

@interface Util : NSObject
//十六进制字符串设置颜色
+ (UIColor *) colorWithHexString: (NSString *)color alpha:(float)alpha;
@end

@interface NSString (QHNSStringCtg)
//判断不是一个空字符串
- (BOOL)isNotEmptyCtg;
@end
//  Util.m
#import "Util.h"

@implementation Util
//判断不是一个空字符串
+ (UIColor *) colorWithHexString: (NSString *)color alpha:(float)alpha{
    //stringByTrimmingCharactersInSet函数过滤字符串中的特殊符号
    //[NSCharacterSet whitespaceAndNewlineCharacterSet]去掉两端的空格
    //uppercaseString:字母全部转换为大写
    NSString *cString = [[color stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString];
    
    if ([cString length] < 6) {
        return [UIColor clearColor];
    }
    //hasPrefix(string)返回一个布尔值表示字符串是否以指定的前缀开始
    //substringFromIndex:字符串从第指定位开端截取,直到最后
    if ([cString hasPrefix:@"0X"])
        cString = [cString substringFromIndex:2];
    if ([cString hasPrefix:@"#"])
        cString = [cString substringFromIndex:1];
    if ([cString length] != 6) {
        NSLog(@"输入的16进制有误,不足6位!");
        return [UIColor clearColor];
    }
    
    NSRange range;
    range.location = 0;
    range.length = 2;
    
    //r
    //substringWithRange:从指定位置截取指定的长度
    NSString *rString = [cString substringWithRange:range];
    
    //g
    range.location = 2;
    NSString *gString = [cString substringWithRange:range];
    
    //b
    range.location = 4;
    NSString *bString = [cString substringWithRange:range];
    
    // Scan values
    unsigned int r, g, b;
    //NSScanner是一个类,用于在字符串中扫描指定的字符,尤其是把它们翻译/转换为数字和别的字符串。可以在创建NSScaner时指定它的string属性,然后scanner会按照你的要求从头到尾地扫描这个字符串的每个字符。
    //scanHexInt:扫描前缀是否带有0x或者0X
    [[NSScanner scannerWithString:rString] scanHexInt:&r];
    [[NSScanner scannerWithString:gString] scanHexInt:&g];
    [[NSScanner scannerWithString:bString] scanHexInt:&b];
    
    return [UIColor colorWithRed:((float) r / 255.0f) green:((float) g / 255.0f) blue:((float) b / 255.0f) alpha:alpha];
}
@end

@implementation NSString (QHNSStringCtg)

//判断不是一个空字符串
- (BOOL)isNotEmptyCtg {
    if (!self) {
        return NO;
    }
    //[NSNull null]是值为空的对象,和nil、Nil、Null是不等价的
    //“空对象”是已经释放了内存地址的对象,即不存在的对象。
    //“值为空的对象”是分配了地址,但是没有值得对象,是实际存在的对象。
    if ([NSNull null] == (id)self) {
        return NO;
    }
    //stringByReplacingOccurrencesOfString替换出现的字符串
    NSString *curStr = [self stringByReplacingOccurrencesOfString:@" " withString:@""];
    if ([curStr isEqualToString:@""]) {
        return NO;
    }
    
    return YES;
}

@end

运行结果:
菜单滑块切换控制器控件代码示例_第1张图片
Untitled.gif

你可能感兴趣的:(菜单滑块切换控制器控件代码示例)