概述
UIScrollView(滾動(dòng)視圖)是一個(gè)在日常開(kāi)發(fā)中使用頻率極高的容器視圖控件, 它允許用戶通過(guò)滾動(dòng)和縮放的方式查看超出屏幕區(qū)域大小的內(nèi)容, 在應(yīng)用程序開(kāi)發(fā)中經(jīng)常使用到的UITableView(列表視圖)、UICollectionView(集合視圖)和UITextView(文本視圖)都是它的子類(lèi).
下面將從用戶界面和事件處理兩個(gè)方面對(duì)UIScrollView做一次詳細(xì)的使用介紹和簡(jiǎn)要的實(shí)現(xiàn)原理分析.
用戶界面相關(guān)
內(nèi)容區(qū)域相關(guān)API介紹
該屬性用于標(biāo)識(shí)內(nèi)容區(qū)域的起點(diǎn)相對(duì)于scrollView的起點(diǎn)的偏移量, 默認(rèn)值為CGPointZero
@property(nonatomic) CGPoint contentOffset;
- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated;
該屬性用于標(biāo)識(shí)內(nèi)容區(qū)域的尺寸, 默認(rèn)值為CGSizeZero
@property(nonatomic) CGSize contentSize;
該屬性用于標(biāo)識(shí)為內(nèi)容區(qū)域周?chē)黾拥目蓾L動(dòng)區(qū)域, 默認(rèn)值為UIEdgeInsetsZero
@property(nonatomic) UIEdgeInsets contentInset;
該屬性用于標(biāo)識(shí)為內(nèi)容區(qū)域周?chē)黾拥?strong>總的可滾動(dòng)區(qū)域, 該屬性值的最終結(jié)果取決于contentInsetAdjustmentBehavior屬性的值
@property(nonatomic, readonly) UIEdgeInsets adjustedContentInset API_AVAILABLE(ios(11.0));
- (void)adjustedContentInsetDidChange API_AVAILABLE(ios(11.0)) NS_REQUIRES_SUPER;
該屬性用于配置safeAreaInsets如何影響adjustedContentInset屬性的值, 該屬性可設(shè)置四個(gè)枚舉值:
-
UIScrollViewContentInsetAdjustmentAutomatic: 默認(rèn), 在UIScrollViewContentInsetAdjustmentScrollableAxes的基礎(chǔ)上添加了向前兼容. 不論是否可以滾動(dòng), 如果scrollView所在的控制器位于導(dǎo)航控制器中且automaticallyAdjustsScrollViewInsets = YES, 則在上下兩個(gè)方向上adjustedContentInset = contentInset + safeAreaInsets成立 -
UIScrollViewContentInsetAdjustmentScrollableAxes: 在可滾動(dòng)方向上adjustedContentInset = contentInset + safeAreaInsets成立. 比如:contentSize.width/height > frame.size.width/height或者alwaysBounceHorizontal/Vertical = YES -
UIScrollViewContentInsetAdjustmentNever: 在任何情況下adjustedContentInset = contentInset成立 -
UIScrollViewContentInsetAdjustmentAlways: 在任何情況下adjustedContentInset = contentInset + safeAreaInsets成立
@property(nonatomic) UIScrollViewContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior API_AVAILABLE(ios(11.0));
該屬性用于標(biāo)識(shí)內(nèi)容區(qū)域和scrollView的Auto Layout參考線
@property(nonatomic,readonly,strong) UILayoutGuide *contentLayoutGuide API_AVAILABLE(ios(11.0));
@property(nonatomic,readonly,strong) UILayoutGuide *frameLayoutGuide API_AVAILABLE(ios(11.0));
指示器相關(guān)API介紹
該屬性用于配置指示器樣式, 該屬性可設(shè)置三個(gè)枚舉值:
-
UIScrollViewIndicatorStyleDefault: 默認(rèn), 黑內(nèi)容白邊框, 適用于任何背景 -
UIScrollViewIndicatorStyleBlack: 全黑, 較小, 適用于白色背景 -
UIScrollViewIndicatorStyleWhite: 全白, 較小, 適用于黑色背景
@property(nonatomic) UIScrollViewIndicatorStyle indicatorStyle;
該屬性用于標(biāo)識(shí)為指示器周?chē)黾拥目蓾L動(dòng)區(qū)域, 默認(rèn)值為UIEdgeInsetsZero
@property(nonatomic) UIEdgeInsets scrollIndicatorInsets;
該屬性用于標(biāo)識(shí)是否在滾動(dòng)時(shí)指示器可見(jiàn), 默認(rèn)為值YES
@property(nonatomic) BOOL showsHorizontalScrollIndicator;
@property(nonatomic) BOOL showsVerticalScrollIndicator;
該方法用于閃動(dòng)一下指示器. 建議在將scrollView展示給用戶時(shí)調(diào)用一下, 以提醒用戶該控件可以滾動(dòng)
- (void)flashScrollIndicators;
滾動(dòng)相關(guān)API介紹
該屬性用于標(biāo)識(shí)是否允許滾動(dòng), 默認(rèn)值為YES
@property(nonatomic,getter=isScrollEnabled) BOOL scrollEnabled;
該屬性用于標(biāo)識(shí)是否只允許同時(shí)滾動(dòng)一個(gè)方向, 默認(rèn)值為NO. 如果設(shè)置為YES, 則用戶在水平/豎直方向上開(kāi)始進(jìn)行滾動(dòng)操作, 便禁止同時(shí)在豎直/水平方向上進(jìn)行滾動(dòng)
注: 當(dāng)用戶在對(duì)角線方向上開(kāi)始進(jìn)行滾動(dòng)操作, 則本次滾動(dòng)可以同時(shí)在兩個(gè)方向上進(jìn)行滾動(dòng)
@property(nonatomic, getter=isDirectionalLockEnabled) BOOL directionalLockEnabled;
該屬性用于標(biāo)識(shí)是否允許通過(guò)點(diǎn)擊狀態(tài)欄讓距離狀態(tài)欄最近的scrollView滾動(dòng)到頂部, 默認(rèn)值為YES
注: 當(dāng)同時(shí)存在多個(gè)將該屬性設(shè)置為
YES的scrollView, 則該屬性在iPhone中無(wú)效; 在iPad中將距離狀態(tài)欄最近的scrollView滾動(dòng)到頂部
@property(nonatomic) BOOL scrollsToTop;
該屬性用于標(biāo)識(shí)是否按頁(yè)數(shù)進(jìn)行滾動(dòng), 默認(rèn)值為NO. 如果設(shè)置為YES, 則在滾動(dòng)時(shí)只會(huì)停止在scrollView的bounds的整數(shù)倍處
@property(nonatomic, getter=isPagingEnabled) BOOL pagingEnabled;
該屬性用于標(biāo)識(shí)是否有觸底反彈效果, 默認(rèn)值為YES
@property(nonatomic) BOOL bounces;
該屬性用于標(biāo)識(shí)是否總是有觸底反彈效果(即使contentSize小于scrollView的尺寸), 默認(rèn)值為NO
注: 該屬性生效的前提條件為
bounces = YES
@property(nonatomic) BOOL alwaysBounceHorizontal;
@property(nonatomic) BOOL alwaysBounceVertical;
該屬性用于配置當(dāng)用戶手指離開(kāi)屏幕后滾動(dòng)減速的速率, 該屬性可設(shè)置兩個(gè)常量:
-
UIScrollViewDecelerationRateNormal: 默認(rèn), 慢慢停止 -
UIScrollViewDecelerationRateFast: 快速停止
@property(nonatomic) CGFloat decelerationRate NS_AVAILABLE_IOS(3_0);
該方法用于將指定區(qū)域滾動(dòng)到剛好可見(jiàn)處
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated;
縮放相關(guān)API介紹
該屬性用于標(biāo)識(shí)最小縮放比例, 默認(rèn)值為1.0
@property(nonatomic) CGFloat minimumZoomScale;
該屬性用于標(biāo)識(shí)最大縮放比例, 默認(rèn)值為1.0
注: 該屬性值必須大于minimumZoomScale才能進(jìn)行縮放
@property(nonatomic) CGFloat maximumZoomScale;
該屬性用于標(biāo)識(shí)縮放比例, 默認(rèn)值為1.0
@property(nonatomic) CGFloat zoomScale NS_AVAILABLE_IOS(3_0);
- (void)setZoomScale:(CGFloat)scale animated:(BOOL)animated NS_AVAILABLE_IOS(3_0);
該方法用于將內(nèi)容縮放到指定區(qū)域
- (void)zoomToRect:(CGRect)rect animated:(BOOL)animated NS_AVAILABLE_IOS(3_0);
該屬性用于標(biāo)識(shí)是否允許觸底反彈, 默認(rèn)值為YES
@property(nonatomic) BOOL bouncesZoom;
該屬性用于標(biāo)識(shí)是否正在縮放
@property(nonatomic,readonly,getter=isZooming) BOOL zooming;
該屬性用于標(biāo)識(shí)是否正在觸底反彈
@property(nonatomic,readonly,getter=isZoomBouncing) BOOL zoomBouncing;
用戶界面實(shí)現(xiàn)原理
frame和bounds
這部分內(nèi)容將會(huì)簡(jiǎn)單介紹一下UIView的兩個(gè)屬性: frame和bounds, 這將有助于理解UIScrollView用戶界面的實(shí)現(xiàn)原理.
在iOS系統(tǒng)中, 視圖的坐標(biāo)系統(tǒng)的原點(diǎn)默認(rèn)位于視圖的左上角, 右方向?yàn)?code>x軸的正方向, 下方向?yàn)?code>y軸的正方向. 其中, frame用于描述視圖在父視圖坐標(biāo)系統(tǒng)中的位置和尺寸; bounds用于描述視圖在自身坐標(biāo)系統(tǒng)中的位置和尺寸. 下面通過(guò)兩個(gè)代碼片段來(lái)具體說(shuō)明:
// 代碼片段1
UIView *superView = [[UIView alloc] initWithFrame:CGRectMake(20.f, 20.f, 100.f, 100.f)];
superView.backgroundColor = [UIColor redColor];
[self.view addSubview:superView];
UIView *subView = [[UIView alloc] initWithFrame:CGRectMake(20.f, 20.f, 60.f, 60.f)];
subView.backgroundColor = [UIColor yellowColor];
[superView addSubview:subView];
NSLog(@"superView.frame = %@, superView.bounds = %@", NSStringFromCGRect(superView.frame), NSStringFromCGRect(superView.bounds));
// 輸出: superView.frame = {{20, 20}, {100, 100}}, superView.bounds = {{0, 0}, {100, 100}}
NSLog(@"subView.frame = %@, subView.bounds = %@", NSStringFromCGRect(subView.frame), NSStringFromCGRect(subView.bounds));
// 輸出: subView.frame = {{20, 20}, {60, 60}}, subView.bounds = {{0, 0}, {60, 60}}
// 代碼片段2
UIView *superView = [[UIView alloc] initWithFrame:CGRectMake(20.f, 20.f, 100.f, 100.f)];
superView.backgroundColor = [UIColor redColor];
[self.view addSubview:superView];
UIView *subView = [[UIView alloc] initWithFrame:CGRectMake(20.f, 20.f, 60.f, 60.f)];
subView.backgroundColor = [UIColor yellowColor];
[superView addSubview:subView];
// 新增代碼
superView.bounds = CGRectMake(0, 20, 100, 100);
NSLog(@"superView.frame = %@, superView.bounds = %@", NSStringFromCGRect(superView.frame), NSStringFromCGRect(superView.bounds));
// 輸出: superView.frame = {{20, 20}, {100, 100}}, superView.bounds = {{0, 20}, {100, 100}}
NSLog(@"subView.frame = %@, subView.bounds = %@", NSStringFromCGRect(subView.frame), NSStringFromCGRect(subView.bounds));
// 輸出: subView.frame = {{20, 20}, {60, 60}}, subView.bounds = {{0, 0}, {60, 60}}
通過(guò)以上兩個(gè)代碼片段可以看出, superView的bounds.origin發(fā)生變化并不影響其自身所處的位置, 但是卻會(huì)影響到subView的位置. 這是因?yàn)?code>superView的bounds.origin發(fā)生變化直接導(dǎo)致了自身坐標(biāo)系統(tǒng)的原點(diǎn)發(fā)生了改變, 即通過(guò)bounds.origin設(shè)置的值便是superView的左上角在自身坐標(biāo)系統(tǒng)中的位置, 而superView則會(huì)根據(jù)自身新的坐標(biāo)系統(tǒng)更新其subView的位置.
注: 本文在此僅涉及
bounds屬性的變化對(duì)位置的影響, 如果想了解其對(duì)尺寸的影響煩請(qǐng)自行
實(shí)現(xiàn)原理
通過(guò)上一部分內(nèi)容的介紹, 理解UIScrollView用戶界面的實(shí)現(xiàn)原理將不再有困難. 其實(shí)UIScrollView只是在用戶滾動(dòng)的時(shí)候動(dòng)態(tài)修改其bounds.origin的值, 這樣便會(huì)相應(yīng)地影響子視圖的位置變化, 而其他滑動(dòng)相關(guān)屬性則均用于約束bounds.origin的變化范圍. 以常用的四個(gè)屬性為例:
-
contentOffset: 當(dāng)用戶在scrollView中向上滑動(dòng)時(shí), 設(shè)置bounds.origin的值逐漸增加, 此時(shí)所有的子視圖便會(huì)相應(yīng)地向上移動(dòng). 其實(shí)contentOffset = bounds.origin. -
contentSize: 由于bounds.origin的值可以隨意變化, 因此scrollView便可以無(wú)限制地向四周滾動(dòng). 其實(shí)contentSize的值便是可滾動(dòng)范圍的抽象. -
contentInset和adjustedContentInset: 在不改變contentSize的前提下對(duì)可滾動(dòng)范圍進(jìn)行擴(kuò)展.
iOS11中的新變化
在iOS10及以前, 當(dāng)scrollView所在的控制器位于導(dǎo)航控制器的最頂層時(shí), 系統(tǒng)會(huì)通過(guò)contentInset屬性自動(dòng)為scrollView上方增加64pt的可滾動(dòng)區(qū)域以防內(nèi)容區(qū)域被導(dǎo)航欄遮擋. 該種優(yōu)化方式可以通過(guò)設(shè)置控制器的automaticallyAdjustsScrollViewInsets = NO來(lái)禁用.
注: 系統(tǒng)只在
UIScrollView是控制器視圖的第0個(gè)子視圖時(shí)才會(huì)自動(dòng)修改其contentInset屬性和scrollIndicatorInsets屬性
在iOS11中, 上述優(yōu)化方式被廢棄. 系統(tǒng)通過(guò)adjustedContentInset屬性配合contentInsetAdjustmentBehavior屬性來(lái)處理scrollView的內(nèi)容區(qū)域超出安全區(qū)域以外的情況, 這是一種對(duì)原有優(yōu)化方式的升級(jí), 避免了原有的一刀切的優(yōu)化方式.
注: 不要被圖片誤導(dǎo),
adjustedContentInset屬性的值是包含contentInset屬性的值的
事件處理相關(guān)
觸摸相關(guān)API介紹
該屬性用于標(biāo)識(shí)用戶是否已經(jīng)觸摸了內(nèi)容區(qū)域并準(zhǔn)備進(jìn)行滑動(dòng)
注: 該屬性值被設(shè)置為
YES的時(shí)候用戶可能只是觸摸了內(nèi)容區(qū)域, 但是并沒(méi)有開(kāi)始進(jìn)行滑動(dòng)
@property(nonatomic,readonly,getter=isTracking) BOOL tracking;
該屬性用于標(biāo)識(shí)用戶是否已經(jīng)開(kāi)始滑動(dòng)內(nèi)容區(qū)域
注: 該屬性值被設(shè)置為
YES之前用戶可能需要先滑動(dòng)一段時(shí)間或距離
@property(nonatomic,readonly,getter=isDragging) BOOL dragging;
該屬性用于標(biāo)識(shí)是否正在處于減速狀態(tài)(即手指已經(jīng)離開(kāi)屏幕, 但scrollView仍然處于滑動(dòng)中)
@property(nonatomic,readonly,getter=isDecelerating) BOOL decelerating;
該屬性用于標(biāo)識(shí)是否延遲內(nèi)容區(qū)域的事件傳遞, 默認(rèn)值為YES. 如果設(shè)置為NO, 則scrollView會(huì)立即調(diào)用-touchesShouldBegin:withEvent:inContentView:方法以進(jìn)行下一步操作
@property(nonatomic) BOOL delaysContentTouches;
當(dāng)已經(jīng)將事件傳遞給子視圖后是否可以取消, 默認(rèn)值為YES. 如果設(shè)置為NO, 則一旦開(kāi)始跟蹤事件, 即使手指進(jìn)行移動(dòng)也不會(huì)取消已經(jīng)傳遞給子視圖的事件
@property(nonatomic) BOOL canCancelContentTouches;
該方法用于在UIScrollView的子類(lèi)中重寫(xiě), 返回是否將事件傳遞給對(duì)應(yīng)的子視圖, 默認(rèn)返回YES. 如果返回NO, 則該事件不會(huì)傳遞給對(duì)應(yīng)的子視圖
- (BOOL)touchesShouldBegin:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view;
該方法用于在UIScrollView的子類(lèi)中重寫(xiě), 返回當(dāng)已經(jīng)將事件傳遞給子視圖后是否可以取消. 默認(rèn)當(dāng)子視圖是UIControl時(shí)返回NO, 即不再繼續(xù)跟蹤用戶的觸摸事件; 否則返回YES, 即仍然繼續(xù)跟蹤用戶的觸摸事件
注: 該方法被調(diào)用的前提是
canCancelContentTouches = YES
- (BOOL)touchesShouldCancelInContentView:(UIView *)view;
其他相關(guān)API介紹
該屬性用于配置隱藏鍵盤(pán)的模式, 該屬性可設(shè)置三個(gè)枚舉值:
-
UIScrollViewKeyboardDismissModeNone: 默認(rèn)值, 不隱藏鍵盤(pán) -
UIScrollViewKeyboardDismissModeOnDrag: 當(dāng)拖拽時(shí)隱藏鍵盤(pán) -
UIScrollViewKeyboardDismissModeInteractive: 當(dāng)拖拽鍵盤(pán)上方時(shí)隱藏鍵盤(pán), 如果反向拖拽鍵盤(pán)會(huì)取消隱藏
@property(nonatomic) UIScrollViewKeyboardDismissMode keyboardDismissMode NS_AVAILABLE_IOS(7_0);
該屬性用于標(biāo)識(shí)內(nèi)建的拖動(dòng)手勢(shì)和捏合手勢(shì), 可在此對(duì)其進(jìn)行配置
@property(nonatomic, readonly) UIPanGestureRecognizer *panGestureRecognizer NS_AVAILABLE_IOS(5_0);
@property(nonatomic, readonly) UIPinchGestureRecognizer *pinchGestureRecognizer NS_AVAILABLE_IOS(5_0);
該屬性用于標(biāo)識(shí)內(nèi)建的下拉刷新控件, 可在此實(shí)現(xiàn)下拉刷新功能
@property (nonatomic, strong, nullable) UIRefreshControl *refreshControl NS_AVAILABLE_IOS(10_0);
事件處理實(shí)現(xiàn)原理
由于scrollView并沒(méi)有用于直接操控的滾動(dòng)條, 因此用戶只能通過(guò)直接操作scrollView的內(nèi)容區(qū)域以便進(jìn)行滾動(dòng)操作. 但是當(dāng)用戶觸碰到屏幕上時(shí), scrollView并不清楚該用戶的目的是想要進(jìn)行滾動(dòng)操作還是單純地想要點(diǎn)擊某一個(gè)視圖. 為了處理這種情況, 當(dāng)用戶觸碰屏幕時(shí), scrollView首先攔截到該觸摸事件并啟用一個(gè)150s的定時(shí)器, 同時(shí)觀察用戶的下一步行為.
- 當(dāng)定時(shí)器結(jié)束前, 如果用戶的觸摸點(diǎn)發(fā)生足夠的移動(dòng), 則直接滾動(dòng)內(nèi)容區(qū)域, 并且不會(huì)繼續(xù)將該觸摸事件傳遞給子視圖.
- 當(dāng)定時(shí)器結(jié)束后, 如果用戶的觸摸點(diǎn)并沒(méi)有發(fā)生足夠的移動(dòng), 則調(diào)用
-touchesShouldBegin:withEvent:inContentView:方法詢問(wèn)是否將事件傳遞給對(duì)應(yīng)的子視圖. 如果返回NO, 則該事件不會(huì)傳遞給對(duì)應(yīng)的子視圖; 如果返回YES, 則該事件會(huì)傳遞給對(duì)應(yīng)的子視圖, 默認(rèn)為YES. - 當(dāng)觸摸事件被傳遞給子視圖后, 如果
canCancelContentTouches=YES, 則會(huì)立即調(diào)用-touchesShouldCancelInContentView:方法詢問(wèn)是否可以取消已經(jīng)傳遞給子視圖的事件. 如果返回NO, 則不再進(jìn)一步跟蹤用戶的觸摸事件; 如果返回YES, 則當(dāng)用戶的觸摸點(diǎn)又發(fā)生足夠的移動(dòng)時(shí), 系統(tǒng)會(huì)向該子視圖發(fā)送-touchesCancelled:withEvent:消息并進(jìn)行滑動(dòng).
代理相關(guān)
該方法在contentOffset發(fā)生變化時(shí)調(diào)用
- (void)scrollViewDidScroll:(UIScrollView *)scrollView;
該方法在將要開(kāi)始拖拽時(shí)調(diào)用
注: 該方法可能需要先滑動(dòng)一段時(shí)間或距離才會(huì)被調(diào)用
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;
該方法在用戶停止拖拽時(shí)調(diào)用
注: 應(yīng)用程序可以通過(guò)修改
targetContentOffset參數(shù)的值來(lái)調(diào)整停止的位置
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset NS_AVAILABLE_IOS(5_0);
該方法在用戶停止拖拽時(shí)調(diào)用
注: 如果在停止拖拽后繼續(xù)移動(dòng), 則
decelerate參數(shù)為YES
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
該方法在將要開(kāi)始減速時(shí)調(diào)用
注: 僅當(dāng)停止拖拽后繼續(xù)移動(dòng)時(shí)才會(huì)被調(diào)用
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView;
該方法在已經(jīng)結(jié)束減速時(shí)調(diào)用
注: 僅當(dāng)停止拖拽后繼續(xù)移動(dòng)時(shí)才會(huì)被調(diào)用
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;
該方法用于返回是否允許點(diǎn)擊狀態(tài)欄讓scrollView滑動(dòng)到頂部, 默認(rèn)值為YES
注: 僅當(dāng)
scrollsToTop屬性值為YES時(shí)才調(diào)用
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView;
該方法在scrollView已經(jīng)滑動(dòng)到頂部時(shí)調(diào)用
注: 僅當(dāng)通過(guò)點(diǎn)擊狀態(tài)欄讓
scrollView滑動(dòng)到頂部才調(diào)用
- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView;
該方法在-setContentOffset:animated:/-scrollRectVisible:animated:方法動(dòng)畫(huà)結(jié)束時(shí)調(diào)用
注: 僅當(dāng)
animated設(shè)置為YES時(shí)才調(diào)用
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView;
該方法在縮放比例發(fā)生變化時(shí)調(diào)用
- (void)scrollViewDidZoom:(UIScrollView *)scrollView NS_AVAILABLE_IOS(3_2);
該方法用于返回參與縮放的子視圖
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView;
該方法在將要開(kāi)始縮放時(shí)調(diào)用
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view NS_AVAILABLE_IOS(3_2);
該方法在已經(jīng)結(jié)束縮放時(shí)調(diào)用
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale;
該方法在adjustedContentInset發(fā)生變化時(shí)調(diào)用
- (void)scrollViewDidChangeAdjustedContentInset:(UIScrollView *)scrollView API_AVAILABLE(ios(11.0));