簡體   English   中英

如何在 tableView Swift(iOS) 上方添加 UIView

[英]How to add UIView above a tableView Swift(iOS)

我正在嘗試在 tableView 上方添加一個 UIview,但我的視圖隱藏在單元格后面。 視圖應該一半在第 0 節的頁腳上,一半在第 1 節的 header 上,空白區域是 header 的填充。

在此處輸入圖像描述

我使用了 bringSubviewToFront 方法,但它不起作用。 我嘗試過的所有內容都在下面評論。

    func setupMyRankView(){
//        tableView.addSubview(myRankView)

//      tableView.footerView(forSection: 0)?.insertSubview(myRankView, aboveSubview: self.view)
//        tableView.footerView(forSection: 0)?.bringSubviewToFront(myRankView)
                self.view.bringSubviewToFront(myRankView)
//        tableView.cellForRow(at: indexPath)?.insertSubview(myRankView, aboveSubview: self.view)
//        tableView.cellForRow(at: indexPath)?.bringSubviewToFront(myRankView)
        
       myRankView.myRankLabel.text = "Hello"
       
    }

嘗試為 header 部分創建自定義 UIView 並將“RankView”添加到此自定義視圖並設置clipToBounds = false (因為您的 RankView 將位於邊界 header 視圖之外)。 然后覆蓋方法 UITableView 委托“viewForHeaderInSection”( 參見官方文檔)並返回您的自定義 header 視圖。

當表格視圖管理它的單元格和節頁眉/頁腳時,它會不斷地重新排列 z 順序。

您需要做的是在每次表更新時將“排名”視圖置於最前面。

一種方法是通過實現表視圖的scrollViewDidScroll這為您提供了一個額外的優勢,即成為計算“排名”視圖的框架的好地方。

它將 go 是這樣的:

  • 當您加載表視圖時,創建一個“排名”視圖數組並將它們添加為表視圖本身的子視圖。
  • scrollViewDidScroll
    • 獲取部分頁腳視圖的右側
    • 獲取下一節的右側 header 視圖
    • 設置“排名”視圖的框架,使其位於各部分之間
    • 將“等級”視圖置於最前面

代碼將如下所示:

    // for each of the "rank" views
    for (i, v) in rankViews.enumerated() {
        // get the rect for the section footer
        var r1 = tableView.rectForFooter(inSection: i)
        // get the rect for the NEXT section header
        let r2 = tableView.rectForHeader(inSection: i + 1)
        
        // set the full rect size to the
        //  Bottom of the Header minus the Top of the Footer
        r1.size.height = r2.maxY - r1.minY
        
        // start with setting the frame of the "rank" view to 50x50
        v.frame = CGRect(x: 0.0, y: 0.0, width: 50.0, height: 50.0)
        // center it horizontonally and vertically
        v.center = CGPoint(x: r1.midX, y: r1.midY)
        
        // bring it to the front
        tableView.bringSubviewToFront(v)
    }

這是您可以嘗試的完整示例...

“排名”視圖示例

class MyRankView: UIView {
    
    let myRankLabel = UILabel()
    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() {
        myRankLabel.textAlignment = .center
        myRankLabel.translatesAutoresizingMaskIntoConstraints = false
        addSubview(myRankLabel)
        let g = self
        NSLayoutConstraint.activate([
            myRankLabel.topAnchor.constraint(equalTo: g.topAnchor, constant: 0.0),
            myRankLabel.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
            myRankLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),
            myRankLabel.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0),
        ])
        layer.borderColor = UIColor.systemGreen.cgColor
        layer.borderWidth = 2
        myRankLabel.textColor = .systemGreen
        backgroundColor = .white
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        layer.cornerRadius = min(bounds.width, bounds.height) * 0.5
    }
}

簡單的多行 label 單元格

class MyTestCell: UITableViewCell {
    
    let theLabel: UILabel = {
        let v = UILabel()
        v.numberOfLines = 0
        return v
    }()
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() -> Void {
        theLabel.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(theLabel)
        let g = contentView.layoutMarginsGuide
        NSLayoutConstraint.activate([
            theLabel.topAnchor.constraint(equalTo: g.topAnchor),
            theLabel.leadingAnchor.constraint(equalTo: g.leadingAnchor),
            theLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor),
            theLabel.bottomAnchor.constraint(equalTo: g.bottomAnchor),
        ])
        theLabel.backgroundColor = .yellow
    }
    
}

可重復使用的節頁眉/頁腳視圖

class MyHeaderFooterBaseView: UITableViewHeaderFooterView {
    
    let label = UILabel()
    override init(reuseIdentifier: String?) {
        super.init(reuseIdentifier: reuseIdentifier)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() {
        label.translatesAutoresizingMaskIntoConstraints = false
        addSubview(label)
        let g = self.layoutMarginsGuide
        NSLayoutConstraint.activate([
            label.topAnchor.constraint(equalTo: g.topAnchor, constant: 8.0),
            label.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
            label.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),
            label.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -8.0),
        ])
        backgroundView = UIView()
    }
}

class MyHeaderView: MyHeaderFooterBaseView {
    override func commonInit() {
        super.commonInit()
        label.textAlignment = .center
        backgroundView?.backgroundColor = .cyan
    }
}

class MyFooterView: MyHeaderFooterBaseView {
    override func commonInit() {
        super.commonInit()
        label.textAlignment = .left
        backgroundView?.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
    }
}

樣品controller

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    let tableView = UITableView(frame: .zero, style: .grouped)
    
    // we'll use varying
    //  number of rows per section and
    //  number of lines per row
    let myData: [[Int]] = [
        [1, 2, 3, 4],
        [3, 2, 1],
        [2, 1, 4, 3, 1],
        [2, 2, 2, 3],
        [1, 1, 5, 1],
        [2, 2, 2],
    ]
    
    var rankViews: [MyRankView] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = .systemYellow
        
        tableView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(tableView)
        
        let g = view.safeAreaLayoutGuide
        
        NSLayoutConstraint.activate([
            
            tableView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
            tableView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            tableView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
            tableView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -20.0),
            
        ])
        
        tableView.register(MyTestCell.self, forCellReuseIdentifier: "c")
        tableView.register(MyHeaderView.self, forHeaderFooterViewReuseIdentifier: "h")
        tableView.register(MyFooterView.self, forHeaderFooterViewReuseIdentifier: "f")
        
        tableView.dataSource = self
        tableView.delegate = self
        
        tableView.sectionHeaderTopPadding = 20.0
        tableView.estimatedSectionHeaderHeight = 60.0
        tableView.estimatedSectionFooterHeight = 60.0
        
        for i in 0..<myData.count - 1 {
            let v = MyRankView()
            v.myRankLabel.text = "\(i)"
            tableView.addSubview(v)
            rankViews.append(v)
        }

    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        updateRankViews()
    }
    func numberOfSections(in tableView: UITableView) -> Int {
        return myData.count
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return myData[section].count
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let c = tableView.dequeueReusableCell(withIdentifier: "c", for: indexPath) as! MyTestCell
        var s: String = "\(indexPath)"
        for i in 2..<(myData[indexPath.section][indexPath.row] + 1) {
            s += "\nLine \(i)"
        }
        c.theLabel.text = s
        return c
    }
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let v = tableView.dequeueReusableHeaderFooterView(withIdentifier: "h") as! MyHeaderView
        v.label.text = "Section Header: \(section)"
        return v
    }
    func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        let v = tableView.dequeueReusableHeaderFooterView(withIdentifier: "f") as! MyFooterView
        v.label.text = "Section Footer: \(section)"
        return v
    }
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        updateRankViews()
    }
    func updateRankViews() {
        
        // for each of the "rank" views
        for (i, v) in rankViews.enumerated() {
            // get the rect for the section footer
            var r1 = tableView.rectForFooter(inSection: i)
            // get the rect for the NEXT section header
            let r2 = tableView.rectForHeader(inSection: i + 1)
            
            // set the full rect size to the
            //  Bottom of the Header minus the Top of the Footer
            r1.size.height = r2.maxY - r1.minY
            
            // start with setting the frame of the "rank" view to 50x50
            v.frame = CGRect(x: 0.0, y: 0.0, width: 50.0, height: 50.0)
            // center it horizontonally and vertically
            v.center = CGPoint(x: r1.midX, y: r1.midY)
            
            // bring it to the front
            tableView.bringSubviewToFront(v)
        }
        
    }
}

運行時看起來像這樣:

在此處輸入圖像描述 在此處輸入圖像描述

將以下代碼添加到項目的 class 的 viewDidLoad() function

let anotherview = UIView()
    anotherview.frame = CGRect(x: 150, y: 200, width: 190, height: 50)
    anotherview.backgroundColor = .red
    self.view.addSubview(anotherview)
    

您可以根據需要添加或更改它。

如果有幫助,請點贊!

暫無
暫無

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

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