相关方法
@property(nonatomic) BOOL autoresizesSubviews; // default is YES. if set, subviews are adjusted according to their autoresizingMask if self.bounds changes
@property(nonatomic) UIViewAutoresizing autoresizingMask; // simple resize. default is UIViewAutoresizingNone
注:parentview设置autoresizesSubviews,subview设置autoresizingMask,parentview.autoresizesSubviews = YES,subview.autoresizingMask才有意义
UIViewAutoresizing
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
x-axis上UIViewAutoresizing可组合值:
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
y-axis上UIViewAutoresizing可组合值:
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
原理
subview在父坐标系x-axis上divide 3个portions:left,width,right
- left:subview左边缘距离父坐标系原点在x-axis上距离,即subview.frame.origin.x,可能为负
- width:subview自身width,即subview.bounds.size.width,恒为正
- right:parentview.bounds.size.width - left - width,可能为负
当parentview.bounds改变(parentview.autoresizesSubviews = YES),根据subview.autoresizingMask值把parentview的bounds.size.width变化量按比例分配到这3个portions上
parentview.bounds.size.width变化量Δwidth = new parentview.bounds.size.width - parentview.bounds.size.width(可能为负)
如果subview.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin,则:
- new left = left + Δwidth * left / (left + width + right)
- new width = width + Δwidth * width / (left + width + right)
- new right = new parentview.bounds.size.width - new left - new width
如果subview.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin,则:
- new left = left + Δwidth * left / (left + right)
- new width = width
- new right = new parentview.bounds.size.width - new left - new width
如果subview.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin,则:
- new left = left + Δwidth * left / left
- new width = width
- new right = new parentview.bounds.size.width - new left - new width
如果subview.autoresizingMask = UIViewAutoresizingNone,则:
- new left = left
- new width = width
- new right = new parentview.bounds.size.width - new left - new width
注:left,width,right,Δwidth都是带符号运算,当然width恒为正,left,right和Δwidth可能为负,left + width + right恒等于parentview.bounds.size.width
subview在父坐标系y-axis上divide 3个portions:top,height,bottom,原理同x-axis,不再赘述
autoresizing局限性
autoresizing是ios为了适应设备屏幕尺寸发生改变时,尽可能的不改变代码而能完美适配所引入的一种简易layout机制,autoresizing核心是同比例缩放,因此适用于设备屏幕尺寸长宽比相同,随着apple后续引入了不同长宽比设备,autoresizing突显了其局限性:
- autoresizing在表示parent view和sub view之间的pos和size关系时能表示的组合非常有限,在x-axis或y-axis一维空间内只能表示有限的8种(1 + 3 + 3 + 1)组合关系,在x-axis和y-axis二维空间内只能表示有限的64种(8 * 8)组合关系,而且只能按某种比例机制,因此不能表示parent view和sub view之间更多更精确的pos和size关系