diff --git a/README.md b/README.md index 5f9a767..b014685 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,50 @@ ![1.gif](http://chuantu.biz/t5/30/1471921557x2031068758.gif) #####HYTabbarView可灵活配置UI界面 - static CGFloat const topBarItemMargin = 15; ///标题之间的间距 - static CGFloat const topBarHeight = 40; //顶部标签条的高度 +@property(nonatomic, assign)CGFloat topBarItemMargin; + +/** 顶部标签条的高度*/ +@property(nonatomic, assign)CGFloat topBarHeight; + + +/***********指示条**************/ + +/** 指示条与标题的距离*/ +indicatorWithItemMargin; + +/** 指示条颜色*/ +indicatorBackgroundColor; + +/** 指示条高度*/ +indicatorHeight; + +/** 指示条的宽度是否随标题的宽度变化,默认值为NO*/ +changeWithItemWidth; + +/** 指示条宽度,默认值为30,如果宽度需要随标题的宽度变化,则不需要设置*/ +indicatorWidth; + + +/***************标题*****************/ + +/** 第一个标题X坐标*/ +firstItemX; + +/** 标题高度*/ +itemHeight; + +/** 标题颜色*/ +itemNormalColor; + +/** 标题选中颜色*/ +itemSelectedColor; + +/** 标题字体大小*/ +itemNormalFont; + +/** 标题选中字体大小*/ +itemSelectedFont; + ####实现思路详解 - 界面分析:分为上下部分,顶部UIScrollView,底部UICollectionView.再实现两部分的联动即可实现 (底部视图相对复杂,占用内存大,底部用UICollectionView实现会比用UIScrollView性能好很多) @@ -76,7 +118,22 @@ if (!_tabbarView) { _tabbarView = ({ - HYTabbarView * tabbar = [[HYTabbarView alloc]initWithFrame:CGRectMake(0, 64, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - 64)]; + HYTabbarView *tabbarView = [[HYTabbarView alloc]initWithFrame:CGRectMake(0, 120, HYScreenW, HYScreenH - 120 - 44 - 20)]; + tabbarView.controllerWithTopBarMargin = 7; + tabbarView.topBar.topBarHeight = 30; + tabbarView.topBar.topBarItemMargin = 22.5; + tabbarView.topBar.indicatorWithItemMargin = 6; + tabbarView.topBar.indicatorBackgroundColor = [UIColor orangeColor]; + tabbarView.topBar.indicatorHeight = 3; + // tabbarView.topBar.indicatorWidth = 50; + // tabbarView.topBar.changeWithItemWidth = YES; + tabbarView.topBar.firstItemX = 15; + tabbarView.topBar.itemNormalColor = [UIColor blackColor]; + tabbarView.topBar.itemSelectedColor = [UIColor greenColor]; + tabbarView.topBar.itemNormalFont = [UIFont systemFontOfSize:15]; + tabbarView.topBar.itemSelectedFont = [UIFont systemFontOfSize:18]; + + [self.view addSubview:tabbarView]; //传入九个控制器,每个控制器分别管理对应的视图 UIViewController * vc0 = [[UIViewController alloc]init]; diff --git "a/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist" "b/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist" new file mode 100644 index 0000000..18d9810 --- /dev/null +++ "b/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist" @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git "a/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276.xcodeproj/project.xcworkspace/xcuserdata/rhkj.xcuserdatad/UserInterfaceState.xcuserstate" "b/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276.xcodeproj/project.xcworkspace/xcuserdata/rhkj.xcuserdatad/UserInterfaceState.xcuserstate" new file mode 100644 index 0000000..265694d Binary files /dev/null and "b/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276.xcodeproj/project.xcworkspace/xcuserdata/rhkj.xcuserdatad/UserInterfaceState.xcuserstate" differ diff --git "a/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276.xcodeproj/xcuserdata/rhkj.xcuserdatad/xcschemes/xcschememanagement.plist" "b/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276.xcodeproj/xcuserdata/rhkj.xcuserdatad/xcschemes/xcschememanagement.plist" new file mode 100644 index 0000000..c56e4b8 --- /dev/null +++ "b/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276.xcodeproj/xcuserdata/rhkj.xcuserdatad/xcschemes/xcschememanagement.plist" @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + 标签栏视图.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git "a/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276/HYTabbarView.h" "b/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276/HYTabbarView.h" index 0c634be..98b4501 100644 --- "a/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276/HYTabbarView.h" +++ "b/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276/HYTabbarView.h" @@ -7,9 +7,13 @@ // #import - +#import "HYTopBar.h" @interface HYTabbarView : UIView +/** 标题栏*/ +@property(nonatomic, strong)HYTopBar *topBar; +/** 页面与topBar的距离*/ +@property(nonatomic, assign)CGFloat controllerWithTopBarMargin; /** * 添加一个子控制器 */ diff --git "a/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276/HYTabbarView.m" "b/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276/HYTabbarView.m" index ea54f62..347ff83 100644 --- "a/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276/HYTabbarView.m" +++ "b/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276/HYTabbarView.m" @@ -8,16 +8,16 @@ #import "HYTabbarView.h" #import "HYTabbarCollectionCell.h" -#import "HYTopBar.h" -static CGFloat const topBarHeight = 40; //顶部标签条的高度 +//#define topBarHeight FitWidth(30)//顶部标签条的高度 @interface HYTabbarView () @property (nonatomic,strong) NSMutableArray *subViewControllers; -@property (nonatomic,strong) HYTopBar *tabbar; @property (nonatomic,strong) UICollectionView *contentView; @property (nonatomic,assign) CGFloat tabbarWidth; //顶部标签条的宽度 +@property(nonatomic, strong)UICollectionViewFlowLayout *layout; + @end @implementation HYTabbarView @@ -36,10 +36,10 @@ - (instancetype)initWithFrame:(CGRect)frame //添加子控件 - (void)setUpSubview{ - self.tabbar = [[HYTopBar alloc] initWithFrame:CGRectMake(0, 0, HYScreenW, topBarHeight)]; - [self addSubview:self.tabbar]; - self.tabbar.backgroundColor = [UIColor orangeColor]; - self.tabbar.topBarDelegate = self; + self.topBar = [[HYTopBar alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)]; + [self addSubview:self.topBar]; + self.topBar.backgroundColor = [UIColor whiteColor]; + self.topBar.topBarDelegate = self; [self addSubview:self.contentView]; } @@ -54,7 +54,7 @@ - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSe - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ HYTabbarCollectionCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"HYTabbarCollectionCell" forIndexPath:indexPath]; - + cell.subVc = self.subViewControllers[indexPath.row] ; return cell; } @@ -63,7 +63,7 @@ - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cell - (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(nonnull UICollectionViewCell *)cell forItemAtIndexPath:(nonnull NSIndexPath *)indexPath { NSInteger index = (collectionView.contentOffset.x + collectionView.bounds.size.width * 0.5) / collectionView.bounds.size.width; - [self.tabbar setSelectedItem:index]; + [self.topBar setSelectedItem:index]; } @@ -73,12 +73,18 @@ - (void)HYTopBarChangeSelectedItem:(HYTopBar *)topbar selectedIndex:(NSInteger)i self.contentView.contentOffset = CGPointMake(HYScreenW * index, 0); } +-(void)HYTopBarChangeContentViewHeight{ + self.layout.itemSize = (CGSize){self.bounds.size.width,(self.frame.size.height - self.topBar.topBarHeight - self.controllerWithTopBarMargin)}; + _contentView.frame = CGRectMake(0, self.topBar.topBarHeight + self.controllerWithTopBarMargin, HYScreenW, self.layout.itemSize.height); +} #pragma mark - ************************* 对外接口 ************************* + + //外界传个控制器,添加一个栏目 - (void)addSubItemWithViewController:(UIViewController *)viewController{ - [self.tabbar addTitleBtn:viewController.title]; - [self.tabbar setSelectedItem:0]; + [self.topBar addTitleBtn:viewController.title]; + [self.topBar setSelectedItem:0]; [self.subViewControllers addObject:viewController]; [self.contentView reloadData]; } @@ -91,6 +97,12 @@ - (void)selectNewItem{ } #pragma mark - ************************* 懒加载 ************************* +-(void)setControllerWithTopBarMargin:(CGFloat)controllerWithTopBarMargin{ + _controllerWithTopBarMargin = controllerWithTopBarMargin; + self.layout.itemSize = (CGSize){self.bounds.size.width,(self.frame.size.height - self.topBar.topBarHeight - self.controllerWithTopBarMargin)}; + _contentView.frame = CGRectMake(0, self.topBar.topBarHeight + self.controllerWithTopBarMargin, HYScreenW, self.layout.itemSize.height); + +} - (NSMutableArray *)subViewControllers{ if (!_subViewControllers) { @@ -103,12 +115,13 @@ - (UICollectionView *)contentView { if (!_contentView) { UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc]init]; + self.layout = layout; //设置layout 属性 - layout.itemSize = (CGSize){self.bounds.size.width,(self.bounds.size.height - topBarHeight)}; + layout.itemSize = (CGSize){self.bounds.size.width,(self.frame.size.height - self.topBar.topBarHeight - self.controllerWithTopBarMargin)}; layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; layout.minimumLineSpacing = 0; - _contentView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, topBarHeight, HYScreenW, HYScreenH - topBarHeight - 64) collectionViewLayout:layout]; + _contentView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, self.topBar.topBarHeight + self.controllerWithTopBarMargin, HYScreenW, layout.itemSize.height) collectionViewLayout:layout]; _contentView.showsHorizontalScrollIndicator = NO; _contentView.pagingEnabled = YES; diff --git "a/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276/HYTopBar.h" "b/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276/HYTopBar.h" index 1650b97..f407b7d 100644 --- "a/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276/HYTopBar.h" +++ "b/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276/HYTopBar.h" @@ -13,12 +13,58 @@ @class HYTopBar; @protocol HYTopBarDelegate - (void)HYTopBarChangeSelectedItem:(HYTopBar *)topbar selectedIndex:(NSInteger)index; +- (void)HYTopBarChangeContentViewHeight; @end @interface HYTopBar : UIScrollView @property (nonatomic,weak) id topBarDelegate; +/** 标题之间的间距*/ +@property(nonatomic, assign)CGFloat topBarItemMargin; + +/** 顶部标签条的高度*/ +@property(nonatomic, assign)CGFloat topBarHeight; + + +/***********指示条**************/ + +/** 指示条与标题的距离*/ +@property(nonatomic, assign)CGFloat indicatorWithItemMargin; + +/** 指示条颜色*/ +@property(nonatomic, strong)UIColor *indicatorBackgroundColor; + +/** 指示条高度*/ +@property(nonatomic, assign)CGFloat indicatorHeight; + +/** 指示条的宽度是否随标题的宽度变化,默认值为NO*/ +@property(nonatomic, assign)BOOL changeWithItemWidth; + +/** 指示条宽度,默认值为30,如果宽度需要随标题的宽度变化,则不需要设置*/ +@property(nonatomic, assign)CGFloat indicatorWidth; + + +/***************标题*****************/ + +/** 第一个标题X坐标*/ +@property(nonatomic, assign)CGFloat firstItemX; + +/** 标题高度*/ +@property(nonatomic, assign)CGFloat itemHeight; + +/** 标题颜色*/ +@property(nonatomic, strong)UIColor *itemNormalColor; + +/** 标题选中颜色*/ +@property(nonatomic, strong)UIColor *itemSelectedColor; + +/** 标题字体大小*/ +@property(nonatomic, strong)UIFont *itemNormalFont; + +/** 标题选中字体大小*/ +@property(nonatomic, strong)UIFont *itemSelectedFont; + - (void)addTitleBtn:(NSString *)title; - (void)setSelectedItem:(NSInteger)index; diff --git "a/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276/HYTopBar.m" "b/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276/HYTopBar.m" index dc1ec45..8c006bd 100644 --- "a/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276/HYTopBar.m" +++ "b/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276/HYTopBar.m" @@ -8,12 +8,14 @@ #import "HYTopBar.h" -static CGFloat const topBarItemMargin = 15; ///标题之间的间距 -static CGFloat const topBarHeight = 40; //顶部标签条的高度 +//static CGFloat const topBarItemMargin = 22.5; ///标题之间的间距 +//static CGFloat const topBarHeight = 18; //顶部标签条的高度 @interface HYTopBar() @property (nonatomic,strong) NSMutableArray *btnArray; @property (nonatomic,strong) UIButton *selectedBtn; +/** 滑动的横线*/ +@property(nonatomic, strong)UIView *indicatorView; @end @implementation HYTopBar @@ -25,6 +27,11 @@ - (instancetype)initWithFrame:(CGRect)frame self.showsHorizontalScrollIndicator = NO; self.showsVerticalScrollIndicator = NO; self.bounces = NO; + + // 滑动条 + UIView *indicatorView = [[UIView alloc] init]; + self.indicatorView = indicatorView; + [self addSubview:indicatorView]; } return self; } @@ -34,12 +41,14 @@ - (void)addTitleBtn:(NSString *)title { UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; [btn setTitle:title forState:UIControlStateNormal]; [btn sizeToFit]; - btn.titleLabel.font = [UIFont systemFontOfSize:15]; - [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; - [btn setTitleColor:[UIColor redColor] forState:UIControlStateSelected]; + btn.titleLabel.font = self.itemNormalFont; + [btn setTitleColor:self.itemNormalColor forState:UIControlStateNormal]; + [btn setTitleColor:self.itemSelectedColor forState:UIControlStateSelected]; [btn addTarget:self action:@selector(itemSelectedChange:) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:btn]; [self.btnArray addObject:btn]; + + [self layoutIfNeeded]; } - (void)itemSelectedChange:(UIButton *)btn { @@ -53,15 +62,28 @@ - (void)itemSelectedChange:(UIButton *)btn { - (void)setSelectedItem:(NSInteger)index { UIButton *btn = self.btnArray[index]; + + // btn.titleLabel.font = self.itemSelectedFont; [UIView animateWithDuration:0.25 animations:^{ self.selectedBtn.selected = NO; - self.selectedBtn.titleLabel.font = [UIFont systemFontOfSize:15]; + self.selectedBtn.titleLabel.font = self.itemNormalFont; btn.selected = YES; - btn.titleLabel.font = [UIFont systemFontOfSize:18]; + btn.titleLabel.font = self.itemSelectedFont; self.selectedBtn = btn; - + + if (self.changeWithItemWidth) { + CGRect newFrame = self.indicatorView.frame; + newFrame.size.width = btn.frame.size.width; + self.indicatorView.frame = newFrame; + } + + + CGPoint newCenter = self.indicatorView.center; + newCenter.x = btn.center.x; + self.indicatorView.center = newCenter; + // 计算偏移量 CGFloat offsetX = btn.center.x - HYScreenW * 0.5; if (offsetX < 0) offsetX = 0; @@ -75,7 +97,12 @@ - (void)setSelectedItem:(NSInteger)index { } }]; } - +- (void)setTopBarHeight:(CGFloat)topBarHeight{ + _topBarHeight = topBarHeight; + if ([self.topBarDelegate respondsToSelector:@selector(HYTopBarChangeContentViewHeight)]) { + [self.topBarDelegate HYTopBarChangeContentViewHeight]; + } +} - (NSMutableArray *)btnArray{ if (!_btnArray) { @@ -85,16 +112,40 @@ - (NSMutableArray *)btnArray{ } - (void)layoutSubviews { - + NSLog(@"-----layoutSubviews"); [super layoutSubviews]; - - CGFloat btnH = topBarHeight; - CGFloat btnX = topBarItemMargin; + self.indicatorView.backgroundColor = self.indicatorBackgroundColor; + + CGRect newFrame = self.indicatorView.frame; + newFrame.size.height = self.indicatorHeight; + self.indicatorView.frame = newFrame; + + CGFloat radius = self.indicatorView.frame.size.height * 0.5; + self.indicatorView.layer.cornerRadius = radius; + + if((!self.changeWithItemWidth) && self.indicatorWidth != 0){ + CGRect newFrame = self.indicatorView.frame; + newFrame.size.width = self.indicatorWidth; + self.indicatorView.frame = newFrame; + }else if(self.indicatorWidth == 0 && !self.changeWithItemWidth){ + CGRect newFrame = self.indicatorView.frame; + newFrame.size.width = 30; + self.indicatorView.frame = newFrame; + } + + CGFloat btnX = self.firstItemX; for (int i = 0 ; i < self.btnArray.count; i++) { - + UIButton *btn = self.btnArray[i]; - btn.frame = CGRectMake(btnX, 0, btn.frame.size.width, btnH); - btnX += btn.frame.size.width + topBarItemMargin; + CGRect titileSize = [btn.titleLabel.text boundingRectWithSize:CGSizeMake(100, 100) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:self.itemSelectedFont} context:nil]; + + btn.frame = CGRectMake(btnX, 0, btn.frame.size.width, titileSize.size.height); + btnX += btn.frame.size.width + self.topBarItemMargin; + + CGRect newFrame = self.indicatorView.frame; + newFrame.origin.y = CGRectGetMaxY(btn.frame) + self.indicatorWithItemMargin; + self.indicatorView.frame = newFrame; + } self.contentSize = CGSizeMake(btnX, 0); } diff --git "a/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276/ViewController.m" "b/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276/ViewController.m" index 0cb2920..8b5eabf 100644 --- "a/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276/ViewController.m" +++ "b/\346\240\207\347\255\276\346\240\217\350\247\206\345\233\276/ViewController.m" @@ -41,45 +41,61 @@ - (HYTabbarView *)tabbarView{ if (!_tabbarView) { _tabbarView = ({ - HYTabbarView * tabbar = [[HYTabbarView alloc]initWithFrame:CGRectMake(0, 64, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - 64)]; + HYTabbarView *tabbarView = [[HYTabbarView alloc]initWithFrame:CGRectMake(0, 120, HYScreenW, HYScreenH - 120 - 44 - 20)]; + tabbarView.controllerWithTopBarMargin = 7; + tabbarView.topBar.topBarHeight = 30; + tabbarView.topBar.topBarItemMargin = 22.5; + tabbarView.topBar.indicatorWithItemMargin = 6; + tabbarView.topBar.indicatorBackgroundColor = [UIColor orangeColor]; + tabbarView.topBar.indicatorHeight = 3; +// tabbarView.topBar.indicatorWidth = 50; + // tabbarView.topBar.changeWithItemWidth = YES; + tabbarView.topBar.firstItemX = 15; + tabbarView.topBar.itemNormalColor = [UIColor blackColor]; + tabbarView.topBar.itemSelectedColor = [UIColor greenColor]; + tabbarView.topBar.itemNormalFont = [UIFont systemFontOfSize:15]; + tabbarView.topBar.itemSelectedFont = [UIFont systemFontOfSize:18]; + + [self.view addSubview:tabbarView]; + TestViewController * vc0 = [[TestViewController alloc]init]; vc0.title = @"推荐"; - [tabbar addSubItemWithViewController:vc0]; + [tabbarView addSubItemWithViewController:vc0]; TestViewController * vc1 = [[TestViewController alloc]init]; vc1.title = @"热点"; - [tabbar addSubItemWithViewController:vc1]; + [tabbarView addSubItemWithViewController:vc1]; TestViewController * vc2 = [[TestViewController alloc]init]; vc2.title = @"视频"; - [tabbar addSubItemWithViewController:vc2]; + [tabbarView addSubItemWithViewController:vc2]; TestViewController * vc3 = [[TestViewController alloc]init]; vc3.title = @"中国好声音"; - [tabbar addSubItemWithViewController:vc3]; + [tabbarView addSubItemWithViewController:vc3]; TestViewController * vc4 = [[TestViewController alloc]init]; vc4.title = @"数码"; - [tabbar addSubItemWithViewController:vc4]; + [tabbarView addSubItemWithViewController:vc4]; TestViewController * vc5 = [[TestViewController alloc]init]; vc5.title = @"头条号"; - [tabbar addSubItemWithViewController:vc5]; + [tabbarView addSubItemWithViewController:vc5]; TestViewController * vc6 = [[TestViewController alloc]init]; vc6.title = @"房产"; - [tabbar addSubItemWithViewController:vc6]; + [tabbarView addSubItemWithViewController:vc6]; TestViewController * vc7 = [[TestViewController alloc]init]; vc7.title = @"奥运会"; - [tabbar addSubItemWithViewController:vc7]; + [tabbarView addSubItemWithViewController:vc7]; TestViewController * vc8 = [[TestViewController alloc]init]; vc8.title = @"时尚"; - [tabbar addSubItemWithViewController:vc8]; + [tabbarView addSubItemWithViewController:vc8]; - tabbar; + tabbarView; }); } return _tabbarView;