解決添加到ScrollView上的UITableView控件自動向下偏移64像素的問題
-
首先理解1:即使UITableView沒有添加到ScrollView上寥袭,UIableView也會向下偏移20像素
- 原因: 這是歷史遺留問題忠聚。就是說只要代碼中出現(xiàn)了UIableView,那么他被創(chuàng)建出來時滴须,默認坐標為(0,20)
-
首先理解2:添加到ScrollView上的UITableView控件在20的基礎(chǔ)之上,還會再向下偏移64像素
- 原因: 自動向下偏移64是由于系統(tǒng)的automaticallyAdjustsScrollViewInsets屬性默認開啟造成的。開啟之后,就會自動調(diào)整布局氓拼。所以會自動向下偏移xx像素。有時候不一定為64像素抵碟。但是都是這個屬性導致的桃漾。所以我們?nèi)绻胱约盒薷牟季郑仨殞傩栽O(shè)置為NO拟逮。
首先理解3:偏移的這些像素對于UITableView來說都是內(nèi)邊距(ContentInset)撬统,即都是UITableView的ContentSize的內(nèi)邊距。因為UITableView的ContentSize的計算不包括內(nèi)邊距敦迄,所以這些像素不是ContentSize的內(nèi)容
-
添加到ScrollView上的UITableView控件
如果ScrollView上沒有導航欄恋追,就向下偏移20像素+xxx像素。xxx像素不確定多少罚屋,具體根據(jù)你添加了什么控件決定苦囱。確定的是有導航欄的情況下
如果ScrollView上有導航欄,那么ScrollView上的控件在默認偏移20像素的基礎(chǔ)上脾猛,再向下移動64像素撕彤。即20像素+64像素。這個64像素是確定的猛拴。
不讓控件向下移動64像素的做法如代碼1:(只是解決了偏移64像素的問題,運行時,UITableView仍然會向下偏移20像素)
//不要控制器去自動調(diào)整scrollView的內(nèi)邊距
self.automaticallyAdjustsScrollViewInsets = NO;
官方解釋:automaticallyAdjustsScrollViewInsets根據(jù)按所在界面的status bar喉刘,navigationbar,與tabbar的高度漆弄,自動調(diào)整scrollview的 inset睦裳。
我們不讓UIViewController調(diào)整整scrollview的inset撼唾,設(shè)置為no,然后我們再自己修改布局即可-
由于狀態(tài)欄的存在蛛蒙,控件仍然會向下移動20像素,不讓控件向下移動20像素的做法代碼2:
//把子控件的y值設(shè)置為0牵祟,UITableView顯示時y坐標距屏幕頂部為0深夯,解決了UITableView向下偏移20像素的問題 for (NSInteger i = 0; i < 5; i++) { UIViewController *childVcView = self.childViewControllers[i];//取控制器 childVcView.view.frame = CGRectMake(i * scrollView.zb_width,0, scrollView.zb_width, scrollView.zb_height);//設(shè)置控制器的view的frame [scrollView addSubview:childVcView.view];//將控制器的view添加到scrollView上面
總結(jié):僅僅利用代碼2將y坐標設(shè)置為0是不能夠?qū)ableView顯示在屏幕頂部的咕晋。只有代碼1+代碼2結(jié)合起來才能將TableView顯示在頂部掌呜。因為你不將代碼1自動調(diào)整設(shè)置為NO,系統(tǒng)仍然會根據(jù)當前界面上的控件來自動調(diào)整內(nèi)邊距,調(diào)整為64,即TableView向下移動64像素汰蓉。【已驗證】-->代碼1+代碼2在開發(fā)中成對出現(xiàn),缺一不可测秸。
ScrollView的frame和的contentSize的區(qū)別
- ScrollView的frame的作用:
- 控制可見范圍,超出可見范圍看不見
- ScrollView的contentSize的作用:
- 限制滾動的范圍(contentSize就是他們說的內(nèi)容或者尺寸或者內(nèi)容尺寸)
情況不同決定了UITableView是否需要設(shè)置寬高
- 不是利用alloc init方式創(chuàng)建出來的UITableView,而從控制器的數(shù)組中取出來的UITableView本身就有寬高缠俺,不需要手動設(shè)置寬高。(注意:取出來的是UITableView唯笙,因為代碼中有.view)
UIView *childVcView = self.childViewControllers[i].view;
childVcView.zb_X = i * scrollView.zb_width;
[scrollView addSubview:childVcView];
- 利用alloc init方式創(chuàng)建出來的UITableView必須自己手動設(shè)置寬高
UITableView *tableView = [[UITableView alloc] init];
tableView.zb_height = scrollView.zb_height;
tableView.zb_width = scrollView.zb_width;
思想:一個TableView對應(yīng)一個控制器(本質(zhì)是類)。一個TableView有自己專門的數(shù)據(jù)源抄瑟。
- 5個TableView對應(yīng)一個類
- 因為TableView要顯示數(shù)據(jù)鞋拟,必須得執(zhí)行數(shù)據(jù)源方法才能顯示數(shù)據(jù)到UITableView上。
- 如果5個TableView對應(yīng)1個類(即5個TableView都是在同一個類中創(chuàng)建的),那么5個TableView的數(shù)據(jù)源都是這一個類
- 那么這個類執(zhí)行數(shù)據(jù)源方法的時候,如果在numberOfRowsInSection中不通過tableView.tag進行判斷是哪個TableView的話澄成,那么默認5個TableView中的行數(shù)都一樣。
- 如果在numberOfRowsInSection中已經(jīng)通過tag判斷出是哪個TableView的前提下,又執(zhí)行了cellForRowAtIndexPath通今,這個時候如果不再次進行判斷的話,那么5個TableView的cell的內(nèi)容肯定都一樣掺喻。
- 正常情況下,每個TableView都有自己的特點,顯示怎么樣的cell對于每個TableView來說,肯定都是不一樣的裂允。如果都一樣貌踏,做社交類app逗堵,電商類app,當進行切換標題欄的時候,每個TableView的內(nèi)容都一樣掂骏,這還看什么勁啊级解。
- 通過tag進行很多的if else來判斷是哪個TableView的做法非常繁瑣掩驱,且代碼界面混亂民逼,所有的代碼都寫在一個類中,這個類會類似的。
- 1個TableView對應(yīng)1個類
- 每個TableView都有自己專門的數(shù)據(jù)源,這樣各個TableView顯示的cell就會互不影響早处。也避免了上述利用tag來進行判斷是哪個TableView的問題默责。
- 優(yōu)點:每個模塊的功能和邏輯讓對應(yīng)的類去管理,后續(xù)開發(fā)的擴展性強
5個TableView對應(yīng)一個類(用于襯托1個TableView對應(yīng)1個類)
#import "ViewController.h"
#import "UIView+Frame.h"
#define ZBColor(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1]
#define ZBRandomColor ZBColor(arc4random_uniform(255), arc4random_uniform(255), arc4random_uniform(255))
@interface ViewController ()<UITableViewDataSource>
//@property (nonatomic,weak)UIScrollView *scrollView;
@property(nonatomic,strong)UITableViewCell *cell;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//將scrollView添加到控制器的view上
UIScrollView *scrollView = [[UIScrollView alloc] init];
scrollView.frame = self.view.bounds;
scrollView.backgroundColor = [UIColor redColor];
[self.view addSubview:scrollView];
//將5個TableView添加到scrollView上坟比。scrollView的contentSize為5個TableView的寬度
for (NSInteger i =0; i < 5 ; i++) {
UITableView *tableView = [[UITableView alloc] init];
tableView.backgroundColor = ZBRandomColor;
tableView.zb_height = scrollView.zb_height;
tableView.zb_width = scrollView.zb_width;
tableView.zb_X = i *tableView.zb_width;
//5個tableView的數(shù)據(jù)源都是1個控制器柠衅,所以5個TableView上都顯示一樣的數(shù)據(jù)
tableView.dataSource =self;
tableView.tag=i;
[scrollView addSubview: tableView];
}
scrollView.contentSize = CGSizeMake(5 *self.view.bounds.size.width, 0);
scrollView.pagingEnabled =YES;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if (tableView.tag == 0) return 5;
if (tableView.tag == 1) return 10;
if (tableView.tag == 2) return 15;
if (tableView.tag == 3) return 20;
else
return 25;
}
static NSString * const ID = @"ce";
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
if(tableView.tag == 0){
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
cell.backgroundColor = [UIColor clearColor];
}
cell.textLabel.text = [NSString stringWithFormat:@"第%ld個tableView-第%zd個cell",tableView.tag,indexPath.row];
return cell;
}else if(tableView.tag == 1){
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
cell.backgroundColor = [UIColor clearColor];
}
cell.textLabel.text = [NSString stringWithFormat:@"第%ld個tableView-第%zd個cell",tableView.tag,indexPath.row];
return cell;
}else if(tableView.tag == 2){
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
cell.backgroundColor = [UIColor clearColor];
}
cell.textLabel.text = [NSString stringWithFormat:@"第%ld個tableView-第%zd個cell",tableView.tag,indexPath.row];
return cell;
}else if(tableView.tag == 3){
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
cell.backgroundColor = [UIColor clearColor];
}
cell.textLabel.text = [NSString stringWithFormat:@"第%ld個tableView-第%zd個cell",tableView.tag,indexPath.row];
return cell;
}else{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
cell.backgroundColor = [UIColor clearColor];
}
cell.textLabel.text = [NSString stringWithFormat:@"第%ld個tableView-第%zd個cell",tableView.tag,indexPath.row];
return cell;
}
}
@end
- 效果圖:
1個TableView對應(yīng)1個類
ViewController.h文件
#import "ViewController.h"
#import "UIView+Frame.h"
#import "ZBAllViewController.h"
#import "ZBPictureViewController.h"
#import "ZBVideoViewController.h"
#import "ZBVoiceViewController.h"
#import "ZBWordViewController.h"
#define ZBColor(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1]
#define ZBRandomColor ZBColor(arc4random_uniform(255), arc4random_uniform(255), arc4random_uniform(255))
@interface ViewController ()<UITableViewDataSource>
//@property (nonatomic,weak)UIScrollView *scrollView;
@property(nonatomic,strong)UITableViewCell *cell;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 初始化子控制器
[self setupChildVcs];
// scrollView
[self setupScrollView];
}
/**
* 初始化子控制器
*/
- (void)setupChildVcs
{
[self addChildViewController:[[ZBAllViewController alloc] init]];
[self addChildViewController:[[ZBVideoViewController alloc] init]];
[self addChildViewController:[[ZBVoiceViewController alloc] init]];
[self addChildViewController:[[ZBPictureViewController alloc] init]];
[self addChildViewController:[[ZBWordViewController alloc] init]];
}
/**
* scrollView
*/
- (void)setupScrollView
{
UIScrollView *scrollView = [[UIScrollView alloc] init];
scrollView.frame = self.view.bounds;
[self.view addSubview:scrollView];
// 添加5個模塊
for (NSInteger i = 0; i < 5; i++) {
/*
3個方法的總結(jié):前提:控件添加到UIScrollView上。
方法1沒有設(shè)置y坐標,所以UITableView顯示時會向下偏移20像素
方法2和方法3設(shè)置了y坐標勋颖,并且設(shè)置為0叁执,使UITableView顯示時y距屏幕頂部為0次哈,所以UITableView顯示時會向下偏移20像素
*/
//方法1:僅僅是設(shè)置childVcView的x坐標恢筝,childVcView的y坐標沒有設(shè)置此改。這樣會導致程序運行時暂题,childVcView也就是UITableView不是填充整個屏幕挂滓,而是向下偏移20像素的距離(狀態(tài)欄的原因)
UIView *childVcView = self.childViewControllers[i].view;
childVcView.zb_X = i * scrollView.zb_width;
[scrollView addSubview:childVcView];
/* 方法2:
//注意:childVcView指針存著的是控制器的view,而不是控制器想括,因為等號右側(cè)有.view渣窜,所以childVcView這時候代表的是一個view位迂。.所以后面兩行代碼childVcView都不用加上.view坝橡。
UIView *childVcView = self.childViewControllers[i].view;//取控制器的view
childVcView.frame = CGRectMake(i * scrollView.zb_width, 0, scrollView.zb_width, scrollView.zb_height);//設(shè)置視圖的frame。
[scrollView addSubview:childVcView];
*/
/* 方法3:
//childViewControllers中的子控制器真實是UITableViewController蹲堂,因為UITableViewController繼承UIViewController播聪,所以childVcView的類型也可以寫成UIViewController
//childVcView指針存著的是控制器,因為沒有等號右側(cè)沒有.view衅檀。所以childVcView這時候代表的是一個控制器沉眶,后兩行代碼childVcView后面必須加上.view。因為我們最終是要把view添加到scrollView上的。
UIViewController *childVcView = self.childViewControllers[i];//取控制器
childVcView.view.frame = CGRectMake(i * scrollView.zb_width, 20, scrollView.zb_width, scrollView.zb_height);//設(shè)置控制器的view的frame
[scrollView addSubview:childVcView.view];//將控制器的view添加到scrollView上面
*/
}
// 其他設(shè)置
scrollView.contentSize = CGSizeMake(5 * scrollView.zb_width, 0);
scrollView.pagingEnabled = YES;
}
@end
ZBPictureViewController文件,
- 其余控制器的代碼和以下代碼一樣,就不一一列出了
import "ZBPictureViewController.h"
#define ZBColor(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1]
#define ZBRandomColor ZBColor(arc4random_uniform(255), arc4random_uniform(255), arc4random_uniform(255))
#import "ZBConst.h"
@interface ZBPictureViewController ()
@end
@implementation ZBPictureViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.backgroundColor = ZBRandomColor;
}
#pragma mark - UITableViewDataSource
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 30;
}
static NSString *ID = @"ce";
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
cell.backgroundColor = [UIColor clearColor];
}
cell.textLabel.text = [NSString stringWithFormat:@"%@ - %zd",self.class,indexPath.row];
return cell;
}
@end
- 效果圖
addChildViewController和addSubview區(qū)分
- 除了下面的解釋洲胖,還有一個做法來解決讓正確的對象添加到正確的對象身上。
- addChildViewController是指:后面的參數(shù)是一個子控制器,要添加到前面的對象中
- addSubview是指:后面的參數(shù)是一個子View库车,要添加到前面的對象中
- 拓展:給某個對象添加顏色backgroundColor晶乔,一定要在view上添加
精華例子1:
//控制器才能添加到控制器中。因為self代表了控制器川无,如果某個對象要添加到控制器中疹味,那么這個對象必須是控制器】茬裕【蘋果公司規(guī)定】
ZBAllViewController *vc1 = [[ZBAllViewController alloc] init];
[self addChildViewController:vc1];
//View才能添加到View中铅檩。因為self.scrollView本身就是個View兔沃,它不是控制器,所以如果某個對象要添加到self.scrollView這個view中時额衙,這個而對象必須是View械哟,因為childVC是控制器的對象,所以必須把childVC再進行細化,拿到childVc的view拯爽。即使childVc.view
UIViewController *childVc = self.childViewControllers[index];
[self.scrollView addSubview:childVc.view];
精華例子2:
- 超級經(jīng)典,注意對比
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//以下演示的給對象添加backgroundColor钧忽,frame等等屬性毯炮,這些屬性一定要在view上進行。
UIView *zb = [[UIView alloc]init];
//zb是個view桃煎,已經(jīng)精確到了view,所以直接可以訪問backgroundColor大刊,frame屬性
zb.backgroundColor = [UIColor redColor];
zb.frame =CGRectMake(80, 80, 100,100);
//self是控制器为迈,必須精確到控制器的view,才能將zb添加到控制器的view上缺菌,否則報錯葫辐。
[self.view addSubview:zb];
//雖說下面的顯示不出運行結(jié)果,但是我們的目的達到了
UIViewController *vc = [[UIViewController alloc] init];
//vc是個控制器,必須精確到vc.view伴郁,才能訪問backgroundColor另患,frame屬性
vc.view.backgroundColor = [UIColor yellowColor];
vc.view.frame =CGRectMake(300, 80, 100, 100) ;
//vc是個控制器,所以可以添加到self上蛾绎。這個時候再用self.view就會報錯
[self addChildViewController:vc];
}
@end
UIViewController和UITableViewController創(chuàng)建出來時昆箕,y的坐標分別為多少
創(chuàng)建TableView的3中方法
- 方式1.利用自帶的ViewController類,繼承UIViewController
- 然后在ViewController.m租冠,遵守協(xié)議<UITableViewDataSource, UITableViewDelegate>
- 設(shè)置數(shù)據(jù)源和代理 tableView.dataSource = self; tableView.delegate = self;
- 實現(xiàn)數(shù)據(jù)源方法和代理方法即可
- 方式2.利用自帶的ViewController類鹏倘,將繼承的UIViewController類改為UITableViewController類
- 在Storyboard選中名字為View的View,然后將Class改為UITableVIew
- 然后在ViewController.m顽爹,直接實現(xiàn)數(shù)據(jù)源方法和代理方法纤泵,不要遵守協(xié)議,不需要設(shè)置數(shù)據(jù)源和代理
- 注意:如果沒有繼承UITableViewController镜粤,而是繼承UIViewController捏题,在執(zhí)行那三個步驟,雖然能顯示TableView的樣子肉渴,但是TableView的cell里面沒有任何內(nèi)容公荧,即使你設(shè)置了cell的內(nèi)容
- 方式3.利用自帶的ViewController類,將繼承的UIViewController類改為UITableViewController類
- 在Storyboard中刪除默認的UIViewController控制器同规,增加一個UITableViewController控制器(別忘記加箭頭哦)
- 然后選中Table View Controller循狰,將class改為ViewController窟社。這就實現(xiàn)了讓ViewController類來管理Table View Controller.
- 如果UIViewController不繼承UITableViewController,而是繼承UIViewController绪钥,那么無法將將class改為ViewController灿里。
- 因為只有相同類型才能進行管理,storyboard中的Table View Controller是UITableViewController類型的程腹,怎么能讓UIViewController類型的類來管理它呢
- 然后在ViewController.m匣吊,直接實現(xiàn)數(shù)據(jù)源方法和代理方法,不要遵守協(xié)議寸潦,不需要設(shè)置數(shù)據(jù)源和代理
方法1代碼+截圖
- ViewController.h文件
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
- ViewController.m文件
#import "ViewController.h"
@interface ViewController () <UITableViewDataSource, UITableViewDelegate>
@property (nonatomic, weak) UITableView *tableView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UITableView *tableView = [[UITableView alloc] init];
tableView.frame = CGRectMake(80, 100, 200, 300);
tableView.backgroundColor = [UIColor grayColor];
//數(shù)據(jù)源
tableView.dataSource = self;
//代理
tableView.delegate = self;
[self.view addSubview:tableView];
}
#pragma mark - <UITableViewDelegate>
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"contentOffset.y = %f", tableView.contentOffset.y);
NSLog(@"contentSize.height = %f", tableView.contentSize.height);
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 20;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
cell.backgroundColor = [UIColor redColor];
}
cell.textLabel.text = [NSString stringWithFormat:@"%@-%zd", self.class, indexPath.row];
return cell;
}
@end
- 截圖
方法2代碼+截圖
- ViewController.h文件
#import <UIKit/UIKit.h>
@interface ViewController : UITableViewController
@end
- ViewController.m文件
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
#pragma mark -代理方法
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"contentOffset.y = %f", tableView.contentOffset.y);
NSLog(@"contentSize.height = %f", tableView.contentSize.height);
}
#pragma mark - 數(shù)據(jù)源方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 20;
}
#pragma mark - 數(shù)據(jù)源方法
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
cell.backgroundColor = [UIColor yellowColor];
}
cell.textLabel.text = [NSString stringWithFormat:@"%@-%zd", self.class, indexPath.row];
return cell;
}
@end
- 截圖
方法3代碼+截圖
- ViewController.h文件
#import <UIKit/UIKit.h>
@interface ViewController : UITableViewController
@end
- ViewController.m文件
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
#pragma mark -代理方法
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"contentOffset.y = %f", tableView.contentOffset.y);
NSLog(@"contentSize.height = %f", tableView.contentSize.height);
}
#pragma mark - 數(shù)據(jù)源方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 20;
}
#pragma mark - 數(shù)據(jù)源方法
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
cell.backgroundColor = [UIColor redColor];
}
cell.textLabel.text = [NSString stringWithFormat:@"%@-%zd", self.class, indexPath.row];
return cell;
}
@end
- 截圖效果和方法2一模一樣
UIScrollView的滾動
- 詳看第六天 UIScrollView和UITableView滾動都是一樣的色鸳。
-
ContentOffset: UIScrollView控件frame距內(nèi)容尺寸的偏移量. 往左偏移為正數(shù),往右偏移為負數(shù)
UIScrollView和UITableView的偏移量正負詳解
- UIScrollView偏移量:scrollView的左上角的值減去contentSize的左上角甸祭,就是contentOffset缕碎,偏移量(有正負)。contentSize(內(nèi)容尺寸)相對于scrollView向左移動池户,那么contentOffset就為正數(shù).向右移動咏雌,那么contentOffset就為負數(shù)。向上移動校焦,為正數(shù)赊抖,向下移動為負數(shù)
- 計算正負數(shù)技巧:
- contentSize(內(nèi)容尺寸)向左移動:contentOffset.x = 0 - (-100) = 100.
- contentSize(內(nèi)容尺寸)向右移動:contentOffset.x = 0 - 200 = -200.
- contentSize(內(nèi)容尺寸)向上移動:contentOffset.y = 0 - (-300) = 300.
- contentSize(內(nèi)容尺寸)向上移動:contentOffset.y = 0 - 400 = - 400.
- UITableView的偏移量:tableView的左上角的值減去contentSize的左上角,就是contentOffset寨典,偏移量(有正負)氛雪。contentSize(內(nèi)容尺寸)相對于tableView向左移動,那么contentOffset就為正數(shù).向右移動耸成,那么contentOffset就為負數(shù)报亩。向上移動,為正數(shù)井氢,向下移動為負數(shù)
- 計算正負數(shù)技巧:
- 同上
UIScrollView和UITableView滾動的是內(nèi)容而不是控件
1.把圖片添加到UIScrollView上.本質(zhì)上是把圖片添加到了UIScrollView的內(nèi)容上弦追。
我們滾動屏幕時,滾動的不是UIScrollView這個控件(窗口)花竞,滾動的是內(nèi)容.
我們手動滾動內(nèi)容時(也可以利用代碼控制contentOffset的偏移量實現(xiàn)滾動內(nèi)容)劲件,圖片會經(jīng)過這個UIScrollView(窗口),經(jīng)過窗口的內(nèi)容會被我們看到约急。
如果你認為圖片添加到了UIScrollView這個控件上零远,假設(shè)圖片添加到了UIScrollView控件的外側(cè)(屏幕的外側(cè)),這樣我們無論怎么滾動厌蔽,也永遠看不到這張圖片牵辣。因為UIScrollView此時就是一個供我們看東西的窗口,超過窗口的東西我們永遠看不到躺枕,你把圖片添加到了這個窗口的外側(cè)服猪,而不是添加到了內(nèi)容上供填,你滾動內(nèi)容時拐云,內(nèi)容里面并沒有圖片罢猪,內(nèi)容經(jīng)過窗口時,怎么會顯示這張圖片(UIScrollView就是窗口叉瘩,通過這個窗口我們才能看到圖片膳帕,超過這個窗口的圖片,我們永遠看不到薇缅。類比井底之蛙)
2.為什么能滾動危彩?
contentSize不能滾動,contentSize僅僅是提供了一個供我們滾動的矩形范圍泳桦。scrollView的內(nèi)容能滾動(前提:我們必須用手滾內(nèi)容啊汤徽,只要觸摸到了內(nèi)容,就能滾灸撰,底層幫我們做好了谒府,不要問為什么)。
3. UIScrollView的內(nèi)容是啥浮毯,包括啥完疫? 內(nèi)容是虛擬的,我們看不到债蓝,但是實際存在壳鹤,如果你把2張圖片通過[self.scrollView addSubview:imageV];的形式添加到了內(nèi)容中,那么內(nèi)容就是兩張圖片饰迹。即芳誓,執(zhí)行addSubview:的操作,執(zhí)行addSubview:方法的參數(shù)就是內(nèi)容,
4.如果你現(xiàn)在仍理解為把圖片添加到UIScrollView上啊鸭,你就無法理解滾動的誰锹淌?為什么能滾動?窗口是誰莉掂?contentSize的深層次含義葛圃?
5.看UITableView動態(tài)截圖+ppt截圖你就理解UIScrollView了:UITableView控件并不能滾動,而是內(nèi)容能滾動憎妙。
UITableView的滾動
- 前言:不受任何干擾來驗證TableView的ContentSize的范圍的做法是取消彈簧效果库正,這樣能滾動多少范圍就能滾動多少范圍。代碼:self.tableView.bounces =NO;
- 以后見到任意一款app厘唾,如果里面有滾動的內(nèi)容褥符,你要想到之所以能滾動,是內(nèi)容滾動造成的抚垃,而不是UITableView的滾動喷楣,也不是UIScrollView的滾動趟大,也不是UICollectionView的滾動。他們?nèi)齻€只是提供一個窗口讓你滾動铣焊,超出這個而窗口我們就看不到窗口之外的內(nèi)容了逊朽。就像井底之蛙一樣,井口就是UITableView曲伊,是UIScrollView叽讳,是UICollectionView,是固定不動的坟募,天上的云彩就是內(nèi)容岛蚤,青蛙可以控制云彩的移動,青蛙就是人的手懈糯。內(nèi)容尺寸僅僅是提供了內(nèi)容所能滾動的范圍涤妒,
- UITableView不設(shè)置ContentSize也能滾動,系統(tǒng)內(nèi)部幫我們算好了.所以開發(fā)中一般不設(shè)置
- UIScrollView必須設(shè)置ContentSize才能滾動
- ContentSize:內(nèi)容的 大小/尺寸赚哗,這個尺寸構(gòu)成了矩形她紫。就比如設(shè)置UIView的frame就決定了UIView的尺寸和位置
- 內(nèi)容尺寸小于UITableView的尺寸(frame)是無法滾動的。你拖動時時能滾動蜂奸,但是松開手又彈回來了犁苏。這不是滾動哦。必須大于UITableView的尺寸才可以滾動的
//本質(zhì):所能滾動的內(nèi)容尺寸就是一個寬為100扩所,高位200的矩形
tableView.contentSize = CGSizeMake(100, 200);
//類比UIScrollView設(shè)置滾動的內(nèi)容尺寸
scrollView.contentSize = CGSizeMake(100, 200);
- scrollView添加到控制器的view上.tableView添加到scrollView上
- 兩個都是可以滾動的围详。
- 可以實現(xiàn)scrollView負責左右滾動,tableView負責上下滾動祖屏。當移動scrollView時,里面的tableView會被移動到屏幕外助赞,當又移到屏幕內(nèi)時,可以保證這個tableView的內(nèi)容仍是之前的內(nèi)容
- 為什么tableView添加到scrollView上袁勺?實際上是添加到scrollView的內(nèi)容尺寸上雹食。
- 只有將5個tableView添加到scrollView上,左右滾動scrollView的內(nèi)容尺寸時期丰,才能顯示加到scrollView的內(nèi)容尺寸中TableView群叶,如果不加到scrollView上兼犯,那么左右滾動scrollView的內(nèi)容尺寸時从诲,因為scrollView中沒有添加任何數(shù)據(jù)大审,所以只會顯示水平指示條奠骄,垂直指示條。你不加到scrollView的內(nèi)容尺寸上维咸,scrollView中憑什么要展示你回懦?闽撤?
UITableView的屬性:frame端辱,ContentOffset梁剔,ContentInset虽画,ContentSize區(qū)分
理解的前提:我們滾動的是內(nèi)容(cell,TableHeadView的高度荣病,TableFooterView高度等等)码撰,滾動的范圍是ContentSize的frame所形成的矩形。
frame:UITableView控件自身的尺寸(矩形)
ContentOffset: 內(nèi)容尺寸距離UITableView控件frame的偏移量众雷,ContentSize(矩形)往上偏移為正數(shù)灸拍,往下偏移為負數(shù)
ContentInset:內(nèi)邊距,即內(nèi)容尺寸周圍的間距做祝,即內(nèi)容尺寸周圍添加的邊距砾省,是無縫粘著內(nèi)容尺寸的邊緣。例如頂部增加100像素混槐,當拖動TableView的時候编兄,頂部可多拖動100像素,并且是永久多出100像素声登。不是拖到不能再拖的時候狠鸳,又彈回來的那種。
-
ContentSize:內(nèi)容尺寸的大小(寬,高)比如高為100,那么最終只能滾動100的范圍,超出滾動的范圍在停止拖拽之后由于彈簧效果會被彈回來(可以通過self.tableView.bounces =NO;禁止彈簧效果來驗證只能滾動100的范圍)悯嗓。UITableView不設(shè)置ContentSize也能滾動
- 它的內(nèi)容尺寸的高度=所有cell的總高度+TableHeadView的高度+TableFooterView高度+sectionHeader的高度+sectionFooter的高度.記住:就是不包括內(nèi)邊距
- ContentInset和TableHeadView和TableFooterView都是緊緊粘著內(nèi)容尺寸的邊緣件舵,如果都存在,那么ContentInset緊貼著TableHeadView的上部脯厨,緊貼著TableFooterView的底部铅祸。因為TableHeadView和TableFooterView屬于內(nèi)容尺寸的一部分
- 在手機上用戶滾動時,我們拿著6s Plus在(414, 736)尺寸的屏幕上滾動合武,滾動的是ContentSize所形成的矩形
- 注意:ContentSize只是用來設(shè)置矩形的大小的临梗。我們滾動的形成的這個矩形,這個矩形是看不到的稼跳,所以會誤讓我們以為滾動的是UITableView盟庞。
UITableView的frame所形成的是個矩形,ContentSize形成的也是個矩形汤善。這兩個矩形的左上角的差值就是偏移量
- ContentSize和內(nèi)邊距是分開的
- 之所以讓內(nèi)容尺寸的高度等于內(nèi)容的高度的原因:
- 內(nèi)容尺寸決定滾動的范圍什猖,只有兩者相等,才能確保內(nèi)容都能全部讓我們滾動到红淡。本質(zhì)上內(nèi)容尺寸和內(nèi)容高度一點關(guān)系都沒有不狮,只是我們手讓他們產(chǎn)生了關(guān)系
- 計算tableView內(nèi)容尺寸的大小(congtentsize)和內(nèi)邊距一點關(guān)系都沒有,內(nèi)邊距不參與計算tableView內(nèi)容的大小
- 根據(jù)上面的公式:內(nèi)容的高度=所有cell的總高度+TableHeadView的高度+TableFooterView高度+sectionHeader的高度+sectionFooter的高度.記住:就是不包括內(nèi)邊距锉屈。
- 通過 內(nèi)容尺寸的高度=所有cell的總高度+TableHeadView的高度+TableFooterView高度+sectionHeader的高度+sectionFooter的高度.記住:就是不包括內(nèi)邊距荤傲。 來確保內(nèi)容都能全部讓我們滾動到
- 計算偏移量(contentoffset)和內(nèi)邊距(contentInset)沒有關(guān)系,內(nèi)邊距不參與計算偏移量的多少颈渊。
- 因為偏移量是=內(nèi)容距UITableView控件frame的偏移量遂黍,又因為內(nèi)容不包括內(nèi)邊距终佛,UITableView控件frame只和自己的本身有關(guān)系,所以說偏移量和內(nèi)邊距一點關(guān)系都沒有
- 之所以讓內(nèi)容尺寸的高度等于內(nèi)容的高度的原因:
沒有cell雾家,沒有contentInset铃彰,沒有TableHeadView、TableHeaderView的情況
- 內(nèi)容的高度=所有cell的總高度+TableHeadView的高度+TableFooterView高度+sectionHeader的高度+sectionFooter的高度.記住:就是不包括內(nèi)邊距芯咧。
- 通過 內(nèi)容尺寸的高度=所有cell的總高度+TableHeadView的高度+TableFooterView高度+sectionHeader的高度+sectionFooter的高度.記住:就是不包括內(nèi)邊距牙捉。 來確保內(nèi)容都能全部讓我們滾動到
#import "ViewController.h"
@interface ViewController () <UITableViewDelegate>
@property (nonatomic, weak) UITableView *tableView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UITableView *tableView = [[UITableView alloc] init];
tableView.frame = CGRectMake(100, 100, 200, 300);
tableView.backgroundColor = [UIColor grayColor];
tableView.delegate = self;
tableView.rowHeight = 40;
[self.view addSubview:tableView];
self.tableView = tableView;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSLog(@"contentSize.height = %f", self.tableView.contentSize.height);
}
#pragma mark - UITableViewDelegate
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 0;
}
@end
- 截圖
- ppt截圖
有cell,沒有contentInset敬飒,沒有TableHeadView邪铲、TableHeaderView的情況
- 內(nèi)容的高度=所有cell的總高度+TableHeadView的高度+TableFooterView高度+sectionHeader的高度+sectionFooter的高度.記住:就是不包括內(nèi)邊距。
- 通過 內(nèi)容尺寸的高度=所有cell的總高度+TableHeadView的高度+TableFooterView高度+sectionHeader的高度+sectionFooter的高度.記住:就是不包括內(nèi)邊距无拗。 來確保內(nèi)容都能全部讓我們滾動到
#import "ViewController.h"
@interface ViewController () <UITableViewDataSource, UITableViewDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UITableView *tableView = [[UITableView alloc] init];
tableView.frame = CGRectMake(100, 100, 200, 300);
tableView.backgroundColor = [UIColor grayColor];
tableView.dataSource = self;
tableView.delegate = self;
tableView.rowHeight = 40;
[self.view addSubview:tableView];
}
#pragma mark - <UITableViewDelegate>
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"\t內(nèi)容尺寸的偏移量y:contentOffset.y = %f", tableView.contentOffset.y);
NSLog(@"\t內(nèi)容尺寸的高度:contentSize.height = %f", tableView.contentSize.height);
}
#pragma mark - 數(shù)據(jù)源
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 20;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
cell.backgroundColor = [UIColor redColor];
}
cell.textLabel.text = [NSString stringWithFormat:@"%@-%zd", self.class, indexPath.row];
return cell;
}
@end
- 運行結(jié)果
- 點擊cell带到,提示偏移量為0,內(nèi)容尺寸的高度為800.這個800是20個cell 的總高度
- ppt截圖
有cell英染,有contentInset揽惹,沒有TableHeadView、TableHeaderView的情況
#import "ViewController.h"
@interface ViewController () <UITableViewDataSource, UITableViewDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UITableView *tableView = [[UITableView alloc] init];
tableView.frame = CGRectMake(100, 100, 200, 300);
tableView.backgroundColor = [UIColor grayColor];
tableView.dataSource = self;
tableView.delegate = self;
tableView.rowHeight = 40;
[self.view addSubview:tableView];
// 內(nèi)邊距
//距tableView內(nèi)容尺寸頂部的距離為64四康,距tableView內(nèi)容尺寸底部的距離為49搪搏。即停止拖動時候頂部多出64的距離,底部多出49的距離,永久性的多出這些距離闪金。
tableView.contentInset = UIEdgeInsetsMake(64, 0, 49, 0);
}
#pragma mark - <UITableViewDelegate>
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"\t內(nèi)容尺寸的偏移量y:contentOffset.y = %f", tableView.contentOffset.y);
NSLog(@"\t內(nèi)容尺寸的高度:contentSize.height = %f", tableView.contentSize.height);
}
#pragma mark - 數(shù)據(jù)源
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 20;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
cell.backgroundColor = [UIColor redColor];
}
cell.textLabel.text = [NSString stringWithFormat:@"%@-%zd", self.class, indexPath.row];
return cell;
}
@end
- 截圖
- ppt截圖
詳情分析:
- tableView.contentInset = UIEdgeInsetsMake(64, 0, 49, 0);//頂部內(nèi)邊距64疯溺,底部內(nèi)邊距49
- 程序運行時,因為距tableView內(nèi)容尺寸頂部的距離為64毕泌,距tableView內(nèi)容尺寸底部的距離為49喝检。即停止拖動時候頂部多出64的距離,底部多出49的距離(永久多出的距離撼泛,不恢復)挠说。程序初始運行時顯示的控件的狀態(tài)也就相當于停止拖動的時候的狀態(tài)。
- 先把控件顯示到指定的位置上愿题,然后才計算偏移量和內(nèi)容尺寸的高度
- 點擊cell 提示800.說明self.tableView.contentSize.height這個內(nèi)容尺寸的高度的計算不包括計算contentInset损俭,
- 點擊cell,執(zhí)行 NSLog(@"contentOffset.y = %f", tableView.contentOffset.y);打印偏移量為-64.因為contentInse不是contentSize的一部分潘酗。再加上UITableView矩形框的左上角和contentSize矩形框的左上角不重合杆兵,即有差值,所以有偏移量仔夺。
有cell琐脏,沒有contentInset,有TableHeadView、TableHeaderView的情況
#import "ViewController.h"
@interface ViewController () <UITableViewDataSource, UITableViewDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UITableView *tableView = [[UITableView alloc] init];
tableView.frame = CGRectMake(100, 100, 200, 300);
tableView.backgroundColor = [UIColor grayColor];
tableView.dataSource = self;
tableView.delegate = self;
tableView.rowHeight = 40;
[self.view addSubview:tableView];
// header - footer
UIView *header = [[UIView alloc] init];
header.frame = CGRectMake(0, 0, tableView.frame.size.width, 64);
header.backgroundColor = [UIColor yellowColor];
tableView.tableHeaderView = header;
UIView *footer = [[UIView alloc] init];
footer.frame = CGRectMake(0, 0, tableView.frame.size.width, 49);
footer.backgroundColor = [UIColor greenColor];
tableView.tableFooterView = footer;
}
#pragma mark - <UITableViewDelegate>
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"\t內(nèi)容尺寸的偏移量y:contentOffset.y = %f", tableView.contentOffset.y);
NSLog(@"\t內(nèi)容尺寸的高度:contentSize.height = %f", tableView.contentSize.height);
}
#pragma mark - 數(shù)據(jù)源
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 20;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
cell.backgroundColor = [UIColor redColor];
}
cell.textLabel.text = [NSString stringWithFormat:@"%@-%zd", self.class, indexPath.row];
return cell;
}
@end
- 截圖
- ppt截圖
詳情分析:
- 點擊cell日裙,提示913吹艇,說明800+64+49=913,說明self.tableView.contentSize.height這個內(nèi)容尺寸的高度的計算包括計算tableHeaderView和tableFooterView的高度
- 點擊cell昂拂,執(zhí)行 NSLog(@"contentOffset.y = %f", tableView.contentOffset.y);打印偏移量為0.說明因為tableHeaderView和tableFooterView都是contentSize的一部分
有cell受神,有contentInset,有TableHeadView格侯、TableHeaderView的情況
#import "ViewController.h"
@interface ViewController () <UITableViewDataSource, UITableViewDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UITableView *tableView = [[UITableView alloc] init];
tableView.frame = CGRectMake(100, 100, 200, 300);
tableView.backgroundColor = [UIColor grayColor];
tableView.dataSource = self;
tableView.delegate = self;
tableView.rowHeight = 40;
[self.view addSubview:tableView];
// 內(nèi)邊距
//距tableView內(nèi)容尺寸頂部的距離為64鼻听,距tableView內(nèi)容尺寸底部的距離為49。即停止拖動時候頂部多出64的距離联四,底部多出49的距離撑碴。
tableView.contentInset = UIEdgeInsetsMake(64, 0, 49, 0);
// header - footer
UIView *header = [[UIView alloc] init];
header.frame = CGRectMake(0, 0, tableView.frame.size.width, 64);
header.backgroundColor = [UIColor yellowColor];
tableView.tableHeaderView = header;
UIView *footer = [[UIView alloc] init];
footer.frame = CGRectMake(0, 0, tableView.frame.size.width, 49);
footer.backgroundColor = [UIColor greenColor];
tableView.tableFooterView = footer;
}
#pragma mark - <UITableViewDelegate>
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"\t內(nèi)容尺寸的偏移量y:contentOffset.y = %f", tableView.contentOffset.y);
NSLog(@"\t內(nèi)容尺寸的高度:contentSize.height = %f", tableView.contentSize.height);
}
#pragma mark - 數(shù)據(jù)源
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 20;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
cell.backgroundColor = [UIColor redColor];
}
cell.textLabel.text = [NSString stringWithFormat:@"%@-%zd", self.class, indexPath.row];
return cell;
}
@end
- 截圖
- ppt截圖
詳情分析:
- 點擊cell,偏移量為-64碎连,內(nèi)容尺寸的高度為913.只是UIScrollVIew的位置和之前的位置不一樣了灰羽。
有cell,沒有contentInset鱼辙,沒有TableHeadView、TableHeaderView玫镐,有額外添加的子控件{0, -40, 375, 40}
#import "ViewController.h"
@interface ViewController () <UITableViewDataSource, UITableViewDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UITableView *tableView = [[UITableView alloc] init];
tableView.frame = CGRectMake(100, 100, 200, 300);
tableView.backgroundColor = [UIColor grayColor];
tableView.dataSource = self;
tableView.delegate = self;
tableView.rowHeight = 40;
[self.view addSubview:tableView];
// 額外添加的子控件 會顯示在TableVIew的內(nèi)部
UIView *zb = [[UIView alloc] init];
zb.frame = CGRectMake(0, -40, tableView.frame.size.width, 40);
zb.backgroundColor = [UIColor blueColor];
[tableView addSubview:zb];
}
#pragma mark - <UITableViewDelegate>
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"\t內(nèi)容尺寸的偏移量y:contentOffset.y = %f", tableView.contentOffset.y);
NSLog(@"\t內(nèi)容尺寸的高度:contentSize.height = %f", tableView.contentSize.height);
}
#pragma mark - 數(shù)據(jù)源
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 20;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
cell.backgroundColor = [UIColor redColor];
}
cell.textLabel.text = [NSString stringWithFormat:@"%@-%zd", self.class, indexPath.row];
return cell;
}
@end
- 截圖
- ppt截圖
詳情分析:
- zb這個view添加到TableView上倒戏,那么zb的父控件是UITableView還是UITableView的內(nèi)容呢?
- frame是指:以父控件的內(nèi)容尺寸的左上角為坐標原點恐似。所以zb是添加到UITableView的內(nèi)容上杜跷。即zb是以父控件的內(nèi)容尺寸的左上角為坐標原點
所以當我們滾動內(nèi)容尺寸的時候,添加的這個zb著滾動矫夷,如果我們認為是添加到UITableView上葛闷,UIableView始終是固定不變的,zb以父控件的坐標原點為原點双藕,因為UITableView一直不變淑趾,所以UITableView的坐標原點也一致不變,那么zb一直不變忧陪。當我們滾動內(nèi)容尺寸的時候扣泊,zb應(yīng)當是不移動的。 但是真實情況是嘶摊,zb會移動延蟹,所以我們認為的是錯的。所zb到內(nèi)容尺寸中 - 向下拖動+gif動畫超級好演示 可以看到拖出來一個藍色的view叶堆,就是zb阱飘,松手之后又彈回去了,看不見了
- 偏移量為0,內(nèi)容尺寸為800.所以內(nèi)容尺寸不計算子控件的40沥匈」迹可以看看內(nèi)容尺寸的計算公式,公式中沒有子控件這個變量咐熙,所以不計算弱恒。以后跟著這個公司來就很好理解滾動的TableView了
有cell,有contentInset棋恼,沒有TableHeadView返弹、TableHeaderView,有額外添加的子控件{0, -40, 375, 40}
#import "ViewController.h"
@interface ViewController () <UITableViewDataSource, UITableViewDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UITableView *tableView = [[UITableView alloc] init];
tableView.frame = CGRectMake(100, 100, 200, 300);
tableView.backgroundColor = [UIColor grayColor];
tableView.dataSource = self;
tableView.delegate = self;
tableView.rowHeight = 40;
[self.view addSubview:tableView];
// 內(nèi)邊距
//距tableView內(nèi)容尺寸頂部的距離為64爪飘,距tableView內(nèi)容尺寸底部的距離為49义起。即停止拖動時候頂部多出64的距離,底部多出49的距離师崎。
tableView.contentInset = UIEdgeInsetsMake(64, 0, 49, 0);
// 額外添加的子控件 會顯示在TableVIew的內(nèi)部
UIView *header = [[UIView alloc] init];
header.frame = CGRectMake(0, -40, tableView.frame.size.width, 40);
header.backgroundColor = [UIColor blueColor];
[tableView addSubview:header];
}
#pragma mark - <UITableViewDelegate>
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"\t內(nèi)容尺寸的偏移量y:contentOffset.y = %f", tableView.contentOffset.y);
NSLog(@"\t內(nèi)容尺寸的高度:contentSize.height = %f", tableView.contentSize.height);
}
#pragma mark - 數(shù)據(jù)源
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 20;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
cell.backgroundColor = [UIColor redColor];
}
cell.textLabel.text = [NSString stringWithFormat:@"%@-%zd", self.class, indexPath.row];
return cell;
}
@end
-
截圖
- ppt截圖
詳細分析:
- 運行時默终,頂部內(nèi)邊距我64,有40被藍色的子控件擋住
- 精華理解:contentInset先占據(jù)64犁罩,把ContentSize擠下去64齐蔽,然后藍色的子控件添加到ContentSize的頂部(被擠下去的頂部)
有cell,沒有contentInset床估,有TableHeadView含滴、TableHeaderView,有額外添加的子控件{0, -40, 375, 40}
#import "ViewController.h"
@interface ViewController () <UITableViewDataSource, UITableViewDelegate>
@property (nonatomic, weak) UITableView *tableView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UITableView *tableView = [[UITableView alloc] init];
tableView.frame = CGRectMake(100, 100, 200, 300);
tableView.backgroundColor = [UIColor grayColor];
tableView.dataSource = self;
tableView.delegate = self;
tableView.rowHeight = 40;
[self.view addSubview:tableView];
self.tableView = tableView;
// header - footer
UIView *header = [[UIView alloc] init];
header.frame = CGRectMake(0, 0, tableView.frame.size.width, 64);
header.backgroundColor = [UIColor yellowColor];
tableView.tableHeaderView = header;
UIView *footer = [[UIView alloc] init];
footer.frame = CGRectMake(0, 0, tableView.frame.size.width, 49);
footer.backgroundColor = [UIColor greenColor];
tableView.tableFooterView = footer;
// 額外添加的子控件 會顯示在TableVIew的內(nèi)部
UIView *zb = [[UIView alloc] init];
zb.frame = CGRectMake(0, -40, tableView.frame.size.width, 40);
zb.backgroundColor = [UIColor blueColor];
[tableView addSubview:zb];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSLog(@"\n \n 內(nèi)容尺寸的高度:contentSize.height = %f", self.tableView.contentSize.height);
}
#pragma mark - <UITableViewDelegate>
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"\t內(nèi)容尺寸的偏移量y:contentOffset.y = %f", tableView.contentOffset.y);
NSLog(@"\t內(nèi)容尺寸的高度:contentSize.height = %f", tableView.contentSize.height);
}
#pragma mark - 數(shù)據(jù)源
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 20;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
cell.backgroundColor = [UIColor redColor];
}
cell.textLabel.text = [NSString stringWithFormat:@"%@-%zd", self.class, indexPath.row];
return cell;
}
@end
- 截圖
- ppt截圖
有cell丐巫,有contentInset谈况,有TableHeadView、TableHeaderView递胧,有額外添加的子控件{0, -40, 375, 40}
#import "ViewController.h"
@interface ViewController () <UITableViewDataSource, UITableViewDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UITableView *tableView = [[UITableView alloc] init];
tableView.frame = CGRectMake(100, 100, 200, 300);
tableView.backgroundColor = [UIColor grayColor];
tableView.dataSource = self;
tableView.delegate = self;
tableView.rowHeight = 40;
[self.view addSubview:tableView];
// 內(nèi)邊距
//距tableView內(nèi)容尺寸頂部的距離為64碑韵,距tableView內(nèi)容尺寸底部的距離為49。即停止拖動時候頂部多出64的距離缎脾,底部多出49的距離祝闻。
tableView.contentInset = UIEdgeInsetsMake(64, 0, 49, 0);
// header - footer
UIView *header = [[UIView alloc] init];
header.frame = CGRectMake(0, 0, tableView.frame.size.width, 64);
header.backgroundColor = [UIColor yellowColor];
tableView.tableHeaderView = header;
UIView *footer = [[UIView alloc] init];
footer.frame = CGRectMake(0, 0, tableView.frame.size.width, 49);
footer.backgroundColor = [UIColor greenColor];
tableView.tableFooterView = footer;
// 額外添加的子控件 會顯示在TableVIew的內(nèi)部
UIView *zb = [[UIView alloc] init];
zb.frame = CGRectMake(0, -40, tableView.frame.size.width, 40);
zb.backgroundColor = [UIColor blueColor];
[tableView addSubview:zb];
}
#pragma mark - <UITableViewDelegate>
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"\t內(nèi)容尺寸的偏移量y:contentOffset.y = %f", tableView.contentOffset.y);
NSLog(@"\t內(nèi)容尺寸的高度:contentSize.height = %f", tableView.contentSize.height);}
#pragma mark - 數(shù)據(jù)源
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 20;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
cell.backgroundColor = [UIColor redColor];
}
cell.textLabel.text = [NSString stringWithFormat:@"%@-%zd", self.class, indexPath.row];
return cell;
}
@end
- 截圖
- ppt截圖
沒有cell,沒有contentInset赊锚,有TableHeadView治筒、TableHeaderView,沒有有額外添加的子控件{0, -40, 375, 40}
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, weak) UITableView *tableView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UITableView *tableView = [[UITableView alloc] init];
tableView.frame = CGRectMake(100, 100, 200, 300);
tableView.backgroundColor = [UIColor grayColor];
tableView.rowHeight = 40;
[self.view addSubview:tableView];
self.tableView = tableView;
// header - footer
UIView *header = [[UIView alloc] init];
header.frame = CGRectMake(0, 0, tableView.frame.size.width, 64);
header.backgroundColor = [UIColor yellowColor];
tableView.tableHeaderView = header;
UIView *footer = [[UIView alloc] init];
footer.frame = CGRectMake(0, 0, tableView.frame.size.width, 49);
footer.backgroundColor = [UIColor greenColor];
tableView.tableFooterView = footer;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSLog(@"\t內(nèi)容尺寸的高度:contentSize.height = %f", self.tableView.contentSize.height);
}
@end
- 截圖
- ppt截圖
詳細分析:
點擊控制器的touchbegan 打印113舷蒲,就是64+49=113. 并且拖動內(nèi)容尺寸耸袜,脫完松手,又會彈回來牲平,因為內(nèi)容尺寸小于UITableView的尺寸
精華截圖動畫
全屏穿透效果知識點:
讓TableView的frame為窗口的大小堤框。
為每個TableView在頂部添加內(nèi)間距,距離為=狀態(tài)欄+導航欄+標題欄。為每個TableView在底部添加內(nèi)邊距蜈抓,距離為=tabBar的高度(49)
self.tableView.contentInset = UIEdgeInsetsMake(ZBNavBarMaxY+ZBTitlesViewH, 0, ZBTabBarH, 0);隱藏滾動條
self.tableView.scrollIndicatorInsets = self.tableView.contentInset;既能穿透導航欄启绰,又能讓底部的tabbar不擋住最下面的cell的做法
給tableView在上下增加內(nèi)邊距,滑動到最下方沟使,由下方的內(nèi)邊距頂著委可,所以最下面的cell不會被擋住