WJ新闻客户端 (基本框架的搭建)
核心技术原理:利用UIScrollView来实现多视图的滑动切换,滑动距离的计算。
1.UIScrollView要使用到的属性介绍
UIScrollView* containView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 30, self.view.width, self.view.height)];
containView.delegate = self;
containView.showsHorizontalScrollIndicator = NO;
containView.pagingEnabled = YES;
containView.bounces = NO;
pagingEnabled: 打开翻页效果(确保scrollview 滑动显示的时候 都显示的是一整块的页面,也就是说scroview中不会同时静止存在两个视图)
bounces:关闭弹簧效果(所谓的弹簧效果也就是说当滑倒uiscrollview 边缘的时候 ,scrollview 可以继续滑动一段距离然后弹回来)
2.先添加5个视图控制器,然后根据要加载多少个视图控制器来计算scrollview 的Contentsize 首先利用 viewCtrls 可变数组来包装我们传入的视图控制器,并且计算出视图控制器的View 所在的位置和大小.然后根据传入的视图控制器的title,并且根据这个title来设置我们后的导航栏上面的按钮的文字属性。如果视图控制器的的titile 为空的话。就显示我们的默认文字。
[mainView addSegementContrl:aView];
[mainView addSegementContrl:bView];
[mainView addSegementContrl:dView];
[mainView addSegementContrl:cView];
[mainView addSegementContrl:addView];
<span style="color:#333333;"> [self.containView setContentSize:CGSizeMake(self.viewCtrls.count*viewWidth,0)];
UIViewController* addViewController = [self.viewCtrls lastObject];
NSInteger currentIndex = self.viewCtrls.count -1 ;
CGFloat viewX = currentIndex*viewWidth;
CGFloat viewY = 0;
CGFloat viewW = viewWidth;
CGFloat viewH = viewHeigh;
[addViewController.view setFrame:CGRectMake(viewX, viewY, viewW,viewH)];
[self.containView addSubview:addViewController.view];
if (addViewController.title == nil) {
addViewController.title = [NSString stringWithFormat:@"item%d",(int)self.viewCtrls.count];
}
[self addBtn:addViewController];</span>
3 设置按钮的位子与按钮的状态以及样式。大概思路先用一个按钮数组来包装我们的按钮。然后使用函数updateBtns来动态设置我们BUTTON的大小以及位置。(为什么不用subviews 来实现相同的效果呢 考虑到最后滑块也在我们的导航栏视图上面,所以为了简化逻辑就没有使用)
-(void) addBtn:(UIViewController*) ctrl
{
UIButton* btn = [[UIButton alloc] init];
[btn setBackgroundColor:[UIColor redColor]];
[btn addTarget:self action:@selector(clcikeBtn:) forControlEvents:UIControlEventTouchUpInside];
[btn setTitle:ctrl.title forState:UIControlStateNormal];
[btn setBackgroundColor: [UIColor whiteColor]];
btn.titleLabel.font = [UIFont systemFontOfSize:15.0F];
[btn setTitleColor:[UIColor redColor] forState:UIControlStateSelected];
[btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[self.segementView addSubview:btn];
[self.btnArray addObject:btn];
[self updateBtns];
}
-(void) updateBtns
{
NSInteger btnCount = self.btnArray.count;
CGFloat btnW = self.view.width / btnCount;
CGFloat btnH = 30;
CGFloat btnX ;
CGFloat btnY = 0;
for (int i = 0; i < self.btnArray.count; i++) {
UIButton* btn = self.btnArray[i];
btnX = i * btnW;
btn.tag = i;
if (btn.tag == 0) {
[self clcikeBtn:btn];
self.slider.width = btnW;
[self.segementView addSubview:self.slider];
}
[btn setFrame:CGRectMake(btnX, btnY, btnW, btnH)];
}
}
4 设置滑块的样式以及添加滑块,使用简单工厂方法,根据传入的类型来创建出不同的滑块模型。
if (self = [super init])
{
self.backgroundColor = [UIColor grayColor];
switch (type) {
case sliderDefault:
{
self.layer.cornerRadius = 10;
self.layer.masksToBounds = YES;
self.alpha = 0.7;
[self setFrame:CGRectMake(0, 3, 100, 24)];
}
break;
case sliderRect:
{
self.alpha = 0.7;
[self setFrame:CGRectMake(0, 3, 100, 24)];
}
break;
}
}
return self;
5 让滑块根据我们的滑动来进行移动,主要思路利用uiscrollview滑动协议来计算我们滑块要移动的距离。(注意 这里需要进行滑动方向的判定。进而选择是向上取整还是向下取整。),这里我们也要进行Btn滑动视图的时候的切换。
-(void) scrollViewDidScroll:(UIScrollView *)scrollView
{
NSInteger i;
CGFloat distancen = scrollView.contentOffset.x / self.view.width;
CGFloat sliderDistance = scrollView.contentOffset.x/self.btnArray.count;
if(scrollView.contentOffset.x > beforeX)
{
[self sliderMove:sliderDistance];
i =floor(distancen + 0.5);
}
else
{
[self sliderMove:sliderDistance];
i =ceil(distancen - 0.5);
}
beforeX = scrollView.contentOffset.x;
UIButton* btn = self.btnArray[i];
[self changeBtn:btn];
}
6 设置导航栏按钮的切换以及动画效果
-(void) changeBtn:(UIButton*) btn
{
[UIView animateWithDuration:2 animations:^{
tempBtn.titleLabel.font = [UIFont systemFontOfSize:15.0F];
tempBtn.selected = NO;
btn.selected = YES;
tempBtn = btn;
btn.titleLabel.font = [UIFont systemFontOfSize:24.0F];
}];
}
最后贴上项目github 地址 (持续更新中) https://github.com/fucklichking/WJSegementContrl