代碼demo 鏈接在評論里,喜歡的朋友點個贊.
效果展示:
一 科普一分鐘:
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總結:
看到頁面效果 慢慢分析,從大結構入手 , 每個部分 做了哪些事情 ,能公用的方法要抽取出來.那樣方便我們思路分析.下期再見.? ^ _ ^ 不要忘記給個贊