第五天,uiscorllview的滚动和缩放,以及代理调用,定时器,对话框

来源:互联网 发布:知乎阿里云免费开通码 编辑:程序博客网 时间:2024/06/05 12:43

 

1.UIScrollView使用

- UIScrollView 介绍

  1> UIScrollView是一种控件,继承自UIView

  2> 用来实现”滚动”和”缩放”的控件

 

- UIScrollView设置滚动的基本步骤(进行滚动和缩放的是内容)

   1>创建一个UIScrollView

   2>向UIScrollView中添加内容(UIimageView)

   3>设置UIScrollView的内容的大小(contentSize)

 

- UIScrollView实现图片滚动(参考案例:大图片展示)

    1>拖一个 UIScrollView 到屏幕

   2> 拖一个 UIImageView 到 UIScrollView 中

   3> 设置 UIImageView 的显示图片, 并根据实际设置的图片的大小修改 UIImageView 的大小

   4> 在控制器的 viewDidLoad 方法中, 设置 UIScrollView 的 contentSize 为图片的实际大小(UIImageView的 Image 属性的 size)

 

- UIScrollView无法滚动可能的原因及解决办法分析

* 没有设置contentSize

*scrollEnabled = NO

* 没有接收到触摸事件:userInteractionEnabled = NO

* 没有取消autolayout功能等原因

 

- UIScrollView frame.size contentSize 的区别

*frame.size指的是: UIScrollView的可视区域的大小, UIScrollView本身的大小

*contentSize指的是: UIScrollView中所包含的内容的大小(要滚动的实际内容的大小)

* 总结: 在UIScrollView的frame.size这么大的范围内, 要显示contentSize这么大的内容。是否需要滚动, 取决于contentSize是否比frame.size大

 

- UIScrollView常见属性

*contentSize (内容尺寸)

 

*contentOffset(内容偏移量,CGPoint类型)

含义:

1>当UIScrollView内部的内容滚动时, 内容相对于UIScrollView左上角的偏移

2>另一种理解方式: 内容滚动到了什么位置

 

** 注意: 可以通过代码来设置这个属性的值, 就相当于是通过代码实现滚动了(无需用户手指来触摸滚动)

 

* contentInset(内容的内边距,UIEdgeInset类型

含义:

1>设置UIScrollView的内容在拖动以后, 内容距离UIScrollView的内边距。(联想按钮的内边距属性:Inset)

2>另一种思考方式: 想象成把内容加大了, 在内容本身的周围加了一圈”外边距”。

 

- UIScrollView 其他属性

@property(nonatomic) BOOL bounces;

设置UIScrollView是否需要弹簧效果

 

@property(nonatomic,getter=isScrollEnabled)BOOL scrollEnabled;

设置UIScrollView是否能滚动

 

@property(nonatomic)BOOL showsHorizontalScrollIndicator;

是否显示水平滚动条

 

@property(nonatomic)BOOL showsVerticalScrollIndicator;

是否显示垂直滚动条

 

 

-监听控件的事件方法:

   *  1>通过addTarget:的方式来监听事件(前提是这个控件是继承自UIControl)

   *  2>通过代理的方式来监听事件

 * 3> 通知

- 代理设计模式在 UIScrollView中的应用

* 通过代理来监听事件

* 设置代理可以通过"拖线"的方式或者是代码的方式

 

- 通过"代码""拖线"的方式设置代理

     *  设置代理的基本步骤:

    *  1. scroll view设置delegate属性(设置代理对象)

    *  2. 让代理对象遵守代理协议

    *  3. 让代理对象,实现协议中的方法

 

 

 

- UIScrollView常用代理方法

// 用户开始拖拽时调用

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;

 

// 滚动到某个位置时调用

- (void)scrollViewDidScroll:(UIScrollView *)scrollView;

 

// 用户结束拖拽时调用

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollViewwillDecelerate:(BOOL)decelerate;

 

// 用户使用捏合手势时调用

-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView;

 

即将开始缩放的时候调用

- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollViewwithView:(UIView *)view

 

正在缩放的时候调用

(void)scrollViewDidZoom:(UIScrollView *)scrollView

 

缩放完毕的时候调用

- (void)scrollViewDidEndZooming::(UIScrollView *)scrollView

 

- 代理设计模式的总结(UIAlertViewUIActionSheetUIScrollView都是通过代理来监听事件的)

 

- 通过 UIScrollView 实现多个子控件的滚动

* 参考案例:喜马拉雅

1> 拖拽一个UIScrollView到控制器view, 设置该UIScrollView大小与控制器view一致;

2> 设置该UIScrollView的背景色为浅灰色;

3> 向UIScrollView中增加内容;

4> 设置UIScrollView的contentSize的height为最下面的图片的最大的Y值再加间距, width为0(因为横向不滚动);

** 注意:某个方向上不希望滚动,则把该方向上的contentSize的值设置为0

5> 向控制器的view中添加一个UIView到最上方, 模拟"导航栏"(x = 0, y = 0, w = self.view.frame.size.width, h =64)

** 这直接拖拽会把这个UIView拽到UIScrollView,这样就会让UIView随着UIScrollView进行滚动,所以需要调整层级为UIScrollView的同层级。

6> 设置顶部"导航栏"(64高) 与 底部 "菜单栏"(49高)的alpha = 0.6 (设置透明度);

7> 设置contentInset属性的top和bottom的值, 在滚动后预留一定的内边距

** 注意:获取某个控件的最大的Y:CGRectGetMaxY(self.lastButton.frame)加边距;

8> 设置一开始就滚动到y 为某个值的位置, 通过contentOffset属性实现

** 注意这里要把y值设置为负数,向上滚动

** 该案例的主要目的:

1> 了解UIScrollView的基本使用

2> 深入了解contentSize、contentInset、contentOffset属性的作用和含义

 

 

-  图片轮播器

1、整体思路:

1>添加 UIScrollView

2>动态向 UIScrollView 中添加图片框(横向)

3>设置 UIScrollView 的 contentSize 实现滚动, 实现横向滚动

4>实现分页

5>实现分页指示器 UIPageControl

   2、具体步骤:

1>创建一个UIScrollView, 设置宽为300, 高为130 (与每张图片的大小一致)

2>向UIScrollView中添加内容(要滚动的内容, 添加到UIScrollView的子控件集合中)

循环添加5个UIImageView, 设置图片, 设置 frame

3>设置UIScrollView的contentSize的width为5个图片的总大小, 上下不滚动所以height为0

4>去掉水平滚动条

self.scrollView.showsHorizontalScrollIndicator= NO;

5>实现自动分页

self.scrollView.pagingEnabled= YES;

问题: 设置完pagingEnabled = YES以后,scrollView是怎么知道该如何分页的?

答: 按照UIScrollView自身的宽度来实现分页的.UIScrollView的宽度就是每页的大小。

 

6>显示分页指示器

1) 通过UIPageControl来实现

2) 拽一个UIPageControl放到控制器的view中, 不要放到UIScrollView中, 否则就一起滚动了.

3) 设置UIPageControl的Tint Color(其他页颜色)和Current Page(当前页颜色)属性颜色

 

注意: 当把UIPageControl添加到控制器的view中的时候, 这个控件和UIScrollView根本没有任何联系, 所以没有分页指示功能

 

7>实现分页指示器总页数、当前页。

总页数: numberOfPages属性

self.pageControl.numberOfPages= imageCount;

当前页: currentPage属性

self.pageControl.currentPage= 0;

 

注意:

在 viewDidLoad 中设置总页数

在- (void)scrollViewDidScroll:代理方法中设置当前页

设置当前页的思路:

通过当前的滚动的偏移值来计算出当前滚动到第几页了

 

8>通过定时器(NSTimer)实现自动滚动

在 viewDidLoad 中启动定时器

启动定时器的两种方法:

1) 调用timerWithXxx创建的timer,把这个timer对象手动加到”消息循环”中才能启动

2) 调用scheduledTimerWithXxx创建的timer,自动启动(创建完毕后自动启动)。

 

9>在定时器的方法中实现滚动, 代码参考备注。

思路1:

1) 通过 UIPageControl 获取当前页数, 并让页数+1

2) 根据加1以后的页数乘以每页的宽度(每张图片宽度)计算出contentOffset.x 的偏移值

3) 手动设置偏移值, 实现滚动 (通过动画方式设置).

 

10>解决Bug

Bug:当拖拽UIScrollView的时候, 保持一段时间不松手的时候, 一旦松手UIScrollView会连续滚动多次。

解决思路:在即将拖拽的时候, 停止计时器, 拖拽完毕后再打开一个计时器。

 

**停止计时器:调用 NSTimer 对象的 invalidate 方法(当某个计时器被停止以后, 就无法再重用了, 下次必须再重新创建一个新的计时器)。[self.timer invalidate];

 

11>解决Bug

Bug:当单击(拖拽)界面上的某个其他控件的时候, UIScrollView停止滚动的问题。

产生 Bug 的原因:

当前处理UI界面的只有一个线程, 当这个线程处理UI的拖动事件的时候就没有能力再去处理滚动操作了

注意: 处理UI界面的的只能是一个线程。所以, 处理UIScrollView的滚动和其他控件的拖拽, 只能用同一个线程。如果多个线程都可以操作 UI 那么就会造成混乱的问题

解决思路: 提高处理滚动的timer的优先级。

注意: 所有控件的默认优先级都是NSRunLoopCommonModes ,但是网络和计时器对象默认的优先级要比控件的优先级低是NSDefaultRunLoopMode , 所以这里要把计时器的优先级调整为与控件一样的优先级NSRunLoopCommonModes。

 

- NSTimer计时器控件/通过使用 Nstimer实现自动滚动

两种不同的定时器

1> NSTimer(时间间隔比较大1秒,几秒)

2> CADisplayLink(时间间隔比较小,0.0几秒等)

创建、启动定时器代码参考:

// 方式一

[NSTimer scheduledTimerWithTimeInterval:0.5target:self selector:@selector(nextImage) userInfo:nil repeats:YES];

 

// 方式二

// 创建 NSTimer 对象

NSTimer *timer = [NSTimertimerWithTimeInterval:1.0 target:self selector:@selector(test1) userInfo:nilrepeats:YES];

   

// 将刚创建的 NSTimer 对象加到消息循环中, 这样就会自动启动定时器

NSRunLoop *runLoop = [NSRunLoopcurrentRunLoop];

[runLoop addTimer:timerforMode:NSRunLoopCommonModes];

 

// 方式三

// 创建计时器对象

NSTimer *timer = [NSTimertimerWithTimeInterval:1.0 target:self selector:@selector(test1) userInfo:nilrepeats:YES]

 

// 每次调用一次 fire 执行一次 test1方法

[timer fire]; // 执行一次 test 方法

[timer fire]; // 执行一次 test 方法

[timer fire]; // 执行一次 test 方法

[timer fire]; // 执行一次 test 方法

 

 

- UIScrollViewUIPageControl的分页

*UIPageControl 基本使用

*UIPageControl 的常见属性:

一共有多少页

@property(nonatomic)NSInteger numberOfPages;

 

当前显示的页码

@property(nonatomic)NSInteger currentPage;

 

只有一页时,是否需要隐藏页码指示器

@property(nonatomic)BOOL hidesForSinglePage;

 

其他页码指示器的颜色

@property(nonatomic,retain) UIColor *pageIndicatorTintColor;

 

当前页码指示器的颜色

@property(nonatomic,retain) UIColor *currentPageIndicatorTintColor;

 

- 解决图片轮播器的2 Bug

Bug1:当单击(拖拽)界面上的某个其他控件的时候, UIScrollView停止滚动的问题。

Bug2:当拖拽UIScrollView的时候, 保持一段时间不松手的时候, 一旦松手UIScrollView会连续滚动多次。

 

 

 

- UIAlertView/UIActionSheet使用(巩固代理的使用)

 

- UIAlertController介绍

 

- 启动图片与控制器大小关系

 

- 介绍为什么 UI控件的 delegate 属性必须要使用 weak

// 所有UI控件的代理属性(一般情况下叫:delegate属性),都必须使用weak来修饰

 

- 介绍拖线时, UI控件为什么weak 来修饰

// 当界面上的控件,要通过一个属性来访问的时候, 一般情况下, 这个属性的修饰符是weak

 

 


0 0
原创粉丝点击