最近一些项目中经常用到一个首页,就是利用父子控制器搭建一个可以左右滑动显示的主页.这个页面从我接触的第一个项目到现在,已经遇到了好几次,每次都会根据不同的需求进行改动,呈现不一样的主页.但大体框架是不变的.所以干脆把首页抽出来做一个demo,以后有用到直接拖进去就好.

总体思路
- 创建父控制器
- 给父控制器添加若干子控制器
- 添加一个左右滚动的根视图View
- 设置标题栏
- 启动程序时直接选中第一个控制器
一、添加子控制器
这里只添加了三个,可以继续无限添加.
-(void)setupChildVCs
{
//创建三个个页面
XHHChild1ViewController *VC1 = [[XHHChild1ViewController alloc]init];
XHHChild2ViewController *VC2 = [[XHHChild2ViewController alloc]init];
XHHChild3ViewController *VC3 = [[XHHChild3ViewController alloc]init];
//给自己添加三个子控制器
[self addChildViewController:VC1];
[self addChildViewController:VC2];
[self addChildViewController:VC3];
}
二、设置scrollVIew
此招式根据自己需要,具体设置scrollVIew的各项参数
-(void)setupScrollView
{
//几个子控制器,就计算几个contentSize的宽度(缺点是:代码设置滚动必须在设置子控制器方法之后)
NSUInteger numVC = self.childViewControllers.count;
UIScrollView *scrollView = [[UIScrollView alloc]initWithFrame:self.view.bounds];
scrollView.backgroundColor = XHHRandomColor;
//不允许设置自动适应内边距
self.automaticallyAdjustsScrollViewInsets = NO;
scrollView.bounces = NO;
scrollView.showsHorizontalScrollIndicator = NO;
scrollView.showsVerticalScrollIndicator = NO;
scrollView.pagingEnabled = YES;
scrollView.backgroundColor = XHHWhite;
scrollView.contentSize = CGSizeMake(XHHScreenW * numVC, 0);
scrollView.delegate = self;
[self.view addSubview:scrollView];
self.scrollView = scrollView;
}
三、 设置顶部菜单栏和标题下面的指示标志
这个顶部菜单栏写起来比较繁琐,但一步一步写下去整个逻辑并不难.
#pragma mark --
#pragma mark - 设置顶部View
-(void)setupTopView
{
//设置n个button到一个View上,再设置成为nav的titleView
UIView *titleView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, XHHScreenW, TopViewH)];
titleView.backgroundColor = XHHCharles;
CGFloat buttonW = self.view.xhh_width/self.childViewControllers.count;
CGFloat buttonH = TopViewH;
//循环添加button
for (int i = 0; i < self.titles.count ; i++ ) {
CGFloat buttonX = i *buttonW;
CGFloat buttonY = 0;
//button的相关设置
UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(buttonX, buttonY,buttonW, buttonH)] ;
button.tag = i;
//选中的title加粗
NSAttributedString *attrNormaltitle = [[NSAttributedString alloc]initWithString:self.titles[i] attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:15],NSForegroundColorAttributeName:XHHBlack}];
NSAttributedString *attrSelectedtitle = [[NSAttributedString alloc]initWithString:self.titles[i] attributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:15],NSForegroundColorAttributeName:XHHBlack}];
[button setAttributedTitle:attrSelectedtitle forState:UIControlStateSelected];
[button setAttributedTitle:attrNormaltitle forState:UIControlStateNormal];
button.titleLabel.textAlignment = NSTextAlignmentCenter;
button.userInteractionEnabled = YES;
[button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
[titleView addSubview:button];
[self.btnArray addObject:button];
//在添加好以后就直接选中button
}
[self.view addSubview:titleView];
self.topView = titleView;
//底部的指示器
UIView *indicatorView = [[UIView alloc]init];
indicatorView.backgroundColor = XHHCharles3;
indicatorView.xhh_height = 2;
indicatorView.xhh_y = titleView.xhh_height - 2;
[titleView addSubview:indicatorView];
self.indicatorView = indicatorView;
UIButton *firstButton = self.btnArray[0];
#pragma mark - 这个sizeToFit必须要写 就是立即计算titleLabel的宽度 不写就没有宽度
[firstButton.titleLabel sizeToFit];
//NSLog(@"%f",firstButton.titleLabel.xhh_width);
indicatorView.xhh_width = firstButton.titleLabel.xhh_width;
indicatorView.xhh_centerX = firstButton.xhh_centerX;
[indicatorView layoutIfNeeded];
}
四、scrollView的代理
这里面有几处可以自定义的地方
a. 指示标志跟随滚动,还是停止拖拽后指示标志才动?
b. 滚动后添加view还是 开始滚动就展示出view?
c. 标题按钮直接显示还是滚动显示?
这些方面都可已根据自己的喜好在代理方法中去定制.
我采用的是跟随滚动
,滚动后显示View
,点击按钮显示滚动动画
.
#pragma mark --
#pragma mark - ScrollView代理
//根据滚动偏移量动态的添加view,这样不会导致打开程序的长时间加载
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
//计算停止滚动后的控制器是哪个
NSInteger index = scrollView.contentOffset.x / self.view.xhh_width;
//用数组记录button,根据index点击
[self buttonClick:self.btnArray[index]];
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
//指示View跟随滚动变更中点 = scroll偏移 * 二者比例 +中点的起始距离.
self.indicatorView.xhh_centerX = scrollView.contentOffset.x * ((XHHScreenW / self.titles.count) / XHHScreenW) + (XHHScreenW / self.titles.count)/2 ;
}
五、两个重要的触发方法
1.button(topView上面的button)点击
-(void)buttonClick:(UIButton *)button
{
NSInteger index = button.tag;
//记录的button取消选中状态
self.selectedBtn.selected = NO;
//当前选中
button.selected = YES;
//选中之后动态跳转到另一个view中去(添加子控制器View)
[UIView animateWithDuration:0.4 animations:^{
self.scrollView.contentOffset = CGPointMake(index * self.view.xhh_width, 0);
}];
//滚动完了之后再添加子控制器,因为添加子控制器的时候用到了scrollView的bounds
[self addChildViews:index];
//继续记录
self.selectedBtn = button;
}
2.其中的添加控制器方法
记得加载过的就不用再次加载了.万一页面比较复杂,可以节省内存.
-(void)addChildViews:(NSUInteger) index
{
UIViewController *ChildVC = self.childViewControllers[index];
if (ChildVC.viewLoaded) {
return;
}
ChildVC.view.frame = self.scrollView.bounds;
[self.scrollView addSubview:ChildVC.view];
}
网友评论