UIView使用Swift查看范围内的宽度/高度

UIView使用Swift查看范围内的宽度/高度,swift,uiview,uicollectionview,uistackview,Swift,Uiview,Uicollectionview,Uistackview,我试图让UICollectionView保持正方形(尽可能大),而不管是哪个方向或iOS设备。我使用的是一个垂直管理两个视图的UIStackView。俯视图是其中包含UICollectionView的视图,是GameView。GameView设置为拥抱顶部、两侧和第二个视图(始终设置为150高)。这是我目前拥有的代码: if UIScreen.main.applicationFrame.size.width > UIScreen.main.applicationFrame.size.hei

我试图让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在编程上不如在模拟器上直观显示的那么宽?

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

其次,如果您希望collectionView为方形,则当视图高度较短时,它将非常小,例如手机旋转为横向:

下面是获得该布局的示例代码:

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-我不明白。。。当您运行这个示例代码时,您是否得到了期望的结果?如果没有,你需要更详细地解释问题是什么(一些屏幕上显示的与你想要的结果相比较的内容会有帮助)。