iOS 控件定制iOS DeveloperiOS学习笔记

iOS篇-UI篇-仿今日头条效果父子控制器的应用

2017-06-22  本文已影响626人  TianTianBaby223


代码demo 链接在评论里,喜欢的朋友点个赞.

效果展示:

TZ头条效果

一 科普一分钟:

1.控制器不能被销毁两种 情况 a: 全局 也就是说用strong 指针指向  b:添加成子控制器

比如:我们在 A控制器 的View 添加 B控制器的View  B 中 添加 touchesBegan点击方法  现在我们用一若指针 weak  指向 B 或者几个局部变量B创建所得的View  结果就是 可以看到 B的View 在A .View 中显示 但是点击B 时没有反应 .因为B对象已经被销毁.

2.ARC 管理原则:只要一个对象没有被强引用,就会被销毁.

3.父子控制器运行原理:只要A控制器的View 成为B 控制器View的子视图 那么A控制器 就要成为B控制器的子控制器.

二 代码实现和思路分析:

实现GIF 效果 首先 我们要 建立两个部分,也就是上半部分展示标题的ScrollView 和下半部分展示内容的 ScrollView.

@property(nonatomic,weak)UIScrollView*titleScrollView;

@property(nonatomic,weak)UIScrollView*contentScrollView;

static int const labelWith =100;

添加子控制器 

//添加所有子控制器

-(void)setAllChildController{

//推荐

oneViewController*oneVC = [[oneViewControlleralloc]init];

oneVC.title=@"推荐";

[self addChildViewController:oneVC];

//热点

twoViewController*twoVC = [[twoViewControlleralloc]init];

twoVC.title=@"热点";

[self addChildViewController:twoVC];

//沈阳

threeViewController*threeVC = [[threeViewControlleralloc]init];

threeVC.title=@"沈阳";

[self addChildViewController:threeVC];

//视频

fourViewController*fourVC = [[four ViewControlleralloc]init];

fourVC.title=@"视频";

[self addChildViewController:fourVC];

//社会

fiveViewController*fiveVC = [[fiveViewControlleralloc]init];

fiveVC.title=@"社会";

[self addChildViewController:fiveVC];

//图片

sixViewController*sixVC = [[sixViewControlleralloc]init];

sixVC.title=@"图片";

[self addChildViewController:sixVC];

}

初始化标题ScrollView

-(void)setupScrollView{

NSInteger count =self.childViewControllers.count;

//设置标题滚动条

self.titleScrollView.contentSize=CGSizeMake(count *100,0);

self.titleScrollView.showsHorizontalScrollIndicator=NO;

//设置内容滚动条

self.contentScrollView.contentSize=CGSizeMake(WIDTH*count,0);

//开启分页

self.contentScrollView.pagingEnabled=YES;

//没有弹簧效果

self.contentScrollView.bounces=NO;

//隐藏水平滚动条

self.contentScrollView.showsHorizontalScrollIndicator=NO;

//设置协议

self.contentScrollView.delegate=self;

}

添加所有子控制器对应标题以及标题设置

-(void)setupTitleLabel{

NSInteger count =self.childViewControllers.count;

CGFloat x  =0;

CGFloaty =0;

CGFloat height =44;

for(int i =0; i < count; i++) {

//取出控制器

UIViewController*vc =self.childViewControllers[i];

//创建label

UILabel*label = [[UILabel alloc]init];

//添加label到titleArray数组

[self.titleArray addObject : label];

label.font= [UIFont systemFontOfSize:16];

label.textAlignment=NSTextAlignmentCenter;

x = i*labelWith;

label.tag= i;

//设置尺寸

label.frame=CGRectMake(x, y,labelWith, height);

//设置Label文字

label.text= vc.title;

//添加手势

UITapGestureRecognizer*tap = [[UITapGestureRecognizer alloc] initWithTarget : self action:@selector(titleClick:)];

label.userInteractionEnabled=YES;

[label addGestureRecognizer : tap];

//设置高亮文字颜色

label.highlightedTextColor= [UIColor redColor];

//默认选中第0个label

if(i ==0) {

[self titleClick : tap];

}

//添加label

[self.titleScrollView addSubview : label];

}

}

UI 部分我们搭建完成了,接下来我们来处理 点击标题的业务逻辑 ,我们先分析一下 点击标题label 应该做哪些事情

1.让标题选中,文字为空色

2.滚动到对应的位置

3.对应的位置添加子控制器View

4.让选中标题居中

-(void)titleClick:(UITapGestureRecognizer*)tap{

//0取出label

UILabel*label = (UILabel*)tap.view;

//1.标题颜色高亮

[self selectLabel : label];

//2.滚动相应位置

NSInteger index = label.tag;

//2.1计算滚动位置

CGFloat offsetX = label.tag*WIDTH;

[self.contentScrollView setContentOffset:CGPointMake(offsetX,0)animated:YES];

//3.对应位置添加控制器View

[self showVC : index];

//4.让选中标题居中

[self setUpTitleCenter : label];

}

接下来各个击破里面的方法

首先是 选择 三部曲 创建 临时变量

a:@property(nonatomic,weak)UILabel*seletLabel;

b:做事情

c:参数 label 赋值给 临时变量

-(void)selectLabel:(UILabel*)label{

_seletLabel.highlighted = NO;

//取消形变

_seletLabel.transform=CGAffineTransformIdentity;

_seletLabel.textColor= [UIColor blackColor];

label.highlighted=YES;

//形变

label.transform=CGAffineTransformMakeScale(1.3,1.3);

_seletLabel = label;

}

对应位置添加控制器View 注意的是 优化考虑 加判断 是否被加载过,加载过的视图一律return

-(void)showVC:(NSInteger)index{

CGFloat offsetX = index *WIDTH;

UIViewController*vc =self.childViewControllers[index];

//判断当前控制器的View有没有加载过如果已经加载过就不需要加载

if(vc.isViewLoaded)return;

vc.view.frame=CGRectMake(offsetX,0,WIDTH,self.contentScrollView.frame.size.height);

[self.contentScrollView addSubview: vc.view];

}

让选中标题居中 思路分析

a:滚动的范围就是  标题的中心点 减去 屏幕中心点的距离 就是 移动后的偏移量

b:假如 得出的结果小于0 我们可以分析出 label的其实点在屏幕中心点的左边 也就是 说可以不做事情

c:当滚动到最大的滚动范围之后 在滚动 我们要把滚动范围就设置为最大滚动范围

-(void)setUpTitleCenter:(UILabel*)centerLabel{

//计算偏移量

CGFloat offsetX = centerLabel.center.x-WIDTH*0.5;

if(offsetX <0) {

offsetX =0;

}

//最大滚动范围

CGFloat maxOffsetX =self.titleScrollView.contentSize.width-WIDTH;

if(offsetX > maxOffsetX) {

offsetX = maxOffsetX;

}

//滚动标题滚动条

[self.titleScrollView setContentOffset:CGPointMake(offsetX,0)animated:YES];

}

分析到这里 上半部分的scroll 业务逻辑已经处理完了 ,接下来我们分析 内容的scroll该如何做处理

首先我们写代理方法:滑动结束时,从今日头条 可以分析出,都是滑动停止的时候页面才开始做事情,所以我们要用scrollViewDidEndDecelerating 这个代理方法

思路分析

a:首先和点击标题一样 添加 子控制器View

b:把对应标题选中

c:标题居中

具体方法和上述一样

-(void)scrollViewDidEndDecelerating:(UIScrollView*)scrollView{

//计算滚动到哪一页

NSInteger index = scrollView.contentOffset.x/scrollView.bounds.size.width;

//1.添加子控制器View

[self showVC :index];

//2.把对应标题选中

UILabel*label =self.titleArray[index];

[self selectLabel : label];

//3让选中标题居中

[self setUpTitleCenter :label];

}

最后计算缩放比例 和 字体的渐变

思路分析 :可以看的出来 字体的变化 和颜色的变化 是渐渐产生的,我们会迅速想到的就是scrollView的代理方法 ,而且 无论做任何事 内容scrollView 都是做事情的 所以接下来我们就要在scrollViewDidScroll 这个代理方法里处理

//滚动就会调用

算法分析

a:要想对label 文章首先 我们必须拿到操作的label 通过scrollview的偏移量 / WIDTH 取整数 我们可以知道当前处理的 label  也就是左边的Label 右边label 就是下角标+1

b:字体变化  可以分析出来 右边的label 相对于 左边的 label 的大小 在0-1 之间 增加或者减小

所以  CGFloat currpage = scrollView.contentOffset.x/WIDTH; 得到的currpage 再减去 它的取整 int currpage 就算了 右边 label 对于 左边label 的相对变化  scale 而左边label 相对于右边label的相对变化 就是相反的 1-scale.

-(void)scrollViewDidScroll:(UIScrollView*)scrollView{

CGFloat currpage = scrollView.contentOffset.x/WIDTH;

//左边角标

NSInteger leftIndex = currpage;

//右边角标

NSInteger rightIndex = leftIndex +1;

//获取左边label

UILabel*leftLabel =self.titleArray[leftIndex];

//获取右边label

UILabel*rightLabel;

if(rightIndex <=self.titleArray.count-1) {

rightLabel =self.titleArray[rightIndex];

}

//计算右边缩放比例右边自己相对于左边字体变大比例

CGFloat rightscal = currpage - leftIndex;

//计算左边缩放比例

CGFloat leftscal =1- rightscal;

//缩放比例1~1.3

//左边缩放比例

leftLabel.transform=CGAffineTransformMakeScale(leftscal*0.3+1,leftscal*0.3+1);

//右边缩放比例

rightLabel.transform=CGAffineTransformMakeScale(rightscal*0.3+1,rightscal*0.3+1);

//设置文字颜色渐变

/**RGB渐变*/

leftLabel.textColor= [UIColor colorWithRed :leftscalgreen :0blue:0alpha:1];

rightLabel.textColor= [UIColor colorWithRed :rightscalgreen :0blue:0alpha:1];

}

到这里就是实现了 所有核心 功能 . 相信你可以做的出来一样的效果了.

3总结:

看到页面效果 慢慢分析,从大结构入手 , 每个部分 做了哪些事情 ,能公用的方法要抽取出来.那样方便我们思路分析.下期再见.  ^ _ ^ 不要忘记给个赞

上一篇 下一篇

猜你喜欢

热点阅读