如何在表格上方添加UIView查看Swift(iOS)

vhmi4jdf  于 2023-01-03  发布在  iOS
关注(0)|答案(3)|浏览(103)

我试图在tableView上方添加一个UI视图,但是视图隐藏在单元格后面。视图应该一半在第0节的页脚,一半在第1节的页眉,空白区域是页眉的填充。

我已经使用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"
       
    }
u5rb5r59

u5rb5r591#

尝试为页眉部分创建自定义UIView,并将“RankView”添加到此自定义视图,并设置clipToBounds = false(因为您的RankView将位于页眉视图的边界之外)。然后重写方法UITableView委托“viewForHeaderInSection”(https://developer.apple.com/documentation/uikit/views_and_controls/table_views/adding_headers_and_footers_to_table_sections)并返回自定义页眉视图。

ma8fv8wu

ma8fv8wu2#

当表格视图管理其单元格和节页眉/页脚时,它会不断地重新排列Z顺序。
您需要做的是在每次表更新时将“排名”视图放在前面。
实现这一点的一种方法是实现表视图的scrollViewDidScroll--这给您带来了额外的好处,它是计算“等级”视图的帧的好地方。
它会是这样的:

  • 加载表视图时,创建一个“等级”视图数组,并将它们作为表视图本身的子视图添加。
  • scrollViewDidScroll
  • 获取节页脚视图的矩形
  • 获取下一节标题视图的矩形
  • 设置“等级”视图的框架,使其位于各部分之间
  • 把“等级”观拉到前面

代码如下所示:

// 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
    }
}

简单多行标签单元格

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)
    }
}

样品控制器

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)
        }
        
    }
}

运行时是这样的:
第一节第一节第一节第一节第一次

e3bfsja2

e3bfsja23#

将以下代码添加到项目类的viewDidLoad()函数中

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

您可以根据需要添加或更改。
如果有帮助请投票!

相关问题