一、目标:
1)
UIScrollView的常见属性
实现滚动缩放
常用的代理方法(后面学习的控件都与代理方法有关)
UIScrollView与UIPageControl的分页
NSTimer的使用,计时器控件周期性执行任务
2)
2.1)什么是UIScrollView?
UI控件 具有缩放 滚动 功能
2.2)为什么会滚动,滚动到哪?
因为:一个屏幕无法显示全部内容
滚动截止:内容结束的地方
2.3)什么在滚动?
scrollview中的内容滚动
2.4)怎么添加scrollview
创建scrollview- 向scrollview中添加子view-限定滚动的范围-注意,滚动范围一定要比原先的scrollview大,而不是比屏幕大
contentSize的宽高一定要大于scrollview的宽高才会滚动
二、scrollview 的常见属性使用
a.@property(weak,nonatomic) UIScrollView*scrollview;
b. _scrollview=[[UIScrollView alloc]initWithFrame:CGRectMake(0,0,100,100)]];
c. _scrollview.contentSize = self.imageview.frame.size;//此处可直接设置大小,也可依据显示内容设置大小
_scrollview.contentSize = CGSizeMake(1024,0)//当高度不希望滚动时,设置为0即可
d.设置显示滚动指示器与否 默认显示
_scrollview.showsVerticalScrollIndicator =NO;
_scrollview.showsHorizontalScrollIndicator = NO;
e.设置弹簧动画效果 默认开启
_scrollview.bounces = YES;
f.即使不设置contentSize 但是在水平和垂直方向上还是可以具备弹簧效果 前提是bounces属性开启
_scrollview.alwaysBounceVertical =YES;
_scrollview.alwaysBounceHorizontal =YES;
g.没有设置contentInset的时候,imageview就会默认停留在初始位置 变相的增加了滚动的范围 top left bottom right
_scrollview.contentInset= UIEdgeInsetsMake(10,20,30,40);
h.contentOffset offset 偏移量,滚动到了某个位置
_scrollview.contentOffset =CGPointMake(100,100);
偏移量的意思是当scrollview移动时与显示在scrollview的视图之间所产生的x、y之间的差值
三、总结scrollView不能滚动的几点原因
1、contentSize的大小小于scrollview的size
2、UserInteractorEnable 用户交互被禁止
3、_scrollview.scrollEnabled =NO
四、如何对offset进行手动修改
CGPoint offset = _scrollview.contentOffset;
offset.x+=10;
offset.y+=10;
如何在赋值的时候显示动画效果
[UIView animateWithDuration:0.4 animations:^{
_scrollview.contentOffset = offset;
}];
或者可以直接调用 setContentOffset
[_scrollview setContentOffset :offset animated:true];
观察在滚动的时候contentSize 和scrollview.frame.size 的变化
NSLog(@"contentSize :%@ scrollview.frame.size:%@",NSStringFromCGSize(_scrollview.contentOffset),NSStringFromCGSize(_scrollview.frame.size));
注意CGSize和CGPoint在转换成NSString 的时候,使用方式
NSStringFromCGSize/ NSStringFromCGPoint
五、显示喜马拉雅电台的布局(使用ScrollView和浮动在上方的View)
注意如何让顶部的View属于浮动状态而不是跟着ScrollView滚动:将View放置在ScrollView上方
获取最底下的Y值
CGFloat Ymax =CGRectGetMaxY(imageview.frame);
六、代理的使用
在viewController控制器中,ScrollView在滚动的时候,不停的对外发消息 用代理(发消息监听)
什么情况下使用代理?
自己不能做 或者 自己不适合做的时候
以猪肉销售商和猪肉养殖户为例,
首先;销售商 需要制定一个标准: “我需要什么样的猪肉”
其次: 双方认可协议签订
最后: 当销售商清楚知道自己缺猪肉的情况下,就会发出消息通知养殖户
这其中涉及的就是代理的过程
制定协议-遵守协议、设置代理、实现相互认识 view.delegate=self; -通知代理*(调用代理放法);
总结:使用代理的时候:
1、制定协议以及代理方法,定义代理属性
2、遵守协议,实现对应的代理方法
3、制定协议者在适当的时候调用代理方法
@protocol HuiDelegate <NSObject>
@property(nonatomic,weak) id<HuiDelegate> delegate
执行方法
-(instancestype)initWithFrame:(CGRect )frame
{
if (self=[super initWithFrame:frame ])
{
//creat button....
[btn addTraget:self action:@selector(didClick) forControlEvent:UIControlEventTouchUpInside];
[self addSubview :btn]
}
}
-(void)didClick
{
if([self.delegate respondsToSelector:@selector(needPigMeet)])
{[self.delegat needPigMeet];}}
注意为什么使用self.delegate respondsToSelector :@selector(needPigMeet)]
如果不写的话,一旦delegate中的代理方法没有设置 系统就会直接崩溃 返回的是一个BOOL值
以上都是“猪肉养殖户”执行的操作:
定义代理-定义代理属性 - 设置代理方法
在ViewController中:
#import“Hui.h”
@interface ViewController()<HuiDelegate>
Hui *h =[[Hui alloc ]initWithFrame:CGRectMake(0,0,200,200)];
h.delegate = self;
-(void) neegPigMeet
{
NSLog(@"ok you got meet");
}
以上都是“猪肉销售商”执行的代理过程
遵守协议-设置代理-实现代理方法
(一般情况下,我们的是看不到代理内部设置的过程,但是我们会知道代理内部有哪些方法,然后进行实现)
七、监听scrollview内部 -联系delegate
1、遵守代理协议
@interface ViewController ()<UIScrollViewDelegate>
2、设置代理
_scrollview.delegate =self;
3、实现协议方法
-(void) scrollViewDidScroll:(UIScrollView *)scrollView
{
NSLog (@"滚动的时候调用:%@",NSStringFromCGPoint(scrollview.contentOffset));
}
-(void)scrollViewWillBeginDragging:(UIScrollView*)scrollview
{
NSLog(@"开始拖拽的时候调用");
}
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollview willDecelerate :(BOOL)decelerate
{
NSLog(@" 停止拖拽的时候调用");
}
八、图片的缩放 (viewForZoomingInScrollView) 代理(内部)
1、遵守协议
<UIScrollViewDelegate>
2、设置代理
_scrollview.delegate=self;
3、设置缩放倍数的范围
_scrollview.minimumZoomScale =0.3;
_scrollview.maxmumZoomScale =3;
4 、设置代理方法
-(UIView*) viewForZoomingInScrollView:(UIScrollView *)scrollview
{
return _imageview;//注意,返回的是你要执行缩放操作的view
}
-(void)scrollViewWillBeginZooming:(UIScrollView*)scrollview withView:(UIView *) view
{
NSLog(@"scrollview开始缩放");
}
-(void)scrollViewDidEndZooming:(UIScrollView *)scrollview withView:(UIView*)view
{
NSLog(@"scrollview结束时调用");
}
九、图片轮播器(计时器和scrollview 和pageControl使用)
1、首先实现图片的scrollview滚动
实现图片的拼接
[_imageNamed setImage:[UIImage imageNamed:[NSString stringWithFormat:"img_%02d",i+1]]];
2、其次添加pageControl
关于pageControl的一些属性
a、numberOfPages
b、currentPage
c、currentPageIndicatorTintColor
d、PageIndicatorTintColor
_pageControl.currentPage =1;(注意 currentPage的范围是从0-numberOfPages-1)
_pageControl.numberOfPages=4;
_pageControl.currentPageIndicatorTintColor =[UIColor redColor];//设置当前page指示器颜色
_pageControl.PageIndicatorTintColot =[UIColor grayColor];//设置page指示器未指示的颜色属性
3、结合pageControl和scrollView(contentOffset变化判断currentPage的变化)
减速的时候,就是一张页面播放完毕的时候
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollview
{
_pageControl.currentPage = (scrollview.contentOffset.x)/(scrollview.frame.size.width);
}
4、自动滚动时候使用Timer(shceduledTimerWithInterval方法)
a、定义NSTimer属性
@property(nonatomic,strong)NSTimer *timer;
b、初始化Timer
c、使用Timer 的scheduledTImerWithInterval 方法
-(void)initTimer
{
_timer =[NSTimer scheduledTimerWithInterval:2//时间间隔
targer:self //控制器
selector:@selector(didclick) //执行的方法
userInfo:nil //用户自定义参数
repeats:true];// 是否重复
[timer fire];//[timer invalidate]; //fire的话,不会等待Inteval 直接执行滚动操作 //invalidate 关闭Timer 而且一旦关闭就无法再开启 Timer必须要重新创建才可以
}
5、出现一个状况,当在view中再添加一个textView的时候,会发现,一旦textView中进行滚动,轮播中的scrollview将会停止(考虑用户交互优先级 )
改变Timer的用户交互优先级
NSRunLoop *mainrunloop =[NSRunLoop mainRunLoop];
[mainrunloop addTimer:_timer forMode:NSDefaultRunLoopModel];
有两种类型:
NSDefaultRunLoopMode
NSRunLoopCommonModes
很明显Default低一点
十、为什么delegate设置属性的时候用weak修饰符?
使用weak是为了防止循环饮用 协议遵守再类扩展名之后
可以自定义两个view
1、SecondView :
@protocol SecondViewDelegate<NSObject>
@property(nonatomic, weak) id<SecondViewDelegate> delegate;
2、FirstView
@interface FirstView()<SecondViewDelegate>
-(instancetype) initWithFrame:(CGRect)frame
{
if(self=[super initWithFrame:frame])
{
SecondView *secondview =[[SecondView alloc]init];//在firstview中引用secondview
secondview.delegate =self; //将secondview的代理指向firstview 也就是说,secondview对firstview有一个会strong/weak的引用
[self addSubview:secondview];
}
}
3、viewController
FirstView *firstview=[[FirstView alloc]initWithFrame:CGRectMake(0,0,100,100)];
可以通过在双方view的执行方法中加入
-(void)dealloc
{
NSLog(@"已回收XXview");
}
可以看出 设为strong 的时候,两边view都是强引用,导致一直未被释放
但是设为weak的时候,firstview对secondview是强引用,secondview对firstview是弱引用 最后两个都被释放了
总结:
只要有两个对象相互引用的时候,其中一个必须为weak 否则无法释放,容易造成循环引用
浙公网安备 33010602011771号