【OC梳理】自动布局

栏目: IOS · 发布时间: 7年前

内容简介:相信许多比较少使用自动布局的同学对下面的参数都感觉比较头疼:其实不难,请往下看: #####Content Hugging Priority : 抗拉伸优先级 最常见的情况是两个label并排放置,并设置水平间距:报错了?莫慌,当两个label的文字长度加上水平间距不足以填满父视图时,需要设置抗拉伸优先级。 解决办法:假设我们不希望Label1被拉伸,则将其Hugging Priority值调大(默认为251)

相信许多比较少使用自动布局的同学对下面的参数都感觉比较头疼:

【OC梳理】自动布局

其实不难,请往下看: #####Content Hugging Priority : 抗拉伸优先级 最常见的情况是两个label并排放置,并设置水平间距:

【OC梳理】自动布局

报错了?莫慌,当两个label的文字长度加上水平间距不足以填满父视图时,需要设置抗拉伸优先级。 解决办法:假设我们不希望Label1被拉伸,则将其Hugging Priority值调大(默认为251)

【OC梳理】自动布局

调整后,修改label1的文字,其长度随之变化:

【OC梳理】自动布局
【OC梳理】自动布局
【OC梳理】自动布局

然后我们在调整的过程中会发现:

【OC梳理】自动布局

又报错了? 接着往下看: #####Content Compression Resistance Priority : 抗压缩优先级 当两个label的文字长度加上水平间距超出了父视图宽度时,需要设置抗压缩优先级。 解决办法:假设我们希望Label1的内容尽可能地展示完全,则将其Resistance Priority值调大(默认为750)

【OC梳理】自动布局

调整后:

【OC梳理】自动布局

可以看到,Label2直接被压没了。 我们把Label2的Resistance Priority值调大:

【OC梳理】自动布局

调整后:

【OC梳理】自动布局

经过上面的过程后,对于如何使用自动布局做出下图的效果,是不是就心里有数了呢:

【OC梳理】自动布局

PS: 抗压缩、抗拉伸优先级同样适用于与父视图的约束优先级(默认值1000) 熟悉了xib中的优先级设置后,在Masonry中对应优先级的思路相同,使用方法 - (void)setContentCompressionResistancePriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis; 进行对应设置(系统自带方法,不是Masonry加的)。

内容尺寸(Intrinsic Content Size)

某些用来展现内容的用户控件,例如文本控件UILabel、按钮UIButton、图片视图UIImageView等,它们具有自身内容尺寸(对于UIImageView,其自身内容尺寸就是图片(1倍图)的尺寸)。

如何设置自定义控件的内容尺寸?

我们可以通过重写 - (CGSize)intrinsicContentSize 方法来指定内容尺寸。 先来看看UIView默认的返回值:

- (CGSize)intrinsicContentSize{
    return CGSizeMake(UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric);
}
复制代码

这个方法的作用是当使用已有约束不能够计算出内容宽度/高度时,自动为视图添加宽度/高度约束,其值为返回值中对应的宽/高。 因此我们可以在这个方法中返回计算好的内容大小。

我们在xib中也可以看到下面的参数(需要注意的是,在这里设置的size仅仅只用于xib中展示效果,实际运行时并没有什么卵用):

【OC梳理】自动布局

知道了intrinsicContentSize的用法后,我们考虑一下下面的需求:

写一个自定义的View,满足下面的功能:

  • 如果未使用约束,直接显示frame的大小即可;
  • 如果添加了能够定位左上角点坐标的约束,则使用默认的内容大小。
  • 如果添加了能够定位左上角点坐标以及能够计算出宽/高其中一个数值时,使用宽/高的另一个默认值。
  • 如果添加了能够计算出全部frame值的约束,则不使用默认内容大小。

整体效果类似UILabel,但是这里简化成固定的默认尺寸。

【OC梳理】自动布局

这里给出一个简单的demo仅供参考:

@interface DemoView()

@property (nonatomic,assign) CGSize defaultSize;

@end

@implementation DemoView {
    BOOL _widthConstraintAdded;
    BOOL _heightConstraintAdded;
    float _widthConstrant;
    float _heightConstrant;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder{
    self = [super initWithCoder:aDecoder];
    if (self) {
        _widthConstraintAdded = _heightConstraintAdded = NO;
        _widthConstrant = self.defaultSize.width;
        _heightConstrant = self.defaultSize.height;
    }
    return self;
}

- (void)layoutSubviews{
    [super layoutSubviews];
    // 是否使用了自动布局
    if (self.constraints.count > 0) {
        // 判断是否添加了可以计算出宽度/高度的约束
        if (self.frame.size.width != _widthConstrant) {
            _widthConstraintAdded = YES;
        }
        if (self.frame.size.height != _heightConstrant) {
            _heightConstraintAdded = YES;
        }
        // 计算缺少的宽/高
        // 计算时可以使用self.frame.size,这个size是自动布局调整后的size了
        if (!_widthConstraintAdded) {
            // 计算宽度的代码...
            _widthConstrant = 10;
        }
        if (!_heightConstraintAdded) {
            // 计算高度的代码...
            _heightConstrant = 10;
        }
        // 添加约束
        if (!CGSizeEqualToSize(self.frame.size, [self intrinsicContentSize])) {
            [self invalidateIntrinsicContentSize];
        }
    }
}

- (CGSize)intrinsicContentSize{
    return CGSizeMake(_widthConstrant, _heightConstrant);
}

- (CGSize)defaultSize{
    if (CGSizeEqualToSize(_defaultSize, CGSizeZero)) {
        // 计算默认内容宽高的代码
        float width = 100;
        float height = 20;
        _defaultSize = CGSizeMake(width, height);
    }
    return _defaultSize;
}
@end
复制代码

ScrollView的自动内容大小

我们看下面的布局:

【OC梳理】自动布局

当我们需要Label2可以显示多行数据时,仅仅设置右边距是不够的:

【OC梳理】自动布局

我们可以让Label2的宽度等于Scrollview的宽度减去左右边距之和:

【OC梳理】自动布局

看看效果:

【OC梳理】自动布局

效果出来了,但是仅仅这样我们发现不能上下滚动,因为没有设置底部间距,scrollview无法计算出内容高度,需要给最下面的view(Label2)添加底部间距:

【OC梳理】自动布局

看看效果:

【OC梳理】自动布局

下面考虑更进一步的需求:Label1也要可以显示多行时的情况。 我们把Label1右边与Label2对齐,然后改一下内容文字:

【OC梳理】自动布局

OK大功告成。

PS:如果使用Tablview时用到Cell的自动高度(不管是用系统自带还是UITableView+FDTemplateLayoutCell),也都需要设置好约束,让它能够计算出竖直方向的内容高度(水平方向tableview不需要,collectionView需要),具体过程和上面类似。

自定义View与自动布局

我们看一个样式:

【OC梳理】自动布局

要实现这一样式的方式有很多种,这里我们考虑用UILabel的子类直接实现的情况(尽可能少的View):

【OC梳理】自动布局

UIView中有这一个类方法: + (Class)layerClass; ,该方法返回的就是view.layer的类型,因此我们可以使用自定义的Layer替换掉默认的Layer,然后裁剪出对应的形状(原理比较简单,直接上代码了):

@interface DemoLabelLayer : CAShapeLayer

@end

@implementation DemoLabelLayer

- (void)layoutSublayers{
    [super layoutSublayers];
    [self setBackgroundPath];
}

- (void)setBackgroundPath{
    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    shapeLayer.fillColor = [UIColor whiteColor].CGColor;
    shapeLayer.fillRule = kCAFillRuleEvenOdd;
    shapeLayer.path = [self backgroundPathFrame:self.bounds].CGPath;
    self.mask = shapeLayer;
}

- (UIBezierPath *)backgroundPathFrame:(CGRect)frame{
    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:frame byRoundingCorners:UIRectCornerTopRight|UIRectCornerBottomRight cornerRadii:CGSizeMake(self.cornerRadius, self.cornerRadius)];
    return path;
}

@end

@interface DemoView()

@end

@implementation DemoView

- (void)awakeFromNib{
    [super awakeFromNib];
}

- (void)layoutSubviews{
    [super layoutSubviews];
    DemoLabelLayer *layer = (DemoLabelLayer *)self.layer;
    layer.backgroundColor = self.backgroundColor.CGColor;
    layer.cornerRadius = self.frame.size.height/2.f;
}

+ (Class)layerClass{
    return [DemoLabelLayer class];
}

@end
复制代码

自动布局的动画

对于需要进行frame动态调整的界面,许多小伙伴都不知道该如何使用自动布局进行动画而放弃,其实不难:

如果使用xib或者代码创建,最简单的方式就是将约束设置成对应属性,直接修改约束的 constant 即可。

如果使用Masonry创建布局,那么只需要使用下面的代码就可以使用动画效果了:

// 如果其约束还没有生成的时候需要动画的话,就请先强制刷新后才写动画,否则所有没生成的约束会直接跑动画
[view.superview layoutIfNeeded];
[UIView animateWithDuration:3 animations:^{
  [view mas_updateConstraints:^(MASConstraintMaker *make) {
    make.height.mas_equalTo(123);
  }];
}];
// 强制绘制
[view.superview layoutIfNeeded];
复制代码

记得动画前后需要刷新。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Learning PHP 5

Learning PHP 5

David Sklar / O'Reilly / July, 2004 / $29.95

Learning PHP 5 is the ideal tutorial for graphic designers, bloggers, and other web crafters who want a thorough but non-intimidating way to understand the code that makes web sites dynamic. The book ......一起来看看 《Learning PHP 5》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

MD5 加密
MD5 加密

MD5 加密工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具