IOS UIScrollView + UIButton 实现页面和顶部标签页水平滚动效果
Posted 风雨无阻
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IOS UIScrollView + UIButton 实现页面和顶部标签页水平滚动效果相关的知识,希望对你有一定的参考价值。
很长一段时间没有写博客了,最近在学习ios开发,看了不少的代码,自己用UIScrollView和UIButton实现了水平滚动的效果,有点类似于今日头条的主界面框架,效果如下:
代码如下:
MyScrollView.h
#import <UIKit/UIKit.h> #import "MySegementView.h" @interface MyScrollView : UIView<UIScrollViewDelegate> - (instancetype) initWithFrame:(CGRect)frame titleArray:(NSArray *)titleArray viewArray:(NSArray *)viewArray; //滚动页面 @property (strong, nonatomic)UIScrollView *myScrollView; //顶部标签按钮滚动视图 @property (strong, nonatomic)MySegementView *mySegementView; @end
MyScrollView.m
#define SCROLLVIEW_WIDTH [UIScreen mainScreen].bounds.size.width #define SCROLLVIEW_HEIGTH self.bounds.size.height #define SEGEMENT_HEIGTHT 44 #import "MyScrollView.h" @implementation MyScrollView /* // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code } */ - (instancetype) initWithFrame:(CGRect)frame titleArray:(NSArray *)titleArray viewArray:(NSArray *)viewArray { self = [super initWithFrame:frame]; if (_mySegementView == nil) { _mySegementView = [[MySegementView alloc] initWithFrame:CGRectMake(0, 0, SCROLLVIEW_WIDTH, SEGEMENT_HEIGTHT) titleArray:titleArray block:^void(int index){ //用block实现回调,顶部按钮点击的时候滚动到指定位置 [_myScrollView setContentOffset:CGPointMake((index - 1) * SCROLLVIEW_WIDTH, 0)]; }]; } [self addSubview:_mySegementView]; [self addSubview:self.myScrollView]; if (self) { for (int i = 0; i < viewArray.count; i++) { UIViewController *viewController = viewArray[i]; viewController.view.frame = CGRectMake(i * SCROLLVIEW_WIDTH, 0, SCROLLVIEW_WIDTH, self.myScrollView.frame.size.height); [self.myScrollView addSubview:viewController.view]; } self.myScrollView.contentSize = CGSizeMake(viewArray.count * SCROLLVIEW_WIDTH, 0); } return self; } // 滚动页面视图懒加载 - (UIScrollView *)myScrollView { if (_myScrollView == nil) { _myScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, _mySegementView.frame.size.height, SCROLLVIEW_WIDTH, SCROLLVIEW_HEIGTH - _mySegementView.frame.size.height)]; _myScrollView.backgroundColor = [UIColor clearColor]; _myScrollView.delegate = self; _myScrollView.showsVerticalScrollIndicator = NO; _myScrollView.showsHorizontalScrollIndicator = NO; _myScrollView.bounces = NO; _myScrollView.scrollsToTop = NO; _myScrollView.pagingEnabled = YES; } return _myScrollView; } //滚动结束,更新按钮下方线条 -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { if (scrollView==_myScrollView) { int p=_myScrollView.contentOffset.x / SCROLLVIEW_WIDTH; [_mySegementView setPageIndex:p + 1]; } } @end
MySegementView.h
#import <UIKit/UIKit.h> typedef void (^btnClickedBlock)(int index); @interface MySegementView : UIView<UIScrollViewDelegate> { int nPageIndex; int titleCount; UIButton *currentBtn; NSMutableArray *btnArray; } - (void)setPageIndex:(int)nIndex; - (instancetype) initWithFrame:(CGRect)frame titleArray : (NSArray *)titleArray block : (btnClickedBlock) clickedBlock; @property (nonatomic, copy) btnClickedBlock block; @property (strong, nonatomic) UIScrollView *segementScrollView; @property (strong, nonatomic) UIView *selectedLine; @end
MySegementView.m
#import "MySegementView.h" #define SEGEMENT_BTN_WIDTH 48 @implementation MySegementView /* // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code } */ - (instancetype) initWithFrame:(CGRect)frame titleArray : (NSArray *)titleArray block : (btnClickedBlock) clickedBlock { self = [super initWithFrame:frame]; [self addSubview:self.segementScrollView]; if (self) { [self setBackgroundColor:[UIColor colorWithRed:0x2d/255.0 green:0x2a/255.0 blue:0x2b/255.0 alpha:1]]; self.block = clickedBlock; nPageIndex = 1; titleCount = titleArray.count; btnArray = [NSMutableArray array]; for (int i = 0; i < titleCount; i++) { UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(i * SEGEMENT_BTN_WIDTH, 0, SEGEMENT_BTN_WIDTH, 42)]; [btn setTitle:titleArray[i] forState:UIControlStateNormal]; btn.titleLabel.font = [UIFont fontWithName:@"Arial" size:14]; [btn setTitleColor:[UIColor redColor] forState:UIControlStateNormal]; btn.tag = i + 1; [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchDown]; [self.segementScrollView addSubview:btn]; [btnArray addObject:btn]; } self.selectedLine.frame = CGRectMake(0, 42, SEGEMENT_BTN_WIDTH, 2); [self.segementScrollView addSubview: self.selectedLine]; self.segementScrollView.contentSize = CGSizeMake(titleCount * SEGEMENT_BTN_WIDTH, 0); } return self; } //懒加载 - (UIScrollView *)segementScrollView { if (_segementScrollView == nil) { CGRect rect = self.frame; _segementScrollView = [[UIScrollView alloc] initWithFrame:rect]; _segementScrollView.showsHorizontalScrollIndicator = NO; _segementScrollView.showsVerticalScrollIndicator = NO; _segementScrollView.bounces = NO; _segementScrollView.pagingEnabled = NO; _segementScrollView.delegate = self; _segementScrollView.scrollsToTop = NO; } return _segementScrollView; } //懒加载 - (UIView *)selectedLine { if (_selectedLine == nil) { _selectedLine = [[UIView alloc] init]; _selectedLine.backgroundColor = [UIColor redColor]; } return _selectedLine; } //设置当前页面,并更新顶部标签页 - (void)setPageIndex:(int)nIndex { if (nIndex != nPageIndex) { nPageIndex = nIndex; [self refreshSegement]; } } - (void)refreshSegement { //找到当前选中页面对应的顶部按钮 for (UIButton *btn in btnArray) { if (btn.tag == nPageIndex) { currentBtn = btn; } } //如果选中页面对应按钮超出可视范围,顶部滚动视图滚动 int x = currentBtn.frame.origin.x; if (currentBtn.frame.origin.x + SEGEMENT_BTN_WIDTH > self.frame.size.width + self.segementScrollView.contentOffset.x) { [self.segementScrollView setContentOffset:CGPointMake(self.segementScrollView.contentOffset.x + SEGEMENT_BTN_WIDTH, 0) animated:YES]; } else if (currentBtn.frame.origin.x < self.segementScrollView.contentOffset.x) { [self.segementScrollView setContentOffset:CGPointMake(currentBtn.frame.origin.x, 0) animated:YES]; } //下方选中标记线条滚动效果 [UIView animateWithDuration:0.2 animations:^{ _selectedLine.frame = CGRectMake(currentBtn.frame.origin.x, self.frame.size.height - 2, SEGEMENT_BTN_WIDTH, 2); }completion:^(BOOL finished) { }]; } - (void)btnClick:(UIButton*)btn { currentBtn = btn; if (nPageIndex != btn.tag) { nPageIndex = btn.tag; [self refreshSegement]; self.block(nPageIndex); } } @end
使用方法:
- (void)viewDidLoad { [super viewDidLoad]; NSMutableArray *array=[NSMutableArray array];//显示的标签页 for (int i = 0; i < 12; i++) { MyViewController1 *viewController1 = [[MyViewController1 alloc] initWithIndex:i + 1];//initWithIndex : 自定义的构造方法,用于显示页面编号 [array addObject:viewController1];//滚动视图列表 } myScrollView = [[MyScrollView alloc] initWithFrame:self.view.frame titleArray:@[@"第1页",@"第2页",@"第3页",@"第4页",@"第5页",@"第6页",@"第7页",@"第8页",@"第9页",@"第10页",@"第11页",@"第12页"] viewArray:array]; [self.view addSubview:myScrollView]; // Do any additional setup after loading the view, typically from a nib. }
源码下载链接:http://download.csdn.net/detail/lzm2625347497/9562677
以上是关于IOS UIScrollView + UIButton 实现页面和顶部标签页水平滚动效果的主要内容,如果未能解决你的问题,请参考以下文章
ios: uiscrollview 和 uiview 自动布局