繁体   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