UITableView - изображение имеет несколько UITableViewCells с прокруткой - PullRequest
1 голос
/ 10 мая 2019

У меня довольно стандартное табличное представление для ipad, где я размещаю две строки данных, добавляя подпредставления к UITableViewCell.contentView.

Я хочу добавить изображение в правую часть этой таблицы, чтобы оно занимало несколько строк, как показано ниже (см. Изображение справа):

Screenshot

Теперь проблема в том, что когда я прокручиваю свою таблицу, изображение обрезается, как только эта ячейка перестает быть полностью в представлении, выглядит так:

* +1012 *Screenshot2

Способ добавления этого изображения:

// priority 999 helps save a lot of headache on troubleshooting auto layout warnings for code created views
extension NSLayoutConstraint {
    func activateWithPriority(_ val: Float) {
        self.priority = UILayoutPriority(val)
        self.isActive = true
    }

    func activateWithBasicPriority() {
        self.priority = UILayoutPriority(999)
        self.isActive = true
    }
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) ?? UITableViewCell()

        if !cell.contentView.subviews.isEmpty {
            for sv in cell.contentView.subviews {
                sv.removeFromSuperview()
            }
        }

        if indexPath.row == 1 {
            let image = UIImageView(image: UIImage(named: "product_placeholder"))
            image.translatesAutoresizingMaskIntoConstraints = false
            cell.contentView.addSubview(image)

            image.widthAnchor.constraint(equalToConstant: 200).activateWithBasicPriority()
            image.heightAnchor.constraint(equalToConstant: 200).activateWithBasicPriority()
            image.rightAnchor.constraint(equalTo: cell.contentView.rightAnchor, constant: -10).activateWithBasicPriority()
            image.topAnchor.constraint(equalTo: cell.contentView.topAnchor, constant: 10).activateWithBasicPriority()
        }

// other stuff here

return cell

}

Я мог бы просто вставить это изображение за пределы моего табличного представления, чтобы наложить его, но проблема в том, что это сделало бы его недоступным для прокрутки, и я хочу, чтобы оно прокручивалось вместе с моей таблицей.

Кроме того, я знаю, что, вероятно, я могу поместить все остальные строки слева от изображения в один ряд с массивной ячейкой, но я хочу избежать этого, если это возможно.

Ответы [ 2 ]

1 голос
/ 10 мая 2019

Вы можете сделать это, добавив свой 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

1 голос
/ 10 мая 2019

Вы можете сделать одну вещь. положить imageView внутрь scrollView рядом tableView. и установите scrollView's contentOffset равным tableView's contentOffset и наоборот.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...