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 ...
随机推荐
- docker镜像与容器
目录 docker镜像与容器 概述 分层存储 镜像与容器 删除镜像与容器 将容器中的改动提交到镜像 慎用 docker commit--构建镜像推荐使用dockerfile docker镜像与容器 概 ...
- kafka java api生产者
import java.util.HashMap; import java.util.List;import java.util.Map;import java.util.Properties; im ...
- codeforces736D. Permutations(线性代数)
题意 $m \leqslant 500000$,题目打错了 Sol 神仙题Orz 构造矩阵$B$,使得$B[b[i]][a[i]] = 1$ 那么他的行列式的奇偶性也就对应了生成排列数列数量的奇偶性( ...
- 浅谈C++ 内存泄漏及其检测工具
浅谈C++ 内存泄漏及其检测工具 http://wenku.baidu.com/link?url=1DGkOOvd_ITZyB8IHAwfhCOx2tfO6id8UfuyQkAMHZU6sasaAXz ...
- springMVC中ajax和后台数据格式错误
前台ajax: $.ajax("${pageContext.request.contextPath}/hello",// 发送请求的URL字符串. { dataType : &qu ...
- java25个Java机器学习工具&库
本列表总结了25个Java机器学习工具&库: 1. Weka集成了数据挖掘工作的机器学习算法.这些算法可以直接应用于一个数据集上或者你可以自己编写代码来调用.Weka包括一系列的工具,如数据预 ...
- 微软OneDrive使用体验
OneDrive是微软推出的一款软件,提供类似百度网盘的功能,能够在线存储照片和文档, 号称从任意电脑.Mac 电脑或手机都可访问. 一起来看看吧,第一次用之前需要进行简单配置. 因为是一个同步盘,需 ...
- leetcode 4.两个排序数组的中位数
题目: 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 . 请找出这两个有序数组的中位数.要求算法的时间复杂度为 O(log (m+n)) . 你可以假设 nums1 和 nums ...
- ZendStudio 常用快捷键大全
应用场景 快捷键 功能 查看快捷键 ctrl+shift+l 显示所有快捷键列表 查看和修改快捷键 打开Window->Preferences->General->keys 修改 ...
- 【Qt】2.2 继续了解信号和槽
槽和普通成员函数一样,可以是虚函数.被重载,可以是公有.私有.保护的.它可以被其它C++成员函数调用. 槽连接了信号,当发射这个信号时,槽会被自动调用. 连接函数: bool QObject::con ...