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

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

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

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

typedef NS_ENUM(NSInteger, UIViewVerticalAlignment) {
UIViewVerticalAlignmentFill = ,
UIViewVerticalAlignmentCenter = ,
UIViewVerticalAlignmentTop = ,
UIViewVerticalAlignmentBottom = }; typedef NS_ENUM(NSInteger, UIViewHorizontalAlignment) {
UIViewHorizontalAlignmentFill = ,
UIViewHorizontalAlignmentCenter = ,
UIViewHorizontalAlignmentLeft = ,
UIViewHorizontalAlignmentRight =
}; @property (nonatomic,assign)UIViewHorizontalAlignment horizontalAlignment; @property (nonatomic,assign)UIViewVerticalAlignment verticalAlignment;

实现的思路如下:

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

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

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

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

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

完整的停靠代码如下:

UIEdgeInsets margin=self.margin;
switch (self.verticalAlignment) {
case UIViewVerticalAlignmentFill:
{
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-top-[view]-bottom-|" options: metrics:@{ @"top" : @(margin.top),@"bottom":@(margin.bottom)} views:@{ @"view" : self}];
[self.superview addConstraints:constraints];
}
break;
case UIViewVerticalAlignmentBottom:
{
[self.superview addConstraint:[NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeBottom multiplier:1.0f constant:-margin.bottom]];
}
break;
case UIViewVerticalAlignmentCenter:
{
[self.superview addConstraint:[NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeCenterY multiplier:1.0f constant:]];
}
break;
case UIViewVerticalAlignmentTop:
{
[self.superview addConstraint:[NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeTop multiplier:1.0f constant:margin.top]];
}
break;
default:
break;
} switch (self.horizontalAlignment) {
case UIViewHorizontalAlignmentFill:{
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|-left-[view]-right-|" options: metrics:@{ @"left" : @(margin.left),@"right":@(margin.right)} views:@{ @"view" : self}];//添加宽度的约束
[self.superview addConstraints:constraints];
}
break;
case UIViewHorizontalAlignmentCenter:{
[self.superview addConstraint:[NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeCenterX multiplier:1.0f constant:]];
}
break;
case UIViewHorizontalAlignmentLeft:{
[self.superview addConstraint:[NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeLeft multiplier:1.0f constant:margin.left]];
}
break;
case UIViewHorizontalAlignmentRight:{
[self.superview addConstraint:[NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeRight multiplier:1.0f constant:-margin.right]];
}
break;
default:
break;
}

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

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

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

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

完整的源码请点击下载。

最新文章

  1. bzoj 1066 蜥蜴
  2. C# 加载 SQLite DLL问题
  3. 虚拟化平台cloudstack(6)——使用maven:jetty调试
  4. SQL Case when 的使用方法(转)
  5. Ajax的实现
  6. iOS - 正则表达式判断邮箱、身份证..是否正确:
  7. Javascript模块化编程:AMD规范及require.js用法【转】 - loheonly的笔记 - 前端网(W3Cfuns)
  8. 常见ie css hack
  9. css控制元素 水平垂直居中
  10. Java将ip字符串转换成整数的代码
  11. 剑指offer——合并两个排序的链表——对象、引用和赋值初接触
  12. springcloud 笔记
  13. 【iCore4 双核心板_FPGA】例程十三:基于SPI的ARM与FPGA通信实验
  14. python类属性在继承中的修改的影响
  15. easyUI中datebox的格式显示
  16. nwjs 实现的 分块上传
  17. 第五章 二叉树(a)树
  18. delete和truncate操作
  19. 【305】◀▶ ArcPy 相关功能实现
  20. PHP中如何对二维数组按某个键值进行排序

热门文章

  1. 牛客网Java刷题知识点之同步方法和同步代码块的区别(用synchronized关键字修饰)
  2. Spring AOP初步总结(二)
  3. 洛谷 P1902 刺杀大使
  4. SourceInsight主题设置
  5. Power BI 连接到 Azure 账单,自动生成报表,可刷新
  6. Java多态的应用
  7. 《算法图解》中涉及的算法的总结及java实现
  8. 用”人话”解释CNN —— 对单个特征图进行视觉化
  9. postman使用--构建工作流和newman
  10. Android之通过adb shell 模拟器 error: more than one device and emulator 改ip dns