// 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
运行结果: