如何重新调整已创建UIView的Frame?重新添加后布局异常排查
问题分析与解决方案
嘿,我一眼就瞅到几个关键问题,咱们挨个拆解:
1. 最致命的笔误:centerView扩展写错了坐标!
你写的centerView方法里,两次都设置了view.center.y,完全漏掉了水平方向的居中设置!这直接导致你的popUp从来都不会水平居中,更别说移除再添加后了。修正后的扩展应该是:
extension UIView { func centerView(_ view: UIView) { view.center.x = bounds.midX // 这里是x!不是y! view.center.y = bounds.midY } }
2. 手动调用layoutSubviews是错误操作
layoutSubviews是系统负责布局的核心方法,绝对不能手动调用。系统会在视图尺寸变化、添加子视图等合适的时机自动触发它。你手动调用反而会打乱布局流程,尤其是在移除再添加视图时,容易导致布局计算混乱。
3. Frame布局的稳定性问题(以及更优的Auto Layout方案)
你当前用直接设置frame的方式,在视图移除再添加时很容易出问题:
- 移除再添加时,父视图的
bounds可能已经发生变化(比如屏幕旋转、父视图被调整过尺寸),你之前的代码没有重新计算最新的尺寸和位置 - Frame布局是一次性的,后续父视图变化时不会自动更新
如果你坚持用Frame布局,修正后的调用代码应该是:
// 假设需要重新添加popUp时: popUp.removeFromSuperview() // 先移除旧的(如果存在) popUp = UIView(frame: .zero) // 初始化用zero frame superview.addSubview(popUp) // 基于父视图当前的bounds计算尺寸(用bounds而不是frame,避免父视图有transform的情况) let targetSize = superview.bounds.size * 0.9 popUp.frame.size = targetSize // 重新调用居中方法 superview.centerView(popUp) // 如果需要立即更新布局,用这个代替layoutSubviews: // superview.setNeedsLayout() // superview.layoutIfNeeded()
更推荐的Auto Layout方案(一劳永逸)
用Auto Layout约束的话,不管你怎么移除、添加popUp,约束都会自动维护布局,完全不用手动计算位置和尺寸:
// 初始化popUp时设置一次约束即可 popUp = UIView() popUp.translatesAutoresizingMaskIntoConstraints = false // 必须关闭自动转换约束 superview.addSubview(popUp) // 激活约束 NSLayoutConstraint.activate([ // 居中约束 popUp.centerXAnchor.constraint(equalTo: superview.centerXAnchor), popUp.centerYAnchor.constraint(equalTo: superview.centerYAnchor), // 尺寸为父视图的90% popUp.widthAnchor.constraint(equalTo: superview.widthAnchor, multiplier: 0.9), popUp.heightAnchor.constraint(equalTo: superview.heightAnchor, multiplier: 0.9) ])
这样处理后,哪怕你多次移除再添加popUp,只要把它重新加到父视图上,约束就会自动生效,布局始终是正确的。
内容的提问来源于stack exchange,提问作者Hal
相关产品推荐
相关产品推荐

