我有一个相当标准的 ipad tableview,我通过向 UITableViewCell.contentView
添加 subview 来放置两行数据。
我想在这个表格的右侧添加一个图像,并让它跨越多行,就像这样(见右图):
现在的问题是,当我滚动表格时,一旦该单元格不再完全显示在 View 中,图像就会被截断,如下所示:
我添加这张图片的方式是
// 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
}
我可以将该图像粘贴在我的 tableview 之外,以覆盖它,但问题是这会使它不可滚动,而我希望它与我的表格一起滚动。
此外,我知道我可能可以将图像左侧的所有其他行放到一行中,就像一个巨大的单元格,但我想尽可能避免这种情况。
最佳答案
您可以通过将 imageView 添加为 tableView 的 subview 来实现。然后它将与单元格一起滚动。
设置它的约束有点棘手,因为你需要让它水平相对于 tableView 的后缘,垂直相对于所需的单元格。
但是,tableView 的尾部约束对其 subview 不起作用,并且在呈现单元格之前您不知道单元格的位置。
所以,一些事情:
我们会将 tableView 嵌入“容器”
UIView
,并将该 View 的尾部约束用于 ImageView 的尾部边缘。我们将创建一个 Top Constraint 变量并在
viewDidAppear()
中设置它的.constant
。
这是一个例子。这都是代码(没有@IBOutlets
)所以只需添加一个新的空 View Controller 并将其类分配给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
}
}
结果:
(使用这张我从你的图片中剪下的图片):
关于ios - UITableView - 让图像跨越多个 UITableViewCells 并滚动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56073115/