在UIScrollView中使用Auto Layout中的VFL(Visual format language)
上一篇VFL(Visual format language)的文章中讲了一些基本用法.传送门http://www.cnblogs.com/wupei/p/4150626.html.
这篇简单的讲解下UIScrollView下的自动布局.UIScrollView有一个contentSize所以,他跟其他的view不一样。其他的view你只需要指定他的四个边距,或者能固定他的大小就行。但是UIScrollView不行,约束写不好可能会导致滚动不了,或者报错或一堆警告。但是理解了他的原理就很容易去做到了。
一、首先实现一个水平滚动
水平滚动最常见的就是一个广告循环了(此处不讲解循环),以前通常是直接用宽度乘以几就是contenSize的宽度。这里就用自动布局来实现指定contenSize的宽度.代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | UIScrollView *scrollview=[[UIScrollView alloc]init]; scrollview.translatesAutoresizingMaskIntoConstraints= NO ; [ self .view addSubview:scrollview]; scrollview.pagingEnabled= YES ; [ self .view addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "H:|[scrollview]|" options:0 metrics: nil views: NSDictionaryOfVariableBindings (scrollview)]]; [ self .view addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "V:|[scrollview]|" options:0 metrics: nil views: NSDictionaryOfVariableBindings (scrollview)]]; UIView *view1=[[UIView alloc]init]; view1.translatesAutoresizingMaskIntoConstraints= NO ; [scrollview addSubview:view1]; view1.backgroundColor=[UIColor redColor]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "H:|[view1(==width)]" options:0 metrics:@{@ "width" :@( self .view.frame.size.width)} views: NSDictionaryOfVariableBindings (view1)]]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "V:|[view1(==200)]" options:0 metrics: nil views: NSDictionaryOfVariableBindings (view1)]]; UIView *view2=[[UIView alloc]init]; view2.translatesAutoresizingMaskIntoConstraints= NO ; [scrollview addSubview:view2]; view2.backgroundColor=[UIColor grayColor]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "H:[view1][view2(==view1)]" options:0 metrics: nil views: NSDictionaryOfVariableBindings (view2,view1)]]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "V:|[view2(==view1)]|" options:0 metrics: nil views: NSDictionaryOfVariableBindings (view2,view1)]]; UIView *view3=[[UIView alloc]init]; view3.translatesAutoresizingMaskIntoConstraints= NO ; [scrollview addSubview:view3]; view3.backgroundColor=[UIColor blackColor]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "H:[view2][view3(==view2)]|" options:0 metrics: nil views: NSDictionaryOfVariableBindings (view3,view2)]]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "V:|[view3(==view1)]|" options:0 metrics: nil views: NSDictionaryOfVariableBindings (view3,view1)]]; |
这在段代码里,我给scrollview初始化了三个子view.而这三个子view在水平方向一字排开。我们来看一下这三个子view的水平约束
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "H:|[view1(==width)]" options:0 metrics:@{@ "width" :@( self .view.frame.size.width)} views: NSDictionaryOfVariableBindings (view1)]]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "H:[view1][view2(==view1)]" options:0 metrics: nil views: NSDictionaryOfVariableBindings (view2,view1)]]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "H:[view2][view3(==view2)]|" options:0 metrics: nil views: NSDictionaryOfVariableBindings (view3,view2)]]; |
从这三个语句来看,很容易看出,这三个view,宽度是相等的。而且下一个view紧跟着上一个view的最右边。
在第一个view的约束中H:|[view1(==width)],这里的H:|就是表明这个view紧贴在它的spuerview的最左边。
第三个view的约束中H:[view2][view3(==view2)]|,后面有一个|,说明了view3在superview的最右边紧贴着。换句话说,这个view3的maxX就是contentSize的width.在这里也就起来一个约束他的滚动范围的作用。正是因为如果,我们的scrollview就可以愉快的滚动起来了。
二、实现一个垂直方向滚动
看过了水平方向的代码,我们知道,只要知道什么时候它的子view贴到最边上就可以确定它的滚动范围了。同理垂直方向也是一样。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | UIScrollView *scrollview=[[UIScrollView alloc]init]; scrollview.translatesAutoresizingMaskIntoConstraints= NO ; [ self .view addSubview:scrollview]; [ self .view addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "H:|[scrollview]|" options:0 metrics: nil views: NSDictionaryOfVariableBindings (scrollview)]]; [ self .view addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "V:|[scrollview]|" options:0 metrics: nil views: NSDictionaryOfVariableBindings (scrollview)]]; UIView *view1=[[UIView alloc]init]; view1.translatesAutoresizingMaskIntoConstraints= NO ; [scrollview addSubview:view1]; view1.backgroundColor=[UIColor redColor]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "H:|[view1(==width)]|" options:0 metrics:@{@ "width" :@( self .view.frame.size.width)} views: NSDictionaryOfVariableBindings (view1)]]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "V:|[view1(==300)]" options:0 metrics: nil views: NSDictionaryOfVariableBindings (view1)]]; UIView *view2=[[UIView alloc]init]; view2.translatesAutoresizingMaskIntoConstraints= NO ; [scrollview addSubview:view2]; view2.backgroundColor=[UIColor grayColor]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "H:|[view2(==view1)]" options:0 metrics: nil views: NSDictionaryOfVariableBindings (view2,view1)]]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "V:[view1][view2(==400)]" options:0 metrics: nil views: NSDictionaryOfVariableBindings (view2,view1)]]; UIView *view3=[[UIView alloc]init]; view3.translatesAutoresizingMaskIntoConstraints= NO ; [scrollview addSubview:view3]; view3.backgroundColor=[UIColor purpleColor]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "H:|[view3(==view2)]|" options:0 metrics: nil views: NSDictionaryOfVariableBindings (view3,view2)]]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "V:[view2][view3(==500)]|" options:0 metrics: nil views: NSDictionaryOfVariableBindings (view3,view2)]]; |
我们再次把这三个view的垂直方向约束抽出来:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "V:|[view1(==300)]" options:0 metrics: nil views: NSDictionaryOfVariableBindings (view1)]]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "V:[view1][view2(==400)]" options:0 metrics: nil views: NSDictionaryOfVariableBindings (view2,view1)]]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "V:[view2][view3(==500)]|" options:0 metrics: nil views: NSDictionaryOfVariableBindings (view3,view2)]]; |
这三个约束,很明显看出view1高度为300,view2高度为400,view3高度为500,而且它们都紧跟在着上一个view。
在view1的约束中可以看出来,它是最上面的,换句话说他的坐标就是(0,0).
而view3的约束是[view3(==500)]|,那它的maxY就是contenSize的height了.这样就可以确定他能在垂直方向滚动了。
三、两个方法都可以滚动(相信这一步已经不难了)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | UIScrollView *scrollview=[[UIScrollView alloc]init]; scrollview.translatesAutoresizingMaskIntoConstraints= NO ; [ self .view addSubview:scrollview]; [ self .view addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "H:|[scrollview]|" options:0 metrics: nil views: NSDictionaryOfVariableBindings (scrollview)]]; [ self .view addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "V:|[scrollview]|" options:0 metrics: nil views: NSDictionaryOfVariableBindings (scrollview)]]; UIView *view1=[[UIView alloc]init]; view1.translatesAutoresizingMaskIntoConstraints= NO ; [scrollview addSubview:view1]; view1.backgroundColor=[UIColor redColor]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "H:|[view1(==width)]" options:0 metrics:@{@ "width" :@( self .view.frame.size.width)} views: NSDictionaryOfVariableBindings (view1)]]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "V:|[view1(==200)]" options:0 metrics: nil views: NSDictionaryOfVariableBindings (view1)]]; UIView *view2=[[UIView alloc]init]; view2.translatesAutoresizingMaskIntoConstraints= NO ; [scrollview addSubview:view2]; view2.backgroundColor=[UIColor grayColor]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "H:[view1][view2(==view1)]" options:0 metrics: nil views: NSDictionaryOfVariableBindings (view2,view1)]]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "V:|[view2(==view1)]" options:0 metrics: nil views: NSDictionaryOfVariableBindings (view2,view1)]]; UIView *view3=[[UIView alloc]init]; view3.translatesAutoresizingMaskIntoConstraints= NO ; [scrollview addSubview:view3]; view3.backgroundColor=[UIColor blackColor]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "H:[view2][view3(==view2)]|" options:0 metrics: nil views: NSDictionaryOfVariableBindings (view3,view2)]]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "V:|[view3(==view1)]" options:0 metrics: nil views: NSDictionaryOfVariableBindings (view3,view1)]]; UIView *view4=[[UIView alloc]init]; view4.translatesAutoresizingMaskIntoConstraints= NO ; [scrollview addSubview:view4]; view4.backgroundColor=[UIColor yellowColor]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "H:|[view4(==200)]" options:0 metrics: nil views: NSDictionaryOfVariableBindings (view4)]]; [scrollview addConstraints:[ NSLayoutConstraint constraintsWithVisualFormat:@ "V:[view1][view4(==800)]|" options:0 metrics: nil views: NSDictionaryOfVariableBindings (view4,view1)]]; |
这里只要知道了两个方法什么时候是到底了,就可以确定他的contenSize了,所以,做起来也不会很麻烦。第三个就不再说一次了。
最后总结:在UIScrollView中使用自动布局,如果要想滚动,就要知道他的contenSize,这是大家都知道的。在自动布局中(VFL方式),你只需要知道你的H方向的范围,以及V方向的范围就可以实现效果。也就是知道|[view]|这个约束中的两个"|"的位置。有一点要注意的是,你的view的宽度你得知道,而且约束没有错。否则就不会算出来你的contenSize。如果H|[view]|这样是无法得知的,因为contenSize是没有范围的,他只知道这个view跟左右两这没有距离,但是无法得知具体width是多少。因为contenSize它自己也不知道它的width是多少。所以你这么写它就会对了H|[view(==x)]|,至于X值是多少,就看你实际情况了.
转载注明出处:http://www.cnblogs.com/wupei/p/4428164.html , http://zhiwupei.sinaapp.com/?p=64
Demo源码:https://github.com/zhiwupei/VFL/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步