簡體   English   中英

以編程方式將按鈕添加到 UIScrollView Swift 5

[英]Add buttons to UIScrollView Swift 5 programmatically

我試圖以編程方式在網格中添加許多按鈕,其中行數超過屏幕大小,所以我希望它們在 UIScrollView 中。

我的最小工作示例如下:

class ViewController: UIViewController {
    
    //center label and down a bit
    let label = UILabel(frame: CGRect(x: UIScreen.main.bounds.width/2 - 100, y: 50, width: 200, height: 200))
    
    // start scroll view underneath label (why not y: 250?)
    let scrollView = UIScrollView(frame: CGRect(x: 0, y: 50, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
    
    override func viewDidLoad() {
        super.viewDidLoad()
                
        // add label to view
        self.view.addSubview(label)
        
        // add Scrollview
        self.view.addSubview(scrollView)
        // uncommenting the following also doesn't work
        //scrollView.contentSize = CGSize(width: UIScreen.main.bounds.width, height: 4000)
        
        // add buttons to scroll view in 5x21 grid
        var idx = 1
        for row in 0...20 {
            for col in 0...4 {
                let button = UIButton(frame: CGRect(x: col*50, y: row*50 + 200, width: 50, height: 50))
                button.backgroundColor = .gray
                button.setTitle("\(idx)", for: .normal)
                button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
                
                // add button to scroll view
                scrollView.addSubview(button)
                
                idx += 1
            }
        }
    }
    
    @objc func buttonAction(sender: UIButton!) {
        label.text = sender.title(for: .normal)
    }

}

不幸的是,滾動不起作用。 即使我明確設置了更大的垂直內容大小(請參閱注釋行) //scrollView.contentSize

我想知道它是否與為固定按鈕設置 x 和 y 值有關? 但是,我還能如何在網格中對齊它們?

那么,如何在獲得工作 ScrollView 的同時獲得我想要的按鈕對齊方式?

我對集合視圖做了同樣的事情,它是滾動視圖的子類,它可以滿足您在行/列方面的需求。

此外,要管理滾動視圖的觸摸,您必須為滾動視圖實現 UIScrollViewDelegate,特別是要區分觸摸和滾動,否則最終可能會出現不可預測的行為。

你真的應該使用自動布局!!!

到目前為止,將按鈕(或任何視圖)添加到滾動視圖的最簡單方法 - 在您要求的網格布局中 - 並讓它自動確定滾動區域是使用堆棧視圖。

這是一個快速示例:

class ViewController: UIViewController {
    
    let label = UILabel()
    let scrollView = UIScrollView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // start with some text in the label
        label.text = "Tap a button"
        
        // center the text in the label
        label.textAlignment = .center
        
        // so we can see the frames
        label.backgroundColor = .yellow
        scrollView.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
        
        // create a vertical stack view to hold the rows of buttons
        let verticalStackView = UIStackView()
        verticalStackView.axis = .vertical

        // we're going to use auto-layout
        label.translatesAutoresizingMaskIntoConstraints = false
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        verticalStackView.translatesAutoresizingMaskIntoConstraints = false

        // add label to view
        self.view.addSubview(label)
        
        // add Scrollview to view
        self.view.addSubview(scrollView)
        
        // add stack view to scrollView
        scrollView.addSubview(verticalStackView)

        // now let's create the buttons and add them
        var idx = 1
        
        for row in 0...20 {
            // create a "row" stack view
            let rowStack = UIStackView()
            // add it to the vertical stack view
            verticalStackView.addArrangedSubview(rowStack)
            
            for col in 0...4 {
                let button = UIButton()
                button.backgroundColor = .gray
                button.setTitle("\(idx)", for: .normal)
                button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
                
                // add button to row stack view
                rowStack.addArrangedSubview(button)
                
                // buttons should be 50x50
                NSLayoutConstraint.activate([
                    button.widthAnchor.constraint(equalToConstant: 50.0),
                    button.heightAnchor.constraint(equalToConstant: 50.0),
                ])
                
                idx += 1
            }
        }

        // finally, let's set our constraints
        
        // respect safe-area
        let safeG = view.safeAreaLayoutGuide

        NSLayoutConstraint.activate([
            
            // constrain label
            //  50-pts from top
            //  80% of the width
            //  centered horizontally
            label.topAnchor.constraint(equalTo: safeG.topAnchor, constant: 50.0),
            label.widthAnchor.constraint(equalTo: safeG.widthAnchor, multiplier: 0.8),
            label.centerXAnchor.constraint(equalTo: safeG.centerXAnchor),
            
            // constrain scrollView
            //  50-pts from bottom of label
            //  Leading and Trailing to safe-area with 8-pts "padding"
            //  Bottom to safe-area with 8-pts "padding"
            scrollView.topAnchor.constraint(equalTo: label.bottomAnchor, constant: 50.0),
            scrollView.leadingAnchor.constraint(equalTo: safeG.leadingAnchor, constant: 8.0),
            scrollView.trailingAnchor.constraint(equalTo: safeG.trailingAnchor, constant: -8.0),
            scrollView.bottomAnchor.constraint(equalTo: safeG.bottomAnchor, constant: -8.0),
            
            // constrain vertical stack view to scrollView Content Layout Guide
            //  8-pts all around (so we have a little "padding")
            verticalStackView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor, constant: 8.0),
            verticalStackView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor, constant: 8.0),
            verticalStackView.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor, constant: -8.0),
            verticalStackView.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor, constant: -8.0),
            
        ])

    }
    
    @objc func buttonAction(sender: UIButton!) {
        label.text = sender.title(for: .normal)
    }
    
}

這是結果:

在此處輸入圖片說明

然后我們將向下滾動並點擊另一個按鈕:

在此處輸入圖片說明

如果你想要按鈕之間的間距,你可以在viewDidLoad()的末尾添加這樣的東西:

// suppose we want 8-pts spacing between the buttons?
verticalStackView.spacing = 8.0
verticalStackView.arrangedSubviews.forEach { v in
    if let stack = v as? UIStackView {
        stack.spacing = 8.0
    }
}

現在它看起來像這樣:

在此處輸入圖片說明

在此處輸入圖片說明

如果您希望按鈕網格水平居中,或者如果您希望調整間距(或按鈕大小)以適應,有幾種不同的方法可以做到這一點......您沒有在問題中描述您的最終目標,但這應該是一個很好的起點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM