iOS 關於Objective-C中UIScrollView的使用總結
前言:由於之前很早寫的關於【iOS 關於UIScrollView的幾點總結】,是從自己的markdown筆記直接拷貝過來後也沒有整理,所以在閱讀上顯得有點亂, 今天花時間重新整理排版了下,方便閱讀。還請見諒這麼久才重新整理。
1、什麼是
UIScrollView
?
- 當手機螢幕需要展示的內容較多超出一個螢幕時,使用者可以通過滾動手勢來檢視螢幕以外的內容。
- 普通的
UIView
不具備滾動的功能,UIScrollView
是一個能夠滾動的檢視控制元件,可以用來展示大量的內容,並且可以通過滾動檢視所有的內容。
2、
UIScrollView
的常見屬性
UIScrollView
- 內容左上角與
ScrollView
左上角的間距值
@property (nonatomic) CGPoint contentOffset;
UIScrollView
內容的尺寸, 滾動範圍
@property (nonatomic) CGSize contentSize;
- 在
UIScrollView
的4周增加額外的滾動區域,一般用來避免ScrollView
的內容被其它控制元件擋住
@property (nonatomic) UIEdgeInsets contentInset;
3、
UIScrollView
各尺寸
4、
UIScrollView
的其他屬性
- 回彈效果
@property (nonatomic) BOOL bounces;
// 取消回彈效果
self.scrollView.bounces = NO;
- 是否能滾動
@property (nonatomic, getter = isScrollEnabled) BOOL scrollEnabled;
- 是否顯示水平滾動條
@property (nonatomic) BOOL showsHorizontalScrollIndicator;
- 是否顯示垂直滾動條
@property (nonatomic) BOOL showsVerticalScrollIndicator;
5、
UIScrollView
的基本使用
- 設定
UIScrollView的contentSize
屬性,告訴UIScrollView
所有內容的尺寸,也就是告訴它滾動的範圍 UIScrollView
使用步驟- 建立
UIScrollView
; - 將需要展示的內容新增到
UIScrollView
中; - 設定
UIScrollView
的滾動範圍(contentSize
)。
- 建立
注意:如果想讓
UIScrollView
進行滾動,必須設定可以滾動的範圍,必須設定可以滾動的範圍一個控制元件沒有設定
frame
,預設x/y
都是0
6、
ScrollView
不能滾動的幾種情況
沒有設定
contentSize
scrollEnabled
屬性 =NO
; // 代表控制元件不可用userInteractionEnabled
屬性 =NO
; // 代表控制元件不能和使用者互動
7、如何去掉滾動條
self.scrollView.showsHorizontalScrollIndicator = NO;
self.scrollView.showsVerticalScrollIndicator = NO;
注意:滾動條也是 scrollValue 的子控制元件的一部分
滾動條可能在子控制元件的前面,也可能在子控制元件的後面
正是因為這個原因,在開發中不推薦使用
subviews
獲取子控制元件的方式當沒有設定
contentSize
情況下,滾動條在其它子控制元件的前面列印,當設定了contentSize
情況下,滾動條在其它子控制元件後面列印,這說明了滾動條的位置是不確定的。
- 設定滾動條的樣式
// default is UIScrollViewIndicatorStyleDefault
@property (nonatomic) UIScrollViewIndicatorStyle indicatorStyle;
- 預設情況下UIScrollView有一個回彈效果
- 只要設定了contentSize就有回彈效果
// 回彈效果
// default YES. if YES, bounces past edge of content and back again
@property (nonatomic) BOOL bounces;
預設如果不設定
contentSize,scrollView
是沒有回彈效果的,可是如果設定了self.scrollView.alwaysbounceVertical = YES & self.scrollView.alwaysBounceHorizontal = YES
的情況下,水平和垂直方向就都有了回彈效果- 一般應用於下拉重新整理功能
設定邊距
contentInset(額外增加的邊距)
@property(nonatomic) UIEdgeInsets contentInset; // default UIEdgeInsetsZero. add additional scroll area around content
設定內容偏移位
contentOffset
(移動的位置是一個臨時的位置,只要輕輕拖拽一下就會回到預設的位置)
計算公式:永遠都是
控制元件的左上角 - 內容的左上角 = 規定的值
// animate at constant velocity to new offset
- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated;
8、UIScrollView代理
如何監聽一個控制元件的變化/狀態
- 首先需要檢視該控制元件的標頭檔案,看它繼承於誰
如果繼承於UIControl,那麼就可以通過addTarget來監聽
如果繼承於UIView,那麼就必須通過代理來監聽
代理作用:
- 當
A
物件想監聽B
物件的變化,那麼可以讓A
成為B
的代理 - 當
B
物件發生一些變化想通知A
物件,那麼可以讓A
成為B
的代理 self
寫在物件方法中就是當前物件的例項物件
- 當
代理協議的規律:
- 定義代理都使用
id
,這樣以後就任意物件都能成為代理(學官方) - 以控制元件的類名開頭,後面加上
delegate
- 代理協議可以寫在
interface()
後面,也可以寫在類擴充套件後面,都是可以的
- 定義代理都使用
代理協議中的方法名的規律:
- 一般以控制元件名稱去掉類字首開頭
代理協議中的方法引數的規律:
誰觸發事件,就將誰傳遞進來
如何監聽
UIScrollView
的變化成為UIScrollView的代理
遵守UIScrollView的協議
實現UIScrollView協議中的方法
只要成為了
UIScrollView
的代理,遵守代理協議,實現協議中的方法,當UIScrollView
放生一些變化的時候,系統就會自動呼叫這些代理方法scrollViewDidScroll:
方法只要UIScrollView
滾動了,系統就會自動呼叫
// 只要UIScrollView滾動就會呼叫
// 系統會自動呼叫這些方法
- (void)scrollViewDidScroll:(UIScrollView *)scrollView; // any offset changes
// 只要使用者準備開始拖拽就會呼叫
// called on start of dragging (may require some time and or distance to move)
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;
// 使用者停止拖拽(已經鬆手)
// 但是並不意味著UIScrollView已經停止滾動了,每次呼叫此方法時,系統都會傳入一個當前是否有慣性的引數(decelerate)
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
// UIScrollView停止減速
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView; // called when scroll view grinds to a halt
8.注意:
如果想在
UIScrollView
停止滾動之後做一些操作,有以下兩種情況:- 沒有慣性:只會呼叫停止拖拽的方法,不會呼叫停止減速的方法
- 有慣性:既會呼叫停止拖拽的方法,也會呼叫停止減速的方法
所以:以後要判斷UIScrollView是否停止滾動,需要同時重寫兩個方法:
- scrollViewDidEndDragging
- scrollViewDidEndDecelerating
// 在開發中如果需要監聽scrollView滾動是否停止可以這樣寫
- (void)scrollViewDidEndDragging:(nonnull UISrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (decelerate == NO) {
[self scrollViewDidEndDecelerating:scrolView];
} else {
}
}
- (void)scrollViewDidEndDecelerating:(nonnull UIScrollView *)scrollView
{
// 在這裡面寫scrollView停止時需要做的事情
NSLog(@"UIScrollView停止滾動了");
}
9.為什麼代理要用 weak
- 任何物件都能成為代理,只要兩者之間遵守了代理協議即可
原因:為了防止迴圈引用
- 控制器-強引用 -> 控制器的
View
-強引用 ->subViews
陣列-強引用 ->UIScrollView
-弱引用 -> 控制器 如果只有一個控制器的情況,程式一啟動就建立的這個控制器是不會被釋放的
(如果它被釋放,它所執行的邏輯肯定不能被執行 )- 只要陣列中儲存了物件,這個陣列就會用強指標指向了這個物件
strong (用於物件, 強指標, 強引用)
weak(用於物件, 一般應用於控制元件/代理)
copy(用於物件, 字串, 主要為了防止外界修改內部的屬性的值)
assign(用於基本資料型別,int/float/double...)
9、
UIScrollView
縮放
- 要想縮放,除了告訴
UIScrollView
要縮放哪一個控制元件以外,還要告訴UIScrollView
最小能縮多小,最大能放多大
- 因為所有的子控制元件都是我們新增進去的,所以要縮放哪一個我們最清楚
- 只要讓控制器成為
UIScrollView
的代理,當UIScrollView
不清楚要縮放哪一個控制元件的時候,UIScrollView
就會呼叫它的代理方法,問問代理到底要縮放哪一個
self.sc.maximumZoomScale = 2.0;
self.sc.minimumZoomScale = 0.5;
2.縮放圖片分為兩步
- 成為代理,通過代理方法告訴
UIScrollView
要縮放哪一個子控制元件 - 設定子控制元件和最小的縮放比
3.想要縮放,必須明確告訴 UIScrollView
要縮放哪一個控制元件,因為 UIScrollView
中可能有很多子控制元件
// 代理方法
// 大部分代理方法是由控制元件名開頭,小部分不是
// 在此方法中告訴UIScrollView要縮放哪一個控制元件
- (UIView *)viewForZoomingInScrollView:(nonnull UISCrollView *)scrollView {
return 需要縮放的圖片
}
// 縮放的過程中呼叫
- (void)scrlooViewDidZoom:(nonnull UIScrollView *)scrolView {
}
// 縮放結束時呼叫
- (void)scrollViewDidEndZooming:(nonnull UIScrollView *)scrollView withView:(nullable UIView *)view atScale:(CGFloat)scale {
}
10、
UIScrollView
- 一個控制元件如果沒有設定
frame
,預設x/y
就是0
- 如果想讓
UIScrollView
進行滾動,必須設定可以滾動的範圍
- 將需要展示的內容新增到
UIScrollView
中 - 設定
UIScrollView
的contentSize
屬性,設定滾動範圍
- 將需要展示的內容新增到
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width + 100, self.scrollView.frame.size.height + 100);
3.注意:scrollView
不能滾動的幾種情況
- 沒有設定contentSize
scrollEnabled
屬性 =NO
(代表控制元件是否可用)userINteractionEnabled
屬性 =NO
(代表控制元件不能和使用者互動,不能響應使用者操作)
11、
UIScrollView
使用步驟
- 建立
UIScrollView
- 將需要展示內容新增到
UISCrollView
中 - 設定
UISCrollView
的滾動範圍(contentSize
)
12、
UIScrollView
圖片輪播器
pagingEnabled
實現分頁的本質,是按照UIScrollView
的寬度或者高度來分頁的.