问题描述
使用Xib构建了视图A。根据设计需求,B是A的子视图。
这边想在A的layoutSubview方法中,根据业务数据模型动态创建B视图(通过加载B的xib文件),同时获取A的实际尺寸来给B的frame赋值
问题就在于:
在interface builder里看A视图的尺寸是 100 x 100
App运行后第一次加载,在A的layoutSubview里获取的尺寸(self.bounds.width)也确实是 100 x 100
但真正显示到屏幕上后,A的尺寸根据机器的实际屏幕尺寸做了resize,变成了 95 x 95例如,这就导致了后续B视图的布局异常
然而后续再次在A的layoutSubview里获取的尺寸就恒定是 95 x 95了,也就是第一次获取到的尺寸和实际显示尺寸不相等,导致视图第一次显示出来总是布局异常(但后续没有问题)
问题出现的环境背景及自己尝试过哪些方法
视图A是用xib构建的,其中子视图B的宽高使用了AspectRatio,宽度等于实际屏幕-56,也就是说B的宽高是根据实际设备屏幕的尺寸来决定的。
相关代码
`
override func layoutSubviews() {
super.layoutSubviews()
refreshUI()
}
func refreshUI() {
if toolData == nil {
return
}
//先清除之前的
for subView in subItemContainerView.subviews {
subView.removeFromSuperview()
}
itemViewArr.removeAll()
plusViewArr.removeAll()
///就是下面这个h,第一次加载是xib文件中的100,后续就恒定变成某个值例如95,应该是autolayout计算过后的值。这边期望第一次就能获取到resize后的值,保证布局正确。
let h:CGFloat = subItemContainerView.frame.height
let w:CGFloat = h * (ST_375_NEED_ITEM_WIDTH / ST_375_NEED_ITEM_HEIGHT)
let midX:CGFloat = subItemContainerView.bounds.midX
let midY:CGFloat = subItemContainerView.bounds.midY
for subItem in toolData!.needStuffArr {
let itemV = ZSNeedItemView.loadFromXib() as! ZSNeedItemView
// let itemV = UIView()
// itemV.backgroundColor = .red
itemV.imageView?.image = UIImage(named: subItem.imgName)
itemV.titleLabel?.attributedText = ZSNeedItemView.desc(ofNeedItemAndCount: subItem)
subItemContainerView.addSubview(itemV)
itemV.sizeToFit()
itemV.frame = CGRect(x: 0, y: 0, width: w, height: h)
itemV.center = CGPoint(x: midX, y: midY)
itemViewArr.append(itemV)
if subItem != toolData?.needStuffArr.last {
//需要加 + 图片
let plusImgView = UIImageView(image: UIImage(named: "item_plus"))
plusImgView.frame = CGRect(x: 0, y: 0, width: PLUS_IMG_WIDTH, height: PLUS_IMG_HEIGHT)
plusImgView.center = CGPoint(x: midX, y: midY)
subItemContainerView.addSubview(plusImgView);
plusViewArr.append(plusImgView)
}
}
}
`
你期待的结果是什么?实际看到的错误信息又是什么?
这边期望第一次就能获取到xib文件 resize后的真实尺寸值,保证布局正确。
实际看到的错误是,第一次展示A视图,布局总是轻微异常,后续再次加载布局正常(猜是已经resize过了)
补充: 目前这边暂时想到的workaround方法就是,app加载的时候,先把A视图加载到window一次,设置成alpha = 0, 然后再快速remove掉,这样就回避掉了第一次加载布局异常。But,这个方法非常的nasty,求elegant一点的方法。