UIScrollView
1.基本使用
- 介绍
当展示的内容较多,超出一个屏幕时,用户可通过滚动手势来查看屏幕以外的内容
普通的UIView不具备滚动功能,不适合显示过多的内容
UIScrollView是一个能够滚动的视图控件,可以用来展示大量的内容,并且可以通过滚动查看所有的内容
举例:手机上的“设置”
- UIScrollView的基本使用
UIScrollView的用法很简单
将需要展示的内容添加到UIScrollView中
设置UIScrollView的contentSize属性,告诉UIScrollView所有内容的尺寸,也就是告诉它滚动的范围(能滚多远,滚到哪里是尽头)
UIScrollView显示内容的小细节
超出UIScrollView边框的内容会被自动隐藏
用户可以用过手势拖动来查看超出边框并被隐藏的内容
- 设置内容尺寸(contentSize)
- 不能滚动的原因
如果UIScrollView无法滚动,可能是以下原因:
没有设置contentSize
注意:scrollEnabled = NO 只是不讓scrollView不能滾動
userInteractionEnabled = NO 是不讓scrollView有任何交互
scrollEnabled = NO
没有接收到触摸事件:userInteractionEnabled = NO
… …
2.常见属性
- 是否有弹簧效果
- 是否总是有弹簧效果
- 作用:下拉刷新,上拉加载
- 是否显示滚动条
- 滚动条的样式
- 滚动条是imageView
- 注意点:不要通过索引去subViews这个数组中去访问scrollView的子控件
- UIScrollView的常见属性
@property(nonatomic) CGPoint contentOffset;
这个属性用来表示UIScrollView滚动的位置
(其实就是内容左上角与scrollView左上角的间距值)
@property(nonatomic) CGSize contentSize;
这个属性用来表示UIScrollView内容的尺寸,滚动范围(能滚多远)
@property(nonatomic) UIEdgeInsets contentInset;
这个属性能够在UIScrollView的4周增加额外的滚动区域,一般用来避免scrollView的内容被其他控件挡住
- UIScrollView的其他属性
@property(nonatomic) BOOL bounces;
设置UIScrollView是否需要弹簧效果
@property(nonatomic,getter=isScrollEnabled) BOOL scrollEnabled;
设置UIScrollView是否能滚动
@property(nonatomic) BOOL showsHorizontalScrollIndicator;
是否显示水平滚动条
@property(nonatomic) BOOL showsVerticalScrollIndicator;
是否显示垂直滚动条
2.設置scrollView的contentSize
self.scrollView.contentSize = image.size;
3.是否有彈簧效果
self.scrollView.bounces = NO;
4.不管你有没有設置contentSize,总是有彈簧效果(下拉刷新)
self.scrollView.alwaysBounceHorizontal = YES;
self.scrollView.alwaysBounceVertical = YES;
5.設置滾動条(默認是YES)
self.scrollView.showsHorizontalScrollIndicator = NO;
self.scrollView.showsVerticalScrollIndicator = NO;
3.偏移量和内边距
- 偏移量的作用
- 偏移量的计算方法
- scrollView左上角和内容左上角的差值
- 上下左右滚动
- 设置内边距
2.設置內容的偏移量
作用1:控制內容滾動的位置
作用2:得知內容滾動的位置
self.scrollView.contentOffset = CGPointMake(200,100);
點击控制器的View會自動調用這個方法
- (void)touchesBegan:(NSSet<UITouch *>*)touches withEvent:(UIEvent *)event{
self.scrollView.contentOffset = CGPointMake(-100,-100);
}
3.設罝內邊距
self.scrollView.contentInset = UIEdgeInsetMake(10,20,30,40);
4.监听scrollView的各种行为
- 代理的介绍
- 監聲方法有兩種,一個是用属性名例如scrollView.delegate = self; 另一種是需要控件継承UIControl,継承用addTarget
- 代码创建scrollView和storyboard创建的区别
- 代码创建要等到真正要显示的时候才会有滚动条
- storyboard创建的一开始就有滚动条
scrollView监听各种行为的3步骤
设置代理
遵守协议
实现相应的代理方法
scrollView的代理方法(监听五个事件)
- 滚动
- 即将拖拽
- 即将停止拖拽
- 已经停止拖拽
- 减速完毕
如何监听scrollView已经停止滚动
- 有2种情况
- 第一种手松开,scrollView就停止滚动
- 第二种,用户停止拖拽,但scrollView由于惯性继续滚动,并且减速
- 有2种情况
scrollView监听各种行为的3步骤:
1.遵守协议
只你聲明UIScrollViewDelegate,就可以實現理面的方法,和調用理面的属性
@interface ViewConteroller ()<UIScrollViewDelegate> //聲明
2.设置代理
scrollView.delegate = self;
3.实现相应的代理方法
當scrollView正在滾動的時候就自動調用這個方法
所以如果你需要監聲那個scrollView就實現這個方法
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
NSLog(@"scrollViewDidScroll---");
}
scrollView的代理方法(监听五个事件):
1. 滚动
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
NSLog(@"scrollViewDidScroll---");
}
2. 即将拖拽
//當scrollView正在滾動時候自動調用這個方法
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
NSLog(@"scrollViewDidScroll---");
}
3. 即将停止拖拽
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{
NSLog(@"scrollViewWillEndDragging");
}
4. 已经停止拖拽
//用戶己經停止拖拽scrollView時調用這個方法
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
NSLog(@"scrollViewDidEndDragging");
}
5. 减速完毕
//scrollView减速完毕會調用,停止滾動
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
NSLog(@"scrollViewDidEndDecelerating");
}
5.代理的注意点
- 任何OC对象都可以作为scrollView的代理,不仅仅是控制器
- 代理一般都是weak
- 代理的一般规律
6.常见控件监听事件
- UIButton
- UISegmentControl
- UISlider
- UITableView
- UITextFlied
1.UIButton
//1.Button 監聲
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
- (void)btnClick:(UIButton *)btn{
NSLog(@"123");
}
2.UISegmentControl
//2.UISegmentedControl 監聲
UISegmentedControl *segmented = [[UISegmentedControl alloc] initWithItems:@[@"123",@"234",@"345"]];
//設置默認選第0個
//segmented.selectedSegmentIndex = 0;
[segmented addTarget:self action:@selector(segmentedClick:) forControlEvents:UIControlEventValueChanged];
segmented.center = CGPointMake(self.view.center.x, 200);
[self.view addSubview:segmented];
- (void)segmentedClick:(UISegmentedControl *)segmented{
NSLog(@"%ld", segmented.selectedSegmentIndex);
}
3.UISlider
4.UITableView
5.UITextFlied(UITextFlied可以用delegate也可以用addTarget)
@interface ViewConteroller ()<UIScrollViewDelegate>
self.textField.delegate = self;
//點击空白結束textField編輯
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self.textField endEditing:YES];
}
//開始編輯
- (void)textFieldDidBeginEditing:(UITextField *)textField{
NSLog(@"開始編輯");
}
//結束編輯
- (void)textFieldDidEndEditing:(UITextField *)textField{
NSLog(@"結束編輯");
}
/**
@param textField textField文字改變會調用這個方法
@param string 用戶輸入的文字
@return YES:允許用戶輸入;NO:禁止用戶輸入
*/
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
if ([string isEqualToString:@"1"]) {
return NO;
}
return YES;
}
7.内容的缩放
- 通过代理告知哪一个控件需要缩放
- 设置缩放的比例
- 监听缩放的过程
- 禁止缩放的弹簧效果
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (nonatomic, weak) UIImageView *imageView;
//做一個圖片的縮放
UIImage *image = [UIImage imageNamed:@"minion"];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
[self.scrollView addSubview:imageView];
//設置contentSize
self.scrollView.contentSize = image.size;
//這里是為了讓scrollView控件返回字控件所定義的
self.imageView = imageView;
//設置縮放的比例
self.scrollView.maximumZoomScale = 2.5;
self.scrollView.minimumZoomScale = 0.5;
}
#pragma mark -
#pragma mark - UIScrollViewDelegate
//返回需要縮放的子控件(scrollView的字控件)
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{
return self.imageView;
}
8.分页功能
- 介绍分页功能
- 添加图片
- 开启分页功能
- 引导页和循环利用的思想(无限滚动)
介绍分页功能
添加图片
开启分页功能
引导页和循环利用的思想(无限滚动)
//分頁
CGFloat scrollViewWith = self.scrollView.frame.size.width;
CGFloat scrollViewHeight = self.scrollView.frame.size.height;
int count = 5;
//1.添加圖片
for (int i = 0; i < count; i++) {
UIImageView *imageView = [[UIImageView alloc] init];
NSString *name = [NSString stringWithFormat:@"img_0%d",i+1];
imageView.image = [UIImage imageNamed:name];
imageView.frame = CGRectMake(i * scrollViewWith, 0, scrollViewWith, scrollViewHeight);
[self.scrollView addSubview:imageView];
}
//2.設置contentSize
self.scrollView.contentSize = CGSizeMake(count * scrollViewWith, 0);
//3.設置分頁功能
self.scrollView.pagingEnabled = YES;
9.显示页码
- 拖入pageControl控件
- 设置总页数和当前页
- 监听scrollView的滚动来改变页码
- 停止滚动才改变页码
- 滚动过程中实时改变页码
- 当只有一页时,隐藏控件
- 自己判断
- hidesForSinglePage
- 禁止与用户交互
- 修改pageControl显示的图片
#import "ViewController.h"
@interface ViewController () <UIScrollViewDelegate>
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (weak, nonatomic) IBOutlet UIPageControl *pageConterol;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//分頁
CGFloat scrollViewWith = self.scrollView.frame.size.width;
CGFloat scrollViewHeight = self.scrollView.frame.size.height;
int count = 5;
//1.添加圖片
for (int i = 0; i < count; i++) {
UIImageView *imageView = [[UIImageView alloc] init];
NSString *name = [NSString stringWithFormat:@"img_0%d",i+1];
imageView.image = [UIImage imageNamed:name];
imageView.frame = CGRectMake(i * scrollViewWith, 0, scrollViewWith, scrollViewHeight);
[self.scrollView addSubview:imageView];
}
//2.設置contentSize
self.scrollView.contentSize = CGSizeMake(count * scrollViewWith, 0);
//3.設置分頁功能
self.scrollView.pagingEnabled = YES;
self.scrollView.delegate = self;
//4.設置总頁數
self.pageConterol.numberOfPages = count;
//5.設置單頁是否顯示
/*方法一:
if (count <= 1 ) {
self.pageConterol.alpha = 0;
self.pageConterol.hidden = YES;
}
*/
//方法二:
self.pageConterol.hidesForSinglePage = YES;
//6.設置page的小點,為圖片的小點
[self.pageConterol setValue:[UIImage imageNamed:@"current"] forKeyPath:@"_currentPageImage"];
[self.pageConterol setValue:[UIImage imageNamed:@"other"] forKeyPath:@"_pageImage"];
}
/*
四舍五入:int(小數 + 0.5)
0.2 ---> 0 int(0.2 + 0.5) = 0.7 -> 0
0.3 ---> 0 int(0.3 + 0.5) = 0.8 -> 0
0.9 ---> 1 int(0.9 + 0.5) = 1.4 -> 1
1.5 ---> 2 int(1.5 + 0.5) = 2 -> 2
(int)(scrollView.contentOffset.x / scrollView.frame.size.width + 0.5)
*/
//分頁方法二:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
//計算頁碼
int page = (scrollView.contentOffset.x / scrollView.frame.size.width + 0.5 );
self.pageConterol.currentPage = page;
}
//分頁方法一:
//scrollview停止迤拽時做些事情
/*
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
if (decelerate == NO) {
//計算頁碼
int page = scrollView.contentOffset.x / scrollView.frame.size.width;
self.pageConterol.currentPage = page;
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
//計算頁碼
int page = scrollView.contentOffset.x / scrollView.frame.size.width;
self.pageConterol.currentPage = page;
}
*/
@end
10.定时器的使用
- 创建定时器
- 停止定时器
- 细节
- 定时器一旦停止工作就不能在使用了
- 修改timer在runloop中的模式
#import "ViewController.h"
@interface ViewController () <UIScrollViewDelegate>
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (weak, nonatomic) IBOutlet UIPageControl *pageConterol;
@property (nonatomic, assign) int count;
@property (nonatomic, weak) NSTimer *timer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//分頁
CGFloat scrollViewWith = self.scrollView.frame.size.width;
CGFloat scrollViewHeight = self.scrollView.frame.size.height;
self.count = 5;
//1.添加圖片
for (int i = 0; i < self.count; i++) {
UIImageView *imageView = [[UIImageView alloc] init];
NSString *name = [NSString stringWithFormat:@"img_0%d",i+1];
imageView.image = [UIImage imageNamed:name];
imageView.frame = CGRectMake(i * scrollViewWith, 0, scrollViewWith, scrollViewHeight);
[self.scrollView addSubview:imageView];
}
//2.設置contentSize
self.scrollView.contentSize = CGSizeMake(self.count * scrollViewWith, 0);
//3.設置分頁功能
self.scrollView.pagingEnabled = YES;
self.scrollView.delegate = self;
//4.設置总頁數
self.pageConterol.numberOfPages = self.count;
//5.設置單頁是否顯示
/*方法一:
if (count <= 1 ) {
self.pageConterol.alpha = 0;
self.pageConterol.hidden = YES;
}
*/
//方法二:
self.pageConterol.hidesForSinglePage = YES;
//6.設置page的小點,為圖片的小點
[self.pageConterol setValue:[UIImage imageNamed:@"current"] forKeyPath:@"_currentPageImage"];
[self.pageConterol setValue:[UIImage imageNamed:@"other"] forKeyPath:@"_pageImage"];
//7.開始定時器
[self startTimer];
}
//定時器的方法
- (void)nextPage{
//計算當前頁
NSInteger page = self.pageConterol.currentPage + 1;
if (page == self.count) {
page = 0;
}
//滾動到下一頁
[self.scrollView setContentOffset:CGPointMake(page * self.scrollView.frame.size.width, 0) animated:YES];
}
#pragma mark -
#pragma mark - 定時器的相關代碼
- (void)startTimer{
self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(nextPage) userInfo:nil repeats:YES];
}
- (void)stopTimer{
[self.timer invalidate];
self.timer = nil;
}
/*
四舍五入:int(小數 + 0.5)
0.2 ---> 0 int(0.2 + 0.5) = 0.7 -> 0
0.3 ---> 0 int(0.3 + 0.5) = 0.8 -> 0
0.9 ---> 1 int(0.9 + 0.5) = 1.4 -> 1
1.5 ---> 2 int(1.5 + 0.5) = 2 -> 2
(int)(scrollView.contentOffset.x / scrollView.frame.size.width + 0.5)
*/
//分頁方法二:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
//計算頁碼
int page = (scrollView.contentOffset.x / scrollView.frame.size.width + 0.5 );
self.pageConterol.currentPage = page;
}
//用戶拖拽,停止定時器
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
[self stopTimer];
}
//用戶己經停止拖拽,開始定時器
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
[self startTimer];
}