UITableView-通过滚动使图像跨多个UITableViewCells

时间:2019-05-10 07:55:45

标签: ios swift uitableview

我在ipad上有一个相当标准的表视图,其中通过向<mat-tab>添加子视图来放置两行数据。

我想在此表的右侧添加一个图像,并使其跨多行,如下所示(请参见右侧的图像):

Screenshot

现在的问题是,当我滚动表格时,一旦该单元格不再完全位于视图中,图像就会被截断,如下所示:

Screenshot2

我添加此图像的方式是

UITableViewCell.contentView

我可以将该图像粘贴在表格视图之外,以使其覆盖,但是问题是,这将使其无法滚动,并且我希望它与表格一起滚动。

此外,我知道我可以将图像左侧的所有其他行像一个巨大的单元格一样放入一行,但是如果可能的话,我想避免这种情况。

2 个答案:

答案 0 :(得分:1)

您可以做一件事。将imageViewscrollView并排放置在tableView中。 然后将scrollView's contentOffset设置为等于tableView's contentOffset,反之亦然。

答案 1 :(得分:1)

您可以通过将imageView添加为tableView的子视图来实现。然后它将与单元格一起滚动。

设置其约束有些棘手,因为您需要使其相对于tableView的后沿水平,而垂直于所需的单元格。

但是,tableView的尾随约束对其子视图不太起作用,并且您不知道单元格的位置,直到其被渲染为止。

所以,几件事:

  1. 我们将tableView嵌入“容器” UIView中,并将该视图的尾随约束用于图像视图的后沿。

  2. 我们将创建一个Top Constraint变量,并将其.constant设置为viewDidAppear()

这里是一个例子。全部都是代码(没有@IBOutlets),因此只需添加一个新的空视图控制器并将其类分配给TableWithSubViewViewController

//  TableWithSubViewViewController.swift
//  Created by Don Mag on 5/10/19

class SimpleOneLabelCell: UITableViewCell {

    // very simple one-label tableView cell

    let theLabel: UILabel = {
        let v = UILabel()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.numberOfLines = 0
        return v
    }()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        contentView.addSubview(theLabel)

        NSLayoutConstraint.activate([
            theLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8.0),
            theLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8.0),
            theLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8.0),

            // trailing constraint set to -150, to allow room for our 120x120 imageview (with padding)
            theLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -150.0),
            ])

    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

class TableWithSubViewViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    let theContainerView: UIView = {
        let v = UIView()
        v.translatesAutoresizingMaskIntoConstraints = false
        return v
    }()

    let theTableView: UITableView = {
        let v = UITableView()
        v.translatesAutoresizingMaskIntoConstraints = false
        return v
    }()

    let overlayImageView: UIImageView = {
        let v = UIImageView()
        v.translatesAutoresizingMaskIntoConstraints = false
        return v
    }()

    // top constraint for the image view
    var overlayViewTopConstraint: NSLayoutConstraint = NSLayoutConstraint()

    let reuseID = "SimpleOneLabelCell"

    override func viewDidLoad() {
        super.viewDidLoad()

        theTableView.dataSource = self
        theTableView.delegate = self

        theTableView.register(SimpleOneLabelCell.self, forCellReuseIdentifier: reuseID)

        // set the imageView's image
        if let img = UIImage(named: "overlay") {
            overlayImageView.image = img
        }

        // add the views
        view.addSubview(theContainerView)
        theContainerView.addSubview(theTableView)
        theTableView.addSubview(overlayImageView)

        // constrain the top of the imageView above the top of the tableView
        //   we'll change the constant in viewDidAppear()
        overlayViewTopConstraint = overlayImageView.topAnchor.constraint(equalTo: theTableView.topAnchor, constant: -120.0)

        NSLayoutConstraint.activate([

            // constrain containerView to all 4 sides (safe-area)
            theContainerView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            theContainerView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
            theContainerView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
            theContainerView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),

            // constrain tableView to all 4 sides of constainerView
            theTableView.topAnchor.constraint(equalTo: theContainerView.topAnchor),
            theTableView.bottomAnchor.constraint(equalTo: theContainerView.bottomAnchor),
            theTableView.leadingAnchor.constraint(equalTo: theContainerView.leadingAnchor),
            theTableView.trailingAnchor.constraint(equalTo: theContainerView.trailingAnchor),

            // constrain the imageView using the Top Constraint we already created, plus
            overlayViewTopConstraint,

            // 20-pts from the right (trailing) edge of the Container View, plus
            overlayImageView.trailingAnchor.constraint(equalTo: theContainerView.trailingAnchor, constant: -20.0),

            // width and height at 120-pt constants
            overlayImageView.widthAnchor.constraint(equalToConstant: 120.0),
            overlayImageView.heightAnchor.constraint(equalToConstant: 120.0),
            ])

    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        // at this point we have the table and its initial cells laid out, so we can use it for
        //  vertical positioning of the image view
        if let c = theTableView.cellForRow(at: IndexPath(row: 1, section: 0)) as? SimpleOneLabelCell {

            // get the frame of the cell on row 1
            let f = c.frame

            // add half-cell-height to the origin.y
            var y = f.origin.y + (f.size.height * 0.5)

            // get the frame of the image view
            let r = overlayImageView.frame

            // subtract half-imageView-height
            y -= (r.height * 0.5)

            // update imageView's top constraint
            overlayViewTopConstraint.constant = y

        }

    }

    // MARK: - Table view data source

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 20
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: reuseID, for: indexPath) as! SimpleOneLabelCell

        cell.theLabel.text = "\(indexPath)\nLine 2\nLine 3"

        return cell
    }

}

结果:

enter image description here

enter image description here

(使用我从您的图片中剪出的这张图片):

enter image description here