在子子视图中获取视图的框架
Getting frame of a view in a sub-subview
所以,让我试着解释一下发生了什么。所以,我有这个视图结构:
ViewController
HeaderView -> Subview of ViewController
MenuView -> Subview of HeaderView
我在每个视图中使用自动布局。
我的问题是在 MenuView 中,当我尝试使用框架大小来锚定一些视图时,框架仍然是 0.0,因此它没有布局任何东西,我认为这可能是因为它仍然没有从 ViewController, 因为我在 HeaderView 里面布局 MenuView 的时候, 也是用到了 frame size.
有什么帮助吗?
编辑:
顺便说一下,界限也是 0.0
代码:
HeaderController
lazy var headerView: HeaderView = {
let hv = HeaderView(maxHeight: self.maxHeight, medHeight: self.medHeight, minHeight: self.minHeight, paddingBetween: 10)
return hv
}()
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
tableView.delegate = self
tableView.dataSource = self
headerView.headerControllerDelegate = self
}
func setupViews() {
addSubview(collectionView)
addSubview(lineView)
bringSubview(toFront: lineView)
_ = collectionView.anchor(top: topAnchor, bottom: bottomAnchor, right: rightAnchor, left: leftAnchor)
lineViewLeftAnchor = lineView.anchor(top: nil, bottom: bottomAnchor, right: nil, left: leftAnchor, topConstant: 0, bottomConstant: 0, rightConstant: 0, leftConstant: 0, widthConstant: frame.size.width / 4, heightConstant: 1.5)[1]
}
}
HeaderView
let menuView: MenuView = {
let mv = MenuView()
return mv
}()
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = Theme.PRIMARY_DARK_COLOR
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
convenience init(maxHeight: CGFloat, medHeight: CGFloat, minHeight: CGFloat, paddingBetween containerPadding: CGFloat) {
self.init(frame: CGRect.zero)
self.maxHeight = maxHeight
self.medHeight = medHeight
self.minHeight = minHeight
self.containerPadding = containerPadding
collapseBtn.addTarget(self, action: #selector(handleCollapse), for: .touchUpInside)
setupViews()
}
func setupViews() {
addSubview(menuView)
_ = menuView.anchor(top: menuContainer.topAnchor, bottom: menuContainer.bottomAnchor, right: menuContainer.rightAnchor, left: menuContainer.leftAnchor)
}
菜单视图
extension MenuView: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as? MenuCell {
cell.menuLabel.text = menuItems[indexPath.row]
cell.menuLabel.textColor = fontColor
return cell
}
return UICollectionViewCell()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return menuItems.count
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: frame.size.width / 4, height: frame.size.height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
这不是全部代码,但我认为这是重要的部分。
这个问题需要更多的背景信息,但您是在尝试获取代码中的帧大小,还是在声明视图未按照其约束进行布局。
如果它在代码中,您需要注意 frame.size
在调用 viewDidAppear
之前不可用。
最明显的解决方案是在 MenuView
的 layoutSubviews
函数中获取 HeaderView
的框架。
但是为什么要得到 HeaderView
的大小呢?在自动布局中,您使用 UI 元素之间的关系来安排应用程序的 UI,因此您不应该关心框架的具体值。
更新:
正确的解决方案是在集合视图的边界发生变化时使您的布局无效。
您必须覆盖 shouldInvalidateLayout(forBoundsChange:)
和 return true
。
并在MenuView
的layoutSubviews
中调用collectionView
的invalidateLayout
。
所以,让我试着解释一下发生了什么。所以,我有这个视图结构:
ViewController
HeaderView -> Subview of ViewController
MenuView -> Subview of HeaderView
我在每个视图中使用自动布局。
我的问题是在 MenuView 中,当我尝试使用框架大小来锚定一些视图时,框架仍然是 0.0,因此它没有布局任何东西,我认为这可能是因为它仍然没有从 ViewController, 因为我在 HeaderView 里面布局 MenuView 的时候, 也是用到了 frame size.
有什么帮助吗?
编辑: 顺便说一下,界限也是 0.0
代码:
HeaderController
lazy var headerView: HeaderView = {
let hv = HeaderView(maxHeight: self.maxHeight, medHeight: self.medHeight, minHeight: self.minHeight, paddingBetween: 10)
return hv
}()
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
tableView.delegate = self
tableView.dataSource = self
headerView.headerControllerDelegate = self
}
func setupViews() {
addSubview(collectionView)
addSubview(lineView)
bringSubview(toFront: lineView)
_ = collectionView.anchor(top: topAnchor, bottom: bottomAnchor, right: rightAnchor, left: leftAnchor)
lineViewLeftAnchor = lineView.anchor(top: nil, bottom: bottomAnchor, right: nil, left: leftAnchor, topConstant: 0, bottomConstant: 0, rightConstant: 0, leftConstant: 0, widthConstant: frame.size.width / 4, heightConstant: 1.5)[1]
}
}
HeaderView
let menuView: MenuView = {
let mv = MenuView()
return mv
}()
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = Theme.PRIMARY_DARK_COLOR
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
convenience init(maxHeight: CGFloat, medHeight: CGFloat, minHeight: CGFloat, paddingBetween containerPadding: CGFloat) {
self.init(frame: CGRect.zero)
self.maxHeight = maxHeight
self.medHeight = medHeight
self.minHeight = minHeight
self.containerPadding = containerPadding
collapseBtn.addTarget(self, action: #selector(handleCollapse), for: .touchUpInside)
setupViews()
}
func setupViews() {
addSubview(menuView)
_ = menuView.anchor(top: menuContainer.topAnchor, bottom: menuContainer.bottomAnchor, right: menuContainer.rightAnchor, left: menuContainer.leftAnchor)
}
菜单视图
extension MenuView: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as? MenuCell {
cell.menuLabel.text = menuItems[indexPath.row]
cell.menuLabel.textColor = fontColor
return cell
}
return UICollectionViewCell()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return menuItems.count
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: frame.size.width / 4, height: frame.size.height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
这不是全部代码,但我认为这是重要的部分。
这个问题需要更多的背景信息,但您是在尝试获取代码中的帧大小,还是在声明视图未按照其约束进行布局。
如果它在代码中,您需要注意 frame.size
在调用 viewDidAppear
之前不可用。
最明显的解决方案是在 MenuView
的 layoutSubviews
函数中获取 HeaderView
的框架。
但是为什么要得到 HeaderView
的大小呢?在自动布局中,您使用 UI 元素之间的关系来安排应用程序的 UI,因此您不应该关心框架的具体值。
更新:
正确的解决方案是在集合视图的边界发生变化时使您的布局无效。
您必须覆盖 shouldInvalidateLayout(forBoundsChange:)
和 return true
。
并在MenuView
的layoutSubviews
中调用collectionView
的invalidateLayout
。