1.不能向上滑动很可能是因为contentSize的大小不对。
scrollView的几个属性contentSize contentOffset contentInset
contentSize是scrollview可以滚动的区域,比如frame = (0 ,0 ,320 ,480) contentSize = (320 ,960),代表你的scrollview可以上下滚动,滚动区域为frame大小的两倍。 contentOffset是scrollview当前显示区域顶点相对于frame顶点的偏移量,比如上个例子你拉到最下面,contentoffset就是(0 ,480),也就是y偏移了480 contentInset是scrollview的contentview的顶点相对于scrollview的位置,例如你的contentInset = (0 ,100),那么你的contentview就是从scrollview的(0 ,100)开始显示
另外UITableView是UIScrollView的子类,它们在上述属性又有所不同,tabelview的contentsize是由它的下列方法共同实 现的 它会自动计算所有的高度和来做为它的contentsize的height.
例如你在delegate方法 那么你的tabelview的contentsize就是(320, 4400) |
UIScrollView 滚动视图 (实例)
- 博客分类:
- Phone / IOS / Objective-C / Swift
UIScrollView 类负责所有基于 UIKit 的滚动操作。
一、创建
1. CGRect bounds = [ [ UIScreen mainScreen ] applicationFrame ] ;
2. UIScrollView* scrollView = [ [UIScrollView alloc ] initWithFrame:bounds ];
或者
1. UIScrollView *scrollView =[[UIScrollView alloc] initWithFrame:CGRectMake(0.0, 0.0,self.view.frame.size.width, 400)];
当你创建完滚动视图后,你可以将另一个视图的内容粘合到滚动视图的空白页上。这回创建一个滚动的内容窗口:
1. [ scrollView addSubview:myView];
你必须给出内容的实际大小,这样滚动视图才知道滚动的范围:
1. scrollView.contentSize = myView.frame.size;
要开启缩放功能需要调整视图的两个属性,分别是maxinumZoomScale 和 mininumZoomScale 。这样就可以允许用户使用捏合手势调整内容大小:
1. scrollView.maxinumZoomScale = 2.0;//允许放大2倍
2. scrollView.mininumZoomScale = 0.5;//允许放大到0.5倍
要打开缩放功能,你还需要增加一个UIScrollViewDelegate 代理,通过一个名为viewForZoomingScrollView 的方法做出响应。这个方法会返回进行缩放时所使用的 UIView 对象:
1. scrollView.delegate = self;
2. - (UIView*)viewForZoomingInScrollView:(UIScrollView*)scrollView{
3. retutn myView;
4. }
Tips:对于大规模数据,你可能会在最初使用一个低于实际大小(1.0)的缩放比例,让用户可以平滑地进行放大。
1. scrollView.pagingEnabled = YES;
2. scrollView.backgroundColor = [UIColor blueColor];
3. scrollView.showsVerticalScrollIndicator = NO;
4. scrollView。showsHorizontalScrollIndicator = NO;
5. scrollView.delegate = self;
6. CGSize newSize = CGSizeMake(self.view.frame.size.width * 2, self.view.frame.size.height);
7. [scrollView setContentSize:newSize];
8. [self.view addSubview: scrollView];
二、属性
除了上面用到的缩放属性外,滚动视图还有会让你多其他属性,可以对现实内容的行为进行微调。你可以对 UIScrollView 类进行多方位定制。下面这些属性是最常用的。
1.indicatorStyle
指定你希望使用的滚动条指示器的类型。默认行为是在白边界上绘制黑色的滚动条,这在大多数背景下都适用。可用风格如下:
1. UIScrollViewIndicatorStyleDefault
2. UIScrollViewIndicatorStyleBlack
3. UIScrollViewIndicatorStyleWhite
2.contentOffset
一个CGPoint结构,其中包含有要显示内容相对于窗口左上角的偏移量。默认是从0×0开始的,但是你也可以将显示内容放在其他位置。
3.directionalLockEnabled
默认行为是允许用户同时进行横向和纵向的滚动。将这个属性设置为YES会导致将用户的滚动行为锁定成只允许横向或纵向进行,具体方向由初始姿态决定。
4.bounces
当用户抵达滚动区域边缘时,这个功能允许用户稍微拖动到边界外一点。当用户松开手指后,这个区域会像个橡皮筋一样,弹回到原位,给用户一个可见的提示,表示他已经到达了文档开始或结束位置。如果不想让用户的滚动范围能够超出可见内容,可以将这个属性设置为NO。
5.bouncesZoom
类似于bounces 选项,这个方法可以令用户的缩放操作超出最大或最小缩放级别,然后弹回到范围以内。如果你不想让用户能够超出你指定的范围进行缩放,将这个属性设置为NO。
6.pagingEnabled (参考:UIPageControl 分页控件-IOS开发)
当开启了分页功能时,滚动视图被分割成多个独立区段,二用户的滚动体验则变成了页面翻转,你可以用这个属性来进行页面翻转。
UIPageControl有一个userInteractionEnabled你可以设置它为NO。就是点击的时候它不调用任何方法。然后设置它的currentPage 为0,并把它加到view上去。
接下来在UIScrollView的delegate方法:
1. - (void)scrollViewDidScroll:(UIScrollView *)scrollView;
在这里你可以写上关于UIPageControl的页面设置的算法。如下
1. int index = fabs(scrollView.contentOffset.x) /scrollView.frame.size.width;
2. pageControl.currentPage = index;
三、委托方法
可以赋予滚动视图一个委托,下列委托方法会在特定时刻收到通知。
1. -(void)scrollViewDidScroll:(UIScrollView*)scrollView;//会在视图滚动时收到通知。包括一个指向被滚动视图的指针,从中可以读取contentOffset属性
以确定其滚动到的位置。
1. -(void)scrollViewWillBeginDragging:(UISCrollView*)scrollView;//当用户首次在某个方向上进行拖动时得到通知。这个方法会
得到被作为参数传递的滚动视图指针,也同样可以从中读取 contentOffset 属性。
1. -(void)scrollViewDidEndDragging:(UIScrollView*)scrollView willDecelerate:(BOOL)decelerate;
2. //当用户抬起拖动到手指时得到通知。还会得到一个布尔值,知名报告滚动视图最后位置之前,是否需要减速。
1. -(void)scrollViewWillBeginDecelerate:(UIScrollView*)scrollView;//当用户抬起手指而视图需要继续移动时,会收到通知。这
个方法可以用来读取 contentOffset属性,从而判断出当用户抬起手指钱最后一次滚动到的位置,虽然这个位置并不会使滚动条的最终
停止位置。
1. -(void)scrollViewDidEndDecelerating:(UIScrollView*)scrollView;//当上面提到的减速完毕、滚动视图停止时得到通知。收到这个通知的时刻,滚动视图的contentOffset属性会反映出滚动条最终停止的位置。
1. -(void)scrollViewDidEndZooming:(UIScrollview*)scrollView withView:(UIView*)view atScale:(float)scale;//当用户对内容进行缩放时,会收到通知。缩放比例表示为一个浮点值,会作为参数传递进来。
1. -(BOOL)scrollViewShouldScrollToTop:(UIScrollView*)scrollView;
2. -(void)scrollViewDidScrollToTop:(UIScrollView*)scrollView;
1. //当用户点出iPhone状态条时,滚动视图委托可以决定视图是否滚动回到开头。
OK,都总结完了,后面会写一个页面翻转的例子敬请关注。
实例:
viewcontroller.h
1. #import <UIKit/UIKit.h>
2.
3. @interface ViewController : UIViewController
4. {
5. __weak IBOutlet UIScrollView *scroller;
6. }
7.
8. @end
viewcontroller.m
1. - (void)viewDidLoad
2. {
3. [scroller setScrollEnabled:YES];
4. [scroller setContentSize:CGSizeMake(320, 1600)];
5.
6. [super viewDidLoad];
7. // Do any additional setup after loading the view, typically from a nib.
8. }
9.
10. - (void)viewDidUnload
11. {
12.
13. scroller = nil;
14. [super viewDidUnload];
15. // Release any retained subviews of the main view.
16. // e.g. self.myOutlet = nil;
17. }
拖拽scrollview视图到Fist Responder.
1. XIB文件的理解
通过IB设计的CnView和EnView分别对应一个XIB文件,在CnView的XIB文件中,主要采用XML格式描述了Button和Label控件的属性(这里不考虑View本身的背景等属性),有个Button和Label,以及Button和Label的位置、大小等。EnView的XIB文件类似。
2. ViewController
每个View对应有个视图控制器(多个View可以采用同一个视图控制器,后边再说),可以看做MVC中的C(尽管严格意义上不是),比如:CnView界面点击按钮之后的响应动作是由ViewController来实现的。
3. XIB和ViewController之间的关系
XIB是表现,ViewController一方面响应XIB上的操作(比如点击、滑动等),同时也控制XIB的显示。
4. File's Owner
重点就是这里了,View和ViewController之间的对应关系,需要一个桥梁来进行连接的(即,对于一个视图,他如何知道自己的界面的操作应该由谁来响应),这个桥梁就是File's Owner。
选中某个XIB的File's Owner,在Inspector中可以看到属性:File Name和Custom Class,该File's Owner就是用来绑定File Name中的xib文件和Custom Class中的ViewController的,在做了这个绑定之后,按住control键,拖动File's Owner到xib中的某个控件的时候,就是Custom Class中定义的IBOutlet元素与xib中元素进行连接的过程,同样,拖动"xib中的控件的动作"到File's Owner的时候,就是将xib中该动作的响应与Custom Class中某个IBAction进行连接的过程。
因此,在存在多个xib文件的情况下,即:有多个View,那么每个View可以采用不同的ViewController,也可以全部采用相同的一个ViewController,通过File's Owner进行关联即可。
其实,File's Owner就是Custom Class类型的对象,而xib中的其他元素都是该对象的成员变量,但是需要手动来关联Custom Class中的成员变量与xib中对象之间的关系。
5. First Responder
View中每次只会有一个对象与用户进行交互,那么当前交互的对象即为First Responder。比如点击文本框,那么此时文本框就是First Responder
6. IB中的File's Owner是一个对象,拥有界面元素的拷贝
一个是IBOutlet :指界面元素在代码中的’代号‘
一个是IBAction:指界面元素产生事件在代码中的触发函数
- UIScrollView的属性总结
属性 | 作用 |
CGPoint contentOffSet | 监控目前滚动的位置 |
CGSize contentSize | 滚动范围的大小 |
UIEdgeInsets contentInset | 视图在scrollView中的位置 |
id<UIScrollerViewDelegate> delegate | 设置协议 |
BOOL directionalLockEnabled | 指定控件是否只能在一个方向上滚动 |
BOOL bounces | 控制控件遇到边框是否反弹 |
BOOL alwaysBounceVertical | 控制垂直方向遇到边框是否反弹 |
BOOL alwaysBounceHorizontal | 控制水平方向遇到边框是否反弹 |
BOOL pagingEnabled | 控制控件是否整页翻动 |
BOOL scrollEnabled | 控制控件是否能滚动 |
BOOL showsHorizontalScrollIndicator | 控制是否显示水平方向的滚动条 |
BOOL showsVerticalScrollIndicator | 控制是否显示垂直方向的滚动条 |
UIEdgeInsets scrollIndicatorInsets | 指定滚动条在scrollerView中的位置 |
UIScrollViewIndicatorStyle indicatorStyle | 设定滚动条的样式 |
float decelerationRate | 改变scrollerView的减速点位置 |
BOOL tracking | 监控当前目标是否正在被跟踪 |
BOOL dragging | 监控当前目标是否正在被拖拽 |
BOOL decelerating | 监控当前目标是否正在减速 |
BOOL delaysContentTouches | 控制视图是否延时调用开始滚动的方法 |
BOOL canCancelContentTouches | 控制控件是否接触取消touch的事件 |
float minimumZoomScale | 缩小的最小比例 |
float maximumZoomScale | 放大的最大比例 |
float zoomScale | 设置变化比例 |
BOOL bouncesZoom | 控制缩放的时候是否会反弹 |
BOOL zooming | 判断控件的大小是否正在改变 |
BOOL zoomBouncing | 判断是否正在进行缩放反弹 |
BOOL scrollsToTop | 控制控件滚动到顶部 |
这里把UIScrollView的几个要点总结下:
从你的手指touch屏幕开始,scrollView开始一个timer,如果:
1. 150ms内如果你的手指没有任何动作,消息就会传给subView。
2. 150ms内手指有明显的滑动(一个swipe动作),scrollView就会滚动,消息不会传给subView,这里就是产生问题二的原因。
3. 150ms内手指没有滑动,scrollView将消息传给subView,但是之后手指开始滑动,scrollView传送touchesCancelled消息给subView,然后开始滚动。
观察下tableView的情况,你先按住一个cell,cell开始高亮,手不要放开,开始滑动,tableView开始滚动,高亮取消。
delaysContentTouches的作用:
这个标志默认是YES,使用上面的150ms的timer,如果设置为NO,touch事件立即传递给subView,不会有150ms的等待。
cancelsTouches的作用:
这个标准默认为YES,如果设置为NO,这消息一旦传递给subView,这scroll事件不会再发生。
-
2 -
3
分步阅读
UIScrollView可以用于显示多于一个屏幕的内容,超出屏幕范围的内容可以通过滑动进行查看
方法/步骤
- 常见属性
CGSize contentSize :设置UIScrollView的滚动范围
CGPoint contentOffset :UIScrollView当前滚动的位置
UIEdgeInsets contentInset :这个属性可以在四周增加滚动范围
- 2
其他属性
BOOL bounces 是否有弹簧效果
BOOL scrollEnabled 是否能滚动
BOOL showsHorizontalScrollIndicator 是否显示水平方向的滚动条
BOOL showsVerticalScrollIndicator 是否显示垂直方向的滚动条
UIScrollViewIndicatorStyle indicatorStyle 设定滚动条的样式
BOOL dragging 是否正在被拖拽
BOOL tracking 当touch后还没有拖动的时候值是YES,否则NO
BOOL decelerating 是否正在减速
BOOL zooming 是否正在缩放 - 3
手势缩放
设置UIScrollView的id<UISCrollViewDelegate> delegate代理对象
设置minimumZoomScale :缩小的最小比例
设置maximumZoomScale :放大的最大比例
让代理对象实现下面的方法,返回需要缩放的视图控件
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
跟缩放相关的常用方法还有
正在缩放的时候调用
-(void)scrollViewDidZoom:(UIScrollView *)scrollView
缩放完毕的时候调用
-(void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
- 4分页效果设置pagingEnabled=YES即可,UIScrollView会被分割成多个独立页面,用户的滚动体验则变成了页面翻转一般会配合UIPageControl增强分页效果,UIPageControl常用属性:NSInteger numberOfPages : 总页数NSInteger currentPage : 当前的页码BOOL hidesForSinglePage : 当只有一页的时候,是否要隐藏视图监听UIPageControl的页面改变:
1. // 添加监听器
[pageControl addTarget:self action:@selector(pageChange:)
forControlEvents:UIControlEventValueChanged];
// 监听方法
- (void)pageChange:(UIPageControl *)pageControl
{
}
- 5图片全屏浏览
5. //1,创建滚动视图 设置大小
self.scroView = [[[UIScrollView alloc] initWithFrame:CGRectMake(10, 20, 300, 350)] autorelease];
CGFloat scro_w = _scroView.bounds.size.width; //每张图片滚动视图的宽
CGFloat scro_h = _scroView.bounds.size.height;//每张图片滚动视图的高
//2,添加
[self addSubview:_scroView];
//3,背景
_scroView.backgroundColor = [UIColor cyanColor];
//4,设置内容视图大小 滚动视图整体范围
_scroView.contentSize = CGSizeMake( scro_w*8, 0);
//5,添加图片
for (int i = 0; i < 8; i++) {
UIImageView *imageView = [[UIImageView alloc] init];
//5.1 设置frame
imageView.frame = CGRectMake(i * scro_w, 0, scro_w, scro_h);
//5.2 设置图片
NSString *imgName = [NSString stringWithFormat:@"0%d.jpg", i + 1];
imageView.image = [UIImage imageNamed:imgName];
//5.3 添加图片
[_scroView addSubview:imageView];
[imageView release];
}
//6.设置属性
_scroView.pagingEnabled = YES; //翻页
_scroView.showsHorizontalScrollIndicator = NO;//控制是否显示水平方向的滚动条
_scroView.bounces = NO;//弹动效果
// 缩放倍数
_scroView.maximumZoomScale = 2.0f;
_scroView.minimumZoomScale = 0.5f;
// 添加PageControl
_pageControl = [[UIPageControl alloc] init];
_pageControl.center = CGPointMake(scro_w * 0.5, scro_h - 20);
_pageControl.bounds = CGRectMake(0, 0, 250, 50);//自身大小
_pageControl.numberOfPages = 8; // 一共显示多少个圆点(多少页)
// 设置非选中页的圆点颜色
_pageControl.pageIndicatorTintColor = [UIColor cyanColor];
// 设置选中页的圆点颜色
_pageControl.currentPageIndicatorTintColor = [UIColor redColor];
// 点击功能(可点击)
_pageControl.enabled = YES;
//添加到当前视图
[self addSubview:_pageControl];
//添加进入按钮
self.enterButton = [UIButton buttonWithType:UIButtonTypeSystem];
[_enterButton setTitle:@"进入" forState:UIControlStateNormal];
_enterButton.frame = CGRectMake((self.bounds.size.width - 100)/2, self.bounds.size.height - 70, 100,35);
_enterButton.backgroundColor = [UIColor cyanColor];
[self addSubview:_enterButton];
_enterButton.enabled = YES;
}
- (void)loadView
{
self.rootView = [[[RootView alloc] initWithFrame:[UIScreen mainScreen].bounds ] autorelease];
self.view = _rootView;//赋值
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor blackColor];
//设置滚动视图代理
_rootView.scroView.delegate = self;
//给pagecontrol添加点击事件
[_rootView.pageControl addTarget:self action:@selector(pageControlAction:) forControlEvents:UIControlEventValueChanged];
//让按钮初始隐藏
_rootView.enterButton.hidden = YES;
//给按钮绑定事件
[_rootView.enterButton addTarget:self action:@selector(enterButtonAction:) forControlEvents:UIControlEventTouchUpInside];
}
//处理按钮点击事件
- (void)enterButtonAction:(UIButton *)sender
{
HomeViewController *homeVC = [[HomeViewController alloc] init];
homeVC.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
//模态跳转
[self presentViewController:homeVC animated:YES completion:nil];
[homeVC release];
//保存已经进入状态
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"kNoFirstEnterFlag"];
[[NSUserDefaults standardUserDefaults] synchronize];//及时同步保存
}
//处理pageControl点击事件
- (void)pageControlAction:(UIPageControl *)sender
{
//1,获取当前页面
NSInteger currentPage = sender.currentPage;
//2,计算偏移量
NSInteger scrollWith = _rootView.scroView.bounds.size.width;//滚动视图宽度
CGPoint offsetPoint = CGPointMake(currentPage * scrollWith ,0);
//3,将偏移量赋值给scrollView 。设置当前偏移量
[_rootView.scroView setContentOffset:offsetPoint animated:YES];
}
#pragma mark - 代理方法
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
NSLog(@"正在滑动《触发 处理》");
int page = _rootView.scroView.contentOffset.x / _rootView.scroView.frame.size.width ;
NSLog(@"ye %d",page);
_rootView.pageControl.currentPage = page;
//判断是否进入
if ( page == 7) {
_rootView.enterButton.hidden = NO;
}else{
_rootView.enterButton.hidden = YES;
}
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
NSLog(@"开始拖拽");
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
NSLog(@"结束拖拽");
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
NSLog(@"结束自由滚动(停止了)");
}
#pragma mark - 缩放代理
//缩放对象
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
//将要缩放的对象返回
return _rootView.scroView.subviews[0];
}
//缩放完成
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale
{
NSLog(@"%@",view);
NSLog(@"%.2f",scale);
}