【问题标题】:UIView width/height within UIStackView using Swift使用 Swift 的 UIStackView 中的 UIView 宽度/高度
【发布时间】:2020-09-26 04:02:20
【问题描述】:

我试图让 UICollectionView 保持一个正方形(尽可能大),无论哪个方向或 iOS 设备。我正在使用具有两个垂直管理视图的 UIStackView。顶视图是其中包含 UICollectionView 的视图,并且是 GameView。 GameView 设置为拥抱顶部、两侧和第二个视图(始终设置为 150 高)。这是我目前拥有的代码:

if UIScreen.main.applicationFrame.size.width > UIScreen.main.applicationFrame.size.height {
        
        theCollection.frame.size.width = GameView.frame.size.height - 46
        theCollection.frame.size.height = GameView.frame.size.height - 46
        
        theCollection.frame.origin.y = 23
        theCollection.frame.origin.x = 23
        
        
    } else {
        
        theCollection.frame.size.width = GameView.frame.size.width - 46
        theCollection.frame.size.height = GameView.frame.size.width - 46
        
        theCollection.frame.origin.y = 23
        theCollection.frame.origin.x = 23
        
    }

但是,这会导致 UICollectionView 比应有的小得多。当我查看所有构建后的大小时,调试器会打印出 GameView 只有 414 宽,即使屏幕是 768 宽(我已经在 GameView 上放置了彩色背景,它显示它像在模拟器中一样拥抱所有侧面)。

为什么我的 GameView 以编程方式比在模拟器上的视觉宽度要小?

【问题讨论】:

    标签: swift uiview uicollectionview uistackview


    【解决方案1】:

    首先,您不需要将框架设置为显式值...使用约束并让自动布局为您完成所有工作。

    其次,如果你希望你的collectionView是Square,当视图的高度很短时它会变得非常小——比如手机旋转到横向:

    这是获取该布局的示例代码:

    class GameViewController: UIViewController, UICollectionViewDataSource {
    
        let stack: UIStackView = {
            let v = UIStackView()
            v.axis = .vertical
            v.alignment = .fill
            v.distribution = .fill
            v.spacing = 0
            return v
        }()
        
        let gameContainerView = UIView()
        let secondView = UIView()
        
        var theCollection: UICollectionView!
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
            layout.itemSize = CGSize(width: 50, height: 50)
            layout.minimumLineSpacing = 4
            layout.minimumInteritemSpacing = 4
            theCollection = UICollectionView(frame: .zero, collectionViewLayout: layout)
            theCollection.translatesAutoresizingMaskIntoConstraints = false
    
            stack.addArrangedSubview(gameContainerView)
            stack.addArrangedSubview(secondView)
            
            stack.translatesAutoresizingMaskIntoConstraints = false
            
            view.addSubview(stack)
            
            // respect safe area
            let g = view.safeAreaLayoutGuide
            
            NSLayoutConstraint.activate([
                
                // constrain stack view to fill safe area
                stack.topAnchor.constraint(equalTo: g.topAnchor),
                stack.leadingAnchor.constraint(equalTo: g.leadingAnchor),
                stack.trailingAnchor.constraint(equalTo: g.trailingAnchor),
                stack.bottomAnchor.constraint(equalTo: g.bottomAnchor),
                
                // second view always has a height of 150
                secondView.heightAnchor.constraint(equalToConstant: 150.0),
                
            ])
    
            // add collection view to game container view
            gameContainerView.addSubview(theCollection)
            
            NSLayoutConstraint.activate([
                
                // it looks like you want the collection view to be square (1:1 ratio)
                //  as large as possible
                //  with 23-pts on top/bottom or left/right, whichever is needed
                
                // give it a 1:1 ratio
                theCollection.heightAnchor.constraint(equalTo: theCollection.widthAnchor),
                
                // centered in container view
                theCollection.centerXAnchor.constraint(equalTo: gameContainerView.centerXAnchor),
                theCollection.centerYAnchor.constraint(equalTo: gameContainerView.centerYAnchor),
                
                // we need *at least* 23-pts "padding"
                theCollection.topAnchor.constraint(greaterThanOrEqualTo: gameContainerView.topAnchor, constant: 23.0),
                theCollection.leadingAnchor.constraint(greaterThanOrEqualTo: gameContainerView.leadingAnchor, constant: 23.0),
                theCollection.trailingAnchor.constraint(lessThanOrEqualTo: gameContainerView.trailingAnchor, constant: -23.0),
                theCollection.bottomAnchor.constraint(lessThanOrEqualTo: gameContainerView.bottomAnchor, constant: -23.0),
    
            ])
            
            // we also need to constrain the collection view's
            //  Height and Width equal to the container's Height and Width
            //  but with Priority less than Required
            let w = theCollection.widthAnchor.constraint(equalTo: gameContainerView.widthAnchor)
            let h = theCollection.heightAnchor.constraint(equalTo: gameContainerView.heightAnchor)
            w.priority = .defaultHigh
            h.priority = .defaultHigh
            w.isActive = true
            h.isActive = true
    
            // set background colors so we can easily see the frames
            theCollection.backgroundColor = .cyan
            gameContainerView.backgroundColor = .green
            secondView.backgroundColor = .yellow
            
            theCollection.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")
            theCollection.dataSource = self
        }
    
        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return 42
        }
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
            cell.backgroundColor = .blue
            return cell
        }
        
    }
    

    【讨论】:

    • 所以,我尝试了您在此处列出的方法,但发现它并不总是有效。在这种情况下它不起作用,因为由于某种原因,堆栈内的视图最终没有堆栈宽,即使我设置了约束以使其始终如此。我的问题不是使盒子成为正确大小的正方形不起作用,而是堆栈内的视图导致它不正确,因为它没有超出堆栈的边缘。
    • @user14337541 - 我不明白......当你运行这个示例代码时,你得到了你想要的结果吗?如果没有,您需要更详细地解释问题所在(与您想要的结果相比,您得到的一些屏幕截图会有所帮助)。
    猜你喜欢
    • 2021-06-13
    • 2019-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-15
    相关资源
    最近更新 更多