试想这样的一个需求场合,一个button靠右显示,并且距离superView的顶部和右边间距分别为10和5。如下图所示:

要实现这样的需求,如果不用自动布局技术,那么我们能想到的就是老老实实的使用绝对布局的坐标计算来实现了,假如这个button宽高都是100,父视图的宽是300,那么这个button的坐标就是:(300-100-5,10)。但要是父视图的宽度变了,我们还得重新计算一遍。颇为麻烦。

幸好我们有自动布局技术。要实现这样的需求还是相对比较简单的。

既然我们要实现这样的需求,而且这个需求其实也是具有普遍性的,那么我们直接封装下好了。我们给UIView添加两个扩展属性:horizontalAlignment和verticalAlignment。两个属性都是枚举。

  1. typedef NS_ENUM(NSInteger, UIViewVerticalAlignment) {
  2. UIViewVerticalAlignmentFill = ,
  3. UIViewVerticalAlignmentCenter = ,
  4. UIViewVerticalAlignmentTop = ,
  5. UIViewVerticalAlignmentBottom =
  6.  
  7. };
  8.  
  9. typedef NS_ENUM(NSInteger, UIViewHorizontalAlignment) {
  10. UIViewHorizontalAlignmentFill = ,
  11. UIViewHorizontalAlignmentCenter = ,
  12. UIViewHorizontalAlignmentLeft = ,
  13. UIViewHorizontalAlignmentRight =
  14. };
  15.  
  16. @property (nonatomic,assign)UIViewHorizontalAlignment horizontalAlignment;
  17.  
  18. @property (nonatomic,assign)UIViewVerticalAlignment verticalAlignment;

实现的思路如下:

我下面以水平停靠举例,对于水平停靠有四种情况,首先就是不停靠完全的填充,也就是我们把该subview的宽度跟superview的宽度绑定到一起。第二种情况是左边停靠,依次还有居中停靠和右边停靠。

对于非填充停靠,在宽度方面肯定不能直接绑定到superview的宽度了,只能使用UIView的扩展属性size的宽度了。

现在以上述场景的实现为例,就是水平方向右边停靠。那么我们只要把subview的NSLayoutAttributeRight跟superview的NSLayoutAttributeRight对齐就好了。代码如下:

  1. [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:self
  2. attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeRight multiplier:1.0f constant:-margin.right]];

对于左边停靠和居中停靠无非就是对齐的属性不一样。对于垂直停靠来说也是这样。

完整的停靠代码如下:

  1. UIEdgeInsets margin=self.margin;
  2. switch (self.verticalAlignment) {
  3. case UIViewVerticalAlignmentFill:
  4. {
  5. NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-top-[view]-bottom-|" options: metrics:@{ @"top" : @(margin.top),@"bottom":@(margin.bottom)} views:@{ @"view" : self}];
  6. [self.superview addConstraints:constraints];
  7. }
  8. break;
  9. case UIViewVerticalAlignmentBottom:
  10. {
  11. [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:self
  12. attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeBottom multiplier:1.0f constant:-margin.bottom]];
  13. }
  14. break;
  15. case UIViewVerticalAlignmentCenter:
  16. {
  17. [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:self
  18. attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeCenterY multiplier:1.0f constant:]];
  19. }
  20. break;
  21. case UIViewVerticalAlignmentTop:
  22. {
  23. [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:self
  24. attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeTop multiplier:1.0f constant:margin.top]];
  25. }
  26. break;
  27. default:
  28. break;
  29. }
  30.  
  31. switch (self.horizontalAlignment) {
  32. case UIViewHorizontalAlignmentFill:{
  33. NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|-left-[view]-right-|" options: metrics:@{ @"left" : @(margin.left),@"right":@(margin.right)} views:@{ @"view" : self}];//添加宽度的约束
  34. [self.superview addConstraints:constraints];
  35. }
  36. break;
  37. case UIViewHorizontalAlignmentCenter:{
  38. [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:self
  39. attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeCenterX multiplier:1.0f constant:]];
  40. }
  41. break;
  42. case UIViewHorizontalAlignmentLeft:{
  43. [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:self
  44. attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeLeft multiplier:1.0f constant:margin.left]];
  45. }
  46. break;
  47. case UIViewHorizontalAlignmentRight:{
  48. [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:self
  49. attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeRight multiplier:1.0f constant:-margin.right]];
  50. }
  51. break;
  52. default:
  53. break;
  54. }

对于停靠,我们前面写的UIStackPanel和UIGridView势必也要支持的。因此我也修改了下原来的代码。

然后对于图中 的那个button的代码就是如下:

  1. UIButton *btn=[[UIButton alloc] initWithSize:CGSizeMake(, )];
  2. [btn setBackgroundColor:[UIColor blueColor]];
  3. btn.isBindSizeToSuperView=YES;
  4. [btn setTitle:@"button1" forState:UIControlStateNormal];
  5. btn.horizontalAlignment=UIViewHorizontalAlignmentRight;
  6. btn.verticalAlignment=UIViewVerticalAlignmentTop;
  7. btn.margin=UIEdgeInsetsMake(, , , );
  8. [self.view addSubview:btn];

至此这个系列的博客完结!

完整的源码请点击下载。

IOS 自动布局-UIStackPanel和UIGridPanel(五)的更多相关文章

  1. IOS 自动布局-UIStackPanel和UIGridPanel(三)

    在这一篇了我将继续讲解UIGridPanel. 在iphone的app里面可以经常看到一些九宫格布局的应用,做过html开发的对这类布局应该是很熟悉的.在IOS中要实现这样的布局方法还是蛮多的,但是我 ...

  2. IOS 自动布局-UIStackPanel和UIGridPanel(四)

    为什么说scrollview的自动化布局是难点? 对scrollview做自动化布局,无非就是想对scrollview里面的subviews来做自动化布局.但是scrollview里面的subview ...

  3. IOS 自动布局-UIStackPanel和UIGridPanel(二)

    在上一篇中我提到了如何使用stackpanel和gridpanel来实现自动布局.而在这一篇中我着重讲解下其中的原理. 在(UIPanel   UIStackPanel  UIGridPanel)中主 ...

  4. IOS 自动布局-UIStackPanel和UIGridPanel(一)

    我以前是做windows phone开发的,后来转做IOS的开发,因此很多windows phone上面的开发经验也被我带到了IOS中.其实有些经验本身跟平台无关,跟平台有关的无非就是实现方法而已.好 ...

  5. iOS开发Swift篇—(五)元组类型

    iOS开发Swift篇—(五)元组类型 一.元组类型介绍 1.什么是元组类型 元组类型由 N个 任意类型的数据组成(N >= 0),组成元组类型的数据可以称为“元素” 示例: let posit ...

  6. iOS 自动布局详细介绍

    1. 自动布局的理解 iOS自动布局很有用,可以在不同size的屏幕上运行,原先看的头痛,还是习惯用最蠢的[UIScreen mainScreen].bounds.size.width等来布局,后来实 ...

  7. iOS自动布局——Masonry详解

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由鹅厂新鲜事儿发表于云+社区专栏 作者:oceanlong | 腾讯 移动客户端开发工程师 前言 UI布局是整个前端体系里不可或缺的一环 ...

  8. iOS 11开发教程(五)iOS11模拟器介绍二

    iOS 11开发教程(五)iOS11模拟器介绍二 3.iOS11模拟器中设置语言 对于不同国家的人来说,使用到的语言是不一样的.一般情况下iOS11模拟器默认使用的English(英语).对于英文不好 ...

  9. iOS开发之窥探UICollectionViewController(五) --一款炫酷的图片浏览组件

    本篇博客应该算的上CollectionView的高级应用了,从iOS开发之窥探UICollectionViewController(一)到今天的(五),可谓是由浅入深的窥探了一下UICollectio ...

随机推荐

  1. 开机启动+Linux发送邮件

    需求:检测Linux上Tomcat是否允许,挂了的话给运维发送邮件通知 实现:编写脚本一直检测Tomcat进程是否存活,否则给运维发送邮件,脚本设置开机时自动启动 1.Linux发送邮件 vim /e ...

  2. linux 的iptables失效解决方法

    1.首先查看iptables配置文件:cat  /etc/sysconfig/iptables 2.然后查看 iptables 配置文件是否生效:iptables  -L,结果如下,很显然和上面的配置 ...

  3. html 手机端click 事件延迟问题(fastclick.js使用方法)

    下载地址: fastclick.js 为什么存在延迟? 从点击屏幕上的元素到触发元素的 click 事件,移动浏览器会有大约 300 毫秒的等待时间.为什么这么设计呢? 因为它想看看你是不是要进行双击 ...

  4. python flask学习(1)与Git基础操作

    今天从简单的flask开始完成Flask web开发的学习.今天学习了Git和GitHub项目的提交. Git尝试提交过程中出现了"Could not read from remote re ...

  5. 开源GIS-对比GeoServer和MapServer

    1  主流组合: 基于C.C++系列的:Mapserver(服务器)+QGIS(桌面软件)+PostGIS(数据库)+Openlayers(JS)/ openscale (FLex)(浏览器客户端) ...

  6. siege4安装和使用介绍

    使用文档参考地址:https://www.joedog.org/siege-manual/ siege4地址:http://download.joedog.org/siege/ cd /usr/loc ...

  7. SQL server 数据库基础语句

    上篇介绍的是鼠标操作 遗漏两个知识: 主外键 两个列 数据类型 必须一致    //int类型不能约束nvarchar 类型      varchar类型不能约束nvarchar类型 varchar( ...

  8. C++实现动态数组

    实现一个动态数组,要求对于随机访问可以在常数时间完成,可以通过push_back向数据的尾部追加元素,可以通过pop_back删除尾部元素,能够满足常见的数组操作. LINE 2016年春招笔试   ...

  9. leetcode_1053. Previous Permutation With One Swap

    1053. Previous Permutation With One Swap https://leetcode.com/problems/previous-permutation-with-one ...

  10. 如何让浏览器关闭后session失效

    llzzcc66 知道合伙人数码行家 推荐于2018-08-10   如果用户不点击网站的“退出”链接,而直接关闭浏览器(或者强制关闭浏览器进程.死机等),服务器无法处理用户退出网站的请求,解决方式如 ...