IOS 自动布局-UIStackPanel和UIGridPanel(四)
为什么说scrollview的自动化布局是难点?
对scrollview做自动化布局,无非就是想对scrollview里面的subviews来做自动化布局。但是scrollview里面的subviews的自动化布局不是由scrollview的高宽来决定的,而是由scrollview的contentSize共同决定的,这样就出现一个问题了,就算scrollview的高宽是改变了,但是只要contentSize不变,那么对于scrollview里面的subviews的高宽其实是没有影响的。而实现自动化布局的NSLayoutConstraint也无法实现对scrollview的contentSize属性做自动化布局的。那么纯粹的想使用NSLayoutConstraint来对scrollview做自动化布局的方法是行不通的。
到这里咱再换一个方法,其实我们平常用scrollview更多的场景是用来做上下滚动或左右滚动,很少有上下滚动和左右滚动同时存在的情况。现在假设我们的自动化布局的scrollview就是上下滚动的,在水平方向,subviews的宽度永远跟scrollview的宽度一致,这样的场景是不是能实现?针对这样的场景我们马上就能想到,只要把subviews的宽度用NSLayoutConstraint实现跟scrollview的宽度绑定就可以了啊。
UIScrollView *scroll=[[UIScrollView alloc] init];
scroll.backgroundColor=[UIColor blueColor];
scroll.isBindSizeToSuperView=YES;
[self.view addSubview:scroll];
[scroll setContentSize:CGSizeMake(, )]; UILabel *label = [[UILabel alloc] initWithSize:CGSizeMake(, )];
label.backgroundColor = [UIColor blackColor];
label.textColor=[UIColor whiteColor];
label.font=[UIFont systemFontOfSize:];
label.text = @"Label1";
label.translatesAutoresizingMaskIntoConstraints=NO;
label.textAlignment = NSTextAlignmentCenter;
[scroll addSubview:label];
[scroll addConstraint:[NSLayoutConstraint constraintWithItem:label
attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:scroll attribute:NSLayoutAttributeWidth multiplier:1.0f constant:]];
我们发现这样做可以啊!别急,你试着再添加一个subview看看?你会发现用这样的方法虽然能让subviews实现宽度跟scrollview的宽度保持一致,但是在垂直方向上无法顺序布局。这是为什么呢?
问题在于translatesAutoresizingMaskIntoConstraints这个属性我们设置了no,为什么要设置no?只要我们使用自动布局,或者更通俗的说,只要我们使用了NSLayoutConstraint,那么必须要把这个属性设置为no。而一旦设置了no,那么这个view的位置和大小也只能是通过NSLayoutConstraint来实现了。说道这里,看过我前三篇博客的同学就能想到,不是有一个UIStackPanel正好可以实现这样的功能的吗?对的。我们可以直接拿来用,把uiStackpanel做未subview添加到scrollView中,然后将本来要添加到scrollvew中的subviews添加到stackpanel中。这样就能实现以上的场景了。但是这样做还是有一个问题,就是stackpanel的宽度我们是可以绑定到scrollview的宽度,但是高度呢?高度必须跟contentSize的height做绑定。而要实现这样的需求我们就得借助IOS的KVO技术来实现,获取scrollview的contentSize属性变化事件,然后再次绑定。这样就能完全的实现以上的需求了。
为了把以上的实现过程进行一个封装,我们在UIPanel里面添加了一个bindToScrollView的方法。
NSString *const KVCUIPanelString_ContentSize = @"scrollView_ContentSize";
-(void)bindToScrollView:(UIScrollView *)scrollView{
_scrollView=scrollView;
self.translatesAutoresizingMaskIntoConstraints=NO; [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:scrollView attribute:NSLayoutAttributeLeft multiplier:1.0f constant:]]; [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:scrollView attribute:NSLayoutAttributeWidth multiplier:1.0f constant:]]; [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:scrollView attribute:NSLayoutAttributeTop multiplier:1.0f constant:]]; [scrollView addObserver:self forKeyPath:KVCUIPanelString_ContentSize options:NSKeyValueObservingOptionNew context:nil];
[self addConstraint:[NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0f constant:[scrollView contentSize].height]];//第一次绑定的时候直接把scrollView的contentSize.height作为panel的高度
} -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
if([keyPath isEqualToString:KVCUIPanelString_ContentSize]){
[self removeConstraints:self.constraints];
[self addConstraint:[NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0f constant:[(UIScrollView *)object contentSize].height]];
}
}
使用kvo的时候一定要记得释放。
-(void)removeFromSuperview{
[super removeFromSuperview];
if(_scrollView){
[_scrollView removeObserver:self forKeyPath:KVCUIPanelString_ContentSize context:nil];
_scrollView=nil;
}
}
方法已经封装好了,那么后面就是如何使用了。代码如下:
//初始化UIScrollView
UIScrollView *scroll=[[UIScrollView alloc] init];
scroll.backgroundColor=[UIColor blueColor];
scroll.isBindSizeToSuperView=YES;//把UIScrollView的高宽绑定到父视图
[self.view addSubview:scroll];
[scroll setContentSize:CGSizeMake(, )];//设置UIScrollView的contentSize UIStackPanel *_panel=[[UIStackPanel alloc] init];
[scroll addSubview:_panel];
_panel.backgroundColor=[UIColor yellowColor];
[_panel bindToScrollView:scroll];//将UIStackPanel绑定到UIScrollView UILabel *label = [[UILabel alloc] initWithSize:CGSizeMake(, )];
label.backgroundColor = [UIColor blackColor];
label.textColor=[UIColor whiteColor];
label.font=[UIFont systemFontOfSize:];
label.text = @"Label1";
label.textAlignment = NSTextAlignmentCenter;
[_panel addSubview:label]; label = [[UILabel alloc] initWithSize:CGSizeMake(, )];
label.backgroundColor = [UIColor blackColor];
label.textColor=[UIColor whiteColor];
label.font=[UIFont systemFontOfSize:];
label.text = @"Label2";
label.margin=UIEdgeInsetsMake(, , , );
label.textAlignment = NSTextAlignmentCenter;
[_panel addSubview:label];
至此,uiscrollview的自动化解决方案已经完成了。
下一遍介绍UIView在如何停靠在superView中,实现不管superview的高宽如何改变,都不会改变UIView的停靠位置。
连带本篇的源码都会在下一篇中给出。
IOS 自动布局-UIStackPanel和UIGridPanel(四)的更多相关文章
- IOS 自动布局-UIStackPanel和UIGridPanel(三)
在这一篇了我将继续讲解UIGridPanel. 在iphone的app里面可以经常看到一些九宫格布局的应用,做过html开发的对这类布局应该是很熟悉的.在IOS中要实现这样的布局方法还是蛮多的,但是我 ...
- IOS 自动布局-UIStackPanel和UIGridPanel(二)
在上一篇中我提到了如何使用stackpanel和gridpanel来实现自动布局.而在这一篇中我着重讲解下其中的原理. 在(UIPanel UIStackPanel UIGridPanel)中主 ...
- IOS 自动布局-UIStackPanel和UIGridPanel(一)
我以前是做windows phone开发的,后来转做IOS的开发,因此很多windows phone上面的开发经验也被我带到了IOS中.其实有些经验本身跟平台无关,跟平台有关的无非就是实现方法而已.好 ...
- IOS 自动布局-UIStackPanel和UIGridPanel(五)
试想这样的一个需求场合,一个button靠右显示,并且距离superView的顶部和右边间距分别为10和5.如下图所示: 要实现这样的需求,如果不用自动布局技术,那么我们能想到的就是老老实实的使用绝对 ...
- iOS自动布局——Masonry详解
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由鹅厂新鲜事儿发表于云+社区专栏 作者:oceanlong | 腾讯 移动客户端开发工程师 前言 UI布局是整个前端体系里不可或缺的一环 ...
- iOS 导出 ipa 包时 四个选项的意义
iOS 导出 ipa 包时 四个选项的意义 如图 在 iOS 到处 ipa包的时候 会有四个选项 1.Save for iOS App Store Deployment 保存到本地 准备上传App ...
- iOS开发Swift篇—(四)运算符
iOS开发Swift篇—(四)运算符 一.运算符 1.Swift所支持的部分运算符有以下一些 赋值运算符:= 复合赋值运算符:+=.-= 算术运算符:+.-.*./ 求余运算符:% 自增.自减运算符: ...
- iOS 自动布局详细介绍
1. 自动布局的理解 iOS自动布局很有用,可以在不同size的屏幕上运行,原先看的头痛,还是习惯用最蠢的[UIScreen mainScreen].bounds.size.width等来布局,后来实 ...
- ios页面间传递参数四种方式
ios页面间传递参数四种方式 1.使用SharedApplication,定义一个变量来传递. 2.使用文件,或者NSUserdefault来传递 3.通过一个单例的class来传递 4.通过Dele ...
随机推荐
- 在webconfig放置固定值
通常的,为了布置到服务器后修改的方便通常把一些会改变的值放在webconfig: 首先在web.ocnfig中放入如下值 <appSettings> <add key="A ...
- javascript 流程控制及函数
回顾 基本语法 在html的使用 <script></script> 注释 ///* */ 指令结束符 ;换行 输出 console.log()document.write() ...
- node.js之Windows 系统下设置Nodejs NPM全局路径
node.js 0.10 版本下修改全局路径: npm config set cache "D:\nodejs\node_cache" npm config set prefix ...
- 关于搭建系统直播和Thinkphp的杂谈(持续更新)
Q:Access denied for user 'root'@'localhost' 错误 A:第一种:配置文件中把数据库的用户名密码再改一遍,把runtime里的文件删除 第二种:修改syste ...
- c语言中的->代表什么意思
c语言中 ->符号是什么意思? 比如c=a->b a为结构体或联合体的指针,->表示调用其成员
- Spring MVC异常统一处理(包括普通请求异常以及ajax请求异常)
通常SpringMVC对异常的配置都是返回某个jsp视图给用户,但是通过ajax方式发起请求,即使发生异常,前台也无法获得任何异常提示信息.因此需要对异常进行统一的处理,对于普通请求以及ajax请求的 ...
- mysql 外键关联
mysql 外键关联 什么是外键:外键是一个特殊的索引,用于关联两个表,只能是指定内容. 如我将新建一个daka的表,然后将此表的class_id 与另外一个class的表的cid字段关联 class ...
- 一个batch如何通过一个网络
一个batch下所有的图片一起经过整个网络,不是说一张图片经过网络后再让下一张进入网络,这样一个batch一起通过网络计算速度比一张一张这样快
- Django-C001-快速入门
此文章完成度[100%]留着以后忘记的回顾.多写多练多思考,我会努力写出有意思的demo,如果知识点有错误.误导,欢迎大家在评论处写下你的感想或者纠错. Django Django是一个开放源码的We ...
- Bootstrap图片支持响应式
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...