掌握
UIScrollView的常見屬性
UIScrollView的常用代理方法
UIScrollView的縮放
UIScrollView和UIPageControl的分頁
NSTimer的使用
什么是UIScrollView
移動設(shè)備的屏幕大小是極其有限的,因此直接展示在用戶眼前的內(nèi)容也相當有限當展示的內(nèi)容較多,超出一個屏幕時,用戶可通過滾動手勢來查看屏幕以外的內(nèi)容,普通的UIView不具備滾動功能,不能顯示過多的內(nèi)容,UIScrollView是一個能夠滾動的視圖控件,可以用來展示大量的內(nèi)容,并且可以通過滾動查看所有的內(nèi)容
舉例:手機上的“設(shè)置”、其他示例程序
UIScrollView的基本使用
UIScrollView的用法很簡單
將需要展示的內(nèi)容添加到UIScrollView中
設(shè)置UIScrollView的contentSize屬性,告訴UIScrollView所有內(nèi)容的尺寸,也就是告訴它滾動的范圍(能滾多遠,滾到哪里是盡頭)
UIScrollView的常見屬性
@property(nonatomic) CGSize contentSize; //這個屬性用來表示UIScrollView內(nèi)容的尺寸,滾動范圍(能滾多遠)
@property(nonatomic) CGPoint contentOffset;
(又叫內(nèi)容偏移量:內(nèi)容左上角減去scoreView左上角差的值,用戶只要稍微動一下,圖片就會再次彈回原始的位置)
這個屬性用來表示UIScrollView滾動到的位置
@property(nonatomic) UIEdgeInsets contentInset;
這個屬性能夠在UIScrollView的4周增加額外的滾動區(qū)域(也可以把這個理解成周圍的厚度)
UIScrollView的其他屬性
@property(nonatomic) BOOL bounces; //設(shè)置UIScrollView是否需要彈簧效果
@property(nonatomic,getter=isScrollEnabled) BOOL scrollEnabled; //設(shè)置UIScrollView是否能滾動
@property(nonatomic) BOOL showsHorizontalScrollIndicator; // 是否顯示水平滾動條
3
@property(nonatomic) BOOL showsVerticalScrollIndicator; // 是否顯示垂直滾動條
tracking // 當touch 后還沒有拖動的時候值是YES,否則NO
zoomBouncing //當內(nèi)容放大到最大或者最小的時候值是
YES,否則 NO
zooming // 當正在縮放的時候值是
YES,否則 NO
decelerating // 當滾動后,手指放開但是還在繼續(xù)滾動中。這個時候是
YES,其它時候是 NO
decelerationRate // 設(shè)置手指放開后的減速率
maximumZoomScale // 一個浮點數(shù),表示能放最大的倍數(shù)
minimumZoomScale // 一個浮點數(shù),表示能縮最小的倍數(shù)
pagingEnabled // 當值是YES 會自動滾動到 subview 的邊界。默認是NO
scrollEnabled // 決定是否可以滾動
如果scrollView不是通過storyboard、xib創(chuàng)建,那么一開始的subviews里面沒有子控件這就是和手動創(chuàng)建的最大的區(qū)別
在scoreView里面在水平滾動條和垂直滾動條沒有設(shè)置為NO的情況下,它也算做ScrollView的一部分(在scoreView里面刪除子控件的時候要格外的注意,但是可以把這兩個滾動條給禁止設(shè)置為NO)
意思是需要動畫 但是時間是蘋果自己定義的第一個參數(shù)是你要滾動到的位置 第二個參數(shù)是是否要動畫效果!
[self.scrollView
setContentOffset:CGPointMake(0, self.scrollView.contentOffset.y) animated:YES];
是否有彈簧效果
self.scrollView.bounces= NO;
不管有沒有contentSize,都能擁有彈簧效果(一般適用于下拉刷新功能,上拉刷新)
self.scrollView.alwaysBounceVertical= YES;(彈簧效果)
self.scrollView.alwaysBounceHorizontal= YES;(水平效果可以滾來滾去)
是否要顯示滾動條
self.scrollView.showsHorizontalScrollIndicator= NO;
self.scrollView.showsVerticalScrollIndicator= NO;
self.scrollView.indicatorStyle= UIScrollViewIndicatorStyleWhite;
NSLog(@"%@", self.scrollView.subviews);
[[self.scrollView.subviews firstObject] removeFromSuperview];
/**
UIControlStateNormal;
UIControlStateHighlighted;
UIControlStateDisabled; 禁止狀態(tài)//
只能通過enabled=NO達到這個狀態(tài)
設(shè)置userInteractionEnabled=NO,可以禁止一些事件,比如點擊和拉拽(意思是禁止和用戶交互)
*/
UIScrollView的代理(delegate)
代理三部曲:作用
1.代理一般都是控制器對象
2.代理一般都是id類型 (注意代理是弱指針,如果是強指針會內(nèi)存泄露)
3.代理協(xié)議的格式:控件類名Delegata
4.代理方法:方法名一般都是以控件名開頭,比如UIScrollView的代理方法就是ScrollViewDelegata
5.如何監(jiān)聽控件的行為
通過addTarget(只有繼承自UIControl的控件,才有這個功能)
通過Delegate(只有擁有delagate的屬性的控件,才有這個功能,有的控件兩個功能都有)
(比如讓控制器監(jiān)聽ScoreView的行為)
注意:給其設(shè)置背景色的時候只有運行的時候才能看到
1.設(shè)置scorollView的deledate(代理)為控制器對象
scorollView.deledata = 控制器
2.控制器要遵守協(xié)議 <UIScrollViewDelegata>
3.控制器要實現(xiàn)UIscoreView協(xié)議里面的代理方法
很多時候,我們想在UIScrollView正在滾動 或
滾動到某個位置 或者 停止?jié)L動 時做一些特定的操作
要想完成上述功能,前提條件就是能夠監(jiān)聽到UIScrollView的整個滾動過程
當UIScrollView發(fā)生一系列的滾動操作時, 會自動通知它的代理(delegate)對象,給它的代理發(fā)送相應(yīng)的消息,讓代理得知它的滾動情況
也就是說,要想監(jiān)聽UIScrollView的滾動過程,就必須先給UIScrollView設(shè)置一個代理對象,然后通過代理得知UIScrollView的滾動過程
仔細看這個方法
UIImageView*imageView = [[UIImageView
alloc] initWithImage:[UIImage imageNamed:@"minion"]];
這個方法的意思是通過一張圖片來初始化這個UIImageView,并且UIImageView的尺寸就是圖片的尺寸!
[scrollView addSubview:imageView];
scrollView.contentSize = imageView.frame.size;
設(shè)置代理(監(jiān)聽scrollView的各種行為)
scrollView.delegate =self;
pragma mark - <UIScrollViewDelegate> 代理方法
只要scrollView在滾動,就會調(diào)用這個方法(監(jiān)聽scrollView的滾動)
- (void)scrollViewDidScroll:(UIScrollView
*)scrollView
{
NSLog(@"scrollViewDidScroll");
}
用戶即將開始拖拽scrollView,就會調(diào)用這個方法
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
NSLog(@"scrollViewWillBeginDragging");
}
用戶即將停止拖拽scrollView,就會調(diào)用這個方法
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint
*)targetContentOffset
{
NSLog(@"scrollViewWillEndDragging");
}
scrollView已經(jīng)停止減速,就會調(diào)用這個方法(停止?jié)L動)
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
NSLog(@"scrollView減速完畢,停止?jié)L動,完全靜止");
}
用戶已經(jīng)停止拖拽scrollView,就會調(diào)用這個方法
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (decelerate == NO)
{
NSLog(@"scrollView停止?jié)L動,完全靜止");
}else {
NSLog(@"用戶停止拖拽,但是scrollView由于慣性,會繼續(xù)滾動,并且減速");
}
}
textField的代理方法
/**
當textField的輸入文字發(fā)生改變時,就會調(diào)用這個方法
@param string 用戶當時輸入的文字
(NSRange暫且不要管)@return YES:允許用戶輸入;NO:禁止用戶輸入
*/
- (BOOL)textField:(UITextField
*)textField shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string
{
if ([string isEqualToString:@"0"]) return
NO;
return YES;
}
UIScrollView和delegate的通信
成為delegate的條件
UIScrollView將delegate需要實現(xiàn)的方法都定義在了UIScrollViewDelegate協(xié)議中,因此要想成為UIScrollView的delegate,必須遵守UIScrollViewDelegate協(xié)議,然后實現(xiàn)協(xié)議中相應(yīng)的方法,就可以監(jiān)聽UIScrollView的滾動過程了
UIScrollView和控制器
一般情況下,就設(shè)置UIScrollView所在的控制器 為 UIScrollView的delegate設(shè)置控制器為UIScrollView的delegate有2種方法:
通過代碼(self就是控制器)
self.Edison.delegate = self;
通過storyboard拖線(右擊UIScrollView)
scrollView的代理方法
scrollView 正在滾動的時候調(diào)用 偏移量一直變化
-
(void)scrollViewDidScroll:(UIScrollView
*)scrollView;scrollView正在縮放
-
(void)scrollViewDidZoom:(UIScrollView
*)scrollView開始拖拽的時候調(diào)用
(void)scrollViewWillBeginDragging:(UIScrollView
*)scrollView;
即將停止拖拽的時候調(diào)用
- (void)scrollViewWillEndDragging:(UIScrollView
*)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
NS_AVAILABLE_IOS(5_0);
已經(jīng)停止拖拽調(diào)用
-
(void)scrollViewDidEndDragging:(UIScrollView
*)scrollView willDecelerate:(BOOL)decelerate;scrollView即將開始減速
-
(void)scrollViewWillBeginDecelerating:(UIScrollView
*)scrollView;scrollView 停止減速 停止
-
(void)scrollViewDidEndDecelerating:(UIScrollView
*)scrollView;scrollView 停止?jié)L的的動畫
(void)scrollViewDidEndScrollingAnimation:(UIScrollView
*)scrollView;
在scrollView中 哪些控件是需要縮放的
-
(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView;
scrollView即將開始縮放
-
(void)scrollViewWillBeginZooming:(UIScrollView
*)scrollView withView:(UIView *)view NS_AVAILABLE_IOS(3_2);scrollView結(jié)束縮放
-
(void)scrollViewDidEndZooming:(UIScrollView
*)scrollView withView:(UIView *)view atScale:(CGFloat)scale;scrollView 即將滾動到頂部
-
(BOOL)scrollViewShouldScrollToTop:(UIScrollView
*)scrollView;scrollView 已經(jīng)滾動到頂部
(void)scrollViewDidScrollToTop:(UIScrollView
*)scrollView;
UIScrollView和控制器
縮放實現(xiàn)步驟
跟縮放相關(guān)的其他代理方法
準備開始縮放的時候調(diào)用
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view
正在縮放的時候調(diào)用
- (void)scrollViewDidZoom:(UIScrollView
*)scrollView
核心代碼:設(shè)置內(nèi)容大小
contentSize.height == 0 設(shè)置為0僅僅代表豎直方向上不能滾動
self.scrollView.contentSize= CGSizeMake(count * w, 0);
分頁
每一頁的尺寸都是跟scrollView的frame.size一樣的
self.scrollView.pagingEnabled= YES;
- (void)scrollViewDidScroll:(UIScrollView
*)scrollView
{
--四舍五入為整數(shù)的方法--
(int)(小數(shù)+ 0.5)
0.3 -> (int)(0.3 + 0.5) == 0
0.4 -> (int)(0.4 + 0.5) == 0
1.5 -> (int)(1.5 + 0.5) == 2
0.7 -> (int)(0.7 + 0.5) == 1
小數(shù)加上0.5再轉(zhuǎn)換成整數(shù),這樣頁碼顯示的就是正確的頁數(shù)(仔細想)
int page = (int)(scrollView.contentOffset.x
/ scrollView.frame.size.width + 0.5);
self.pageControl.currentPage= page;
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
int page = scrollView.contentOffset.x / scrollView.frame.size.width;
self.pageControl.currentPage= page;
}
分頁
只要將UIScrollView的pageEnabled屬性設(shè)置為YES,UIScrollView會被分割成多個獨立頁面,里面的內(nèi)容就能進行分頁展示
一般會配合UIPageControl增強分頁效果,UIPageControl常用屬性如下
一共有多少頁
@property(nonatomic)
NSInteger numberOfPages;
當前顯示第幾頁
@property(nonatomic) NSInteger
currentPage;
只有一頁時,是否需要隱藏頁碼指示器
@property(nonatomic)
BOOL hidesForSinglePage;
其他頁碼指示器的顏色
@property(nonatomic,retain) UIColor
*pageIndicatorTintColor;
當前頁碼指示器的顏色
@property(nonatomic,retain) UIColor
*currentPageIndicatorTintColor;
NSTimer
注意:(它現(xiàn)在是弱指針,NSTimer的內(nèi)部會有一個強指針引用著它)
NSTimer叫做“定時器”,它的作用如下
在指定的時間執(zhí)行指定的任務(wù)
每隔一段時間執(zhí)行指定的任務(wù)
調(diào)用下面的方法就會開啟一個定時任務(wù)
(NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget
selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
每隔ti秒,調(diào)用一次aTarget的aSelector方法,yesOr No決定了是否重復執(zhí)行這個任務(wù)
通過invalidate方法可以停止定時器的工作,一旦定時器被停止了,就不能再次執(zhí)行任務(wù)。只能再創(chuàng)建一個新的定時器才能執(zhí)行新的任務(wù)
停止定時器:
- (void)invalidate;
當用戶即將開始拖拽scrollView時,停止定時器
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
[self stopTimer]; 這個stopTimer方法是自己定義的,并不是系統(tǒng)的!
}
當用戶已經(jīng)結(jié)束拖拽scrollView時,開啟定時器
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
[self startTimer]; 這個startTimer方法是自己定義的,并不是系統(tǒng)的!
}
返回一個自動開始執(zhí)行任務(wù)的定時器
self.timer= [NSTimer
scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(nextPage:) userInfo:@"123" repeats:YES];
修改NSTimer在NSRunLoop中的模式:NSRunLoopCommonModes
主線程不管在處理什么操作,都會抽時間處理NSTimer
[[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
*******************************************************************筆記**************************
-
常見屬性
設(shè)置只能在一個方向上滾動
self.scrollView.directionalLockEnabled =YES;
內(nèi)容在scrollView四周的彈簧效果
self.scrollView.bounces = NO;
實現(xiàn)下拉刷新
不管有沒有contentSize 都可以水平 垂直方向的拉
self.scrollView.alwaysBounceVertical =YES;
self.scrollView.alwaysBounceHorizontal =YES;
分頁效果
self.scrollView.pagingEnabled =YES;
UIButton
*btn ;btn.enabled
= NO;btn.userInteractionEnabled
= NO;設(shè)置scrollView能不能滾動
self.scrollView.scrollEnabled =NO;
任何繼承自UIView的子類都能使用以下屬性設(shè)置與用戶是否能交互
self.scrollView.userInteractionEnabled =NO;
滾動條在scrollView的subview中
NSLog(@"------subviews = %@",self.scrollView.subviews);
設(shè)置水平方向的滾動條
self.scrollView.showsHorizontalScrollIndicator =NO;
self.scrollView.showsVerticalScrollIndicator =NO;
subviews中沒有滾動條
NSLog(@"----2--subviews = %@",self.scrollView.subviews);
滾動條的樣式
self.scrollView.indicatorStyle =
UIScrollViewIndicatorStyleBlack;慣性停下來的速度 靠自己的手驗證
self.scrollView.decelerationRate = 0.1f;
-
重點常見屬性
設(shè)置內(nèi)容尺寸
self.scrollView.contentSize =
imageView.image.size;設(shè)置內(nèi)容的偏移量
self.scrollView.contentOffset = CGPointMake(200,
200);內(nèi)邊距
self.scrollView.contentInset =
UIEdgeInsetsMake(20, 30, 40, 50);
3.delegate
代理(assign 弱引用)
面試題:
代理的好處:可以實現(xiàn)監(jiān)聽的思想,假如讓一個對象A監(jiān)聽另一個對象B的狀態(tài),這個時候可以用代理
通知的思想:一個對象B的狀態(tài)發(fā)生了改變(做了某些事情),想通知另一個對象A,這就是通知
- 遵守協(xié)議
- 成為代理
- 實現(xiàn)代理方法
一般:
1. 代理的名稱一般是控件的名稱+ Delegate
UITextFieldDelegate,UITableViewDelegate,UIScrollViewDelegate,UIAlertViewDelegate
2. 代理需要實現(xiàn)的的方法一般都是代理名稱- UI - delegate
- (BOOL)textField:(UITextField
*)textField shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string;
- (void)tableView:(UITableView
*)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)alertView:(UIAlertView
*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex;
3. 成為代理
一般需要在A類中寫代理方法,那么就讓A類成為代理
遵守協(xié)議 - 寫在.h文件中
(如果是需要當前控制器,那么就.m中遵守協(xié)議就可以了)
實現(xiàn)(你需要和必須實現(xiàn)的)代理方法
成為代理
scrollView.delegate(scrollView 的屬性) = self
4.圖片的縮放
- 遵守協(xié)議
- 成為代理
- 實現(xiàn)代理方法
- 在- (UIView *)viewForZoomingInScrollView:(UIScrollView
*)scrollView 返回一個需要縮放的控件
- 設(shè)置scrollView的最大和最小縮放比例
- 用到的代理方法
以下方法中 view 就是正在縮放的控件
scale 縮放比例
- (void)scrollViewWillBeginZooming:(UIScrollView
*)scrollView withView:(UIView *)view
- (void)scrollViewWillBeginZooming:(UIScrollView
*)scrollView withView:(UIView *)view
縮放前:
5.UITextField 的代理方法
- 常見設(shè)置
數(shù)字鍵盤
textField.keyboardType = UIKeyboardTypeNumberPad;
改變鍵盤的右下角return 按鈕的名稱
textField.returnKeyType = UIReturnKeyDone;
-
代理方法
textField : A輸入框發(fā)送改變 就把A輸入框傳入代理方法中 range : 其實就是光標的位置 長度就是代表需要替換哪些字符串 string : 輸入的是什么就是什么
- (BOOL)textField:(UITextField
*)textField shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string
- 圖片輪播器
- 往scrollView 中添加imageView (5個),imageView的尺寸保持根scrollView的尺寸一致
- 設(shè)置分頁pagingEnabled = YES
- pageControl 在storyboard中
根 scrollView 同級
- 設(shè)置pageControl的一些屬性 numberOfPages currentPage...
- 在scrollViewDidScroll代理方法中設(shè)置currentPage
使用x偏移量/ scrollView的寬度+ 0.5 "記得打印偏移量"
6.
nextPage
1. 獲取pageControl的當前頁+ 1 (跳到下一個) = index
2. 判斷index 是不是為5 (如果是 index = 0)(循環(huán)切換)
3. 設(shè)置偏移量(使用偏移量切換到下一個imageView)
index *width(scrollView)
- 定時器
- performSector
- NSTimer
self.timer = [NSTimer
scheduledTimerWithTimeInterval:2.0f target:self
selector:@selector(nextPage:) userInfo:@"ceshi" repeats:YES];
timer是一次性, 用了就不能再用了
3. 添加timer到主線程
[[NSRunLoop mainRunLoop] addTimer:self.timer
forMode:NSRunLoopCommonModes];
效果展示:
- 封裝圖片輪播器
- 類方法加載xib
- 先把awakeFromNib
1. pageControl的一次性操作
- 重寫圖片數(shù)組set方法
將控制器中viewDidLoad里面所有的代碼除了pageControl的一次性操作
- copy控制器中所有的方法
- 將報錯的地方補上
- 使用scrollView做購物車
- 設(shè)置contentSize
拿出scrollView中的最后一個控件
算出這個空間的bottom = (控件的高+ 控件的y)
bottom 就是contentSize 的height
- 設(shè)置contentOffset
首先判斷最后一個控件的bottom 是不是比scrollView的高度大
如果大設(shè)置偏移量height 就 = bottom