我在单元格内部实现了一个带有scrollview的tableview。单元格由两个视图组成,第二个视图(以绿色显示)在滑动后出现:
我现在要实现的是,当单元格向右滑动时,单元格高度会逐渐扩展。因此,当我开始向右滑动单元格并且绿色子视图在主屏幕上变得可见时,我希望单元格的高度增加,直到绿色子视图完全可见。然后当我向左滑动时,一切都恢复正常。
由于UITableViewCell符合滚动视图委托,我怀疑我在我的单元子类中编写了一些代码 - 也许使用scrollViewDidScroll使用滚动视图的contentOffset.y
。
答案 0 :(得分:3)
这是一个使用自动布局和自动调整单元格的示例(Swift 3)。不确定你打算如何开始"开始"绿色视图,所以这个演示将它初始化为40磅宽(高度包含在宽度的50%)。
您可以简单地创建一个新的.swift文件并粘贴它,然后在Storyboard中添加一个UITableViewController并将其类指定给StretchCellTableViewController
。其他一切都是在代码中创建的......不需要IBOutlets。
//
// StretchCellTableViewController.swift
// SWTemp2
//
// Created by Don Mag on 6/22/17.
// Copyright © 2017 DonMag. All rights reserved.
//
import UIKit
class NonStretchCell: UITableViewCell {
// pretty standard one-label cell
var theLabel: UILabel!
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupCell()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupCell()
}
func setupCell() {
theLabel = UILabel()
theLabel.font = UIFont.systemFont(ofSize: 16.0, weight: UIFontWeightLight)
theLabel.numberOfLines = 0
theLabel.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(theLabel)
theLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 8.0).isActive = true
theLabel.topAnchor.constraint(equalTo: self.topAnchor, constant: 6.0).isActive = true
theLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -6.0).isActive = true
theLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -8.0).isActive = true
}
}
class StretchCell: UITableViewCell {
var stretchView: UIView!
var widthConstraint: NSLayoutConstraint!
var scaleAction : ((CGFloat)->())?
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupCell()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupCell()
}
func setBarWidth(_ w: CGFloat) -> Void {
widthConstraint.constant = w
}
func setupCell() {
// instantiate the view
stretchView = UIView()
stretchView.translatesAutoresizingMaskIntoConstraints = false
stretchView.backgroundColor = .green
// add it to self (the cell)
self.addSubview(stretchView)
// "pin" it to top, bottom and left
stretchView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0.0).isActive = true
stretchView.topAnchor.constraint(equalTo: self.topAnchor, constant: 0.0).isActive = true
stretchView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0.0).isActive = true
// set height constraint to be 50% of the width
stretchView.heightAnchor.constraint(equalTo: stretchView.widthAnchor, multiplier: 0.5).isActive = true
// instantiate the width constraint
widthConstraint = NSLayoutConstraint(item: stretchView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 40)
// needs priority of 999 so auto-layout doesn't complain
widthConstraint.priority = 999
// activate the width constraint
NSLayoutConstraint.activate([widthConstraint])
// create a UIPanGestureRecognizer and add it to the stretch view
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(didPan(sender:)))
stretchView.addGestureRecognizer(panGesture)
}
func didPan(sender: UIPanGestureRecognizer) {
let loc = sender.location(in: self)
if sender.state == .began {
// if you want to do something on drag start...
//print("Gesture began")
} else if sender.state == .changed {
//print("Gesture is changing", loc)
// update the width of the stretch view (but keep it at least 20-pts wide, so it doesn't disappear)
// height is set to 1:1 so it updates automatically
widthConstraint.constant = max(loc.x, 20)
// call back to the view controller
scaleAction?(widthConstraint.constant)
} else if sender.state == .ended {
// if you want to do something on drag end...
//print("Gesture ended")
}
}
}
class StretchCellTableViewController: UITableViewController {
// array to track the bar widths, assuming we have more than one row with a bar
// only a few rows will have the "stretch bar" - but for this example we'll just track a barWidth for *every* row
var barWidths = [CGFloat]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 80
tableView.register(StretchCell.self, forCellReuseIdentifier: "StretchCell")
tableView.register(NonStretchCell.self, forCellReuseIdentifier: "NonStretchCell")
// init array for barWidths... initial value: 40, 30 slots
barWidths = Array(repeating: 40, count: 30)
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return barWidths.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// just make every 5th row a "Stretch" cell (starting at #3)
if indexPath.row % 5 == 3 {
let cell = tableView.dequeueReusableCell(withIdentifier: "StretchCell", for: indexPath) as! StretchCell
cell.selectionStyle = .none
// cells are reused, so set the bar width to our saved value
cell.setBarWidth(barWidths[indexPath.row])
// "call-back" function
cell.scaleAction = {
(newWidth) in
// update the bar width in our tracking array
self.barWidths[indexPath.row] = newWidth
// disable Animations, because we're changing the size repeatedly
UIView.setAnimationsEnabled(false)
// wrap begin/end updates() to force row-height re-calc
self.tableView.beginUpdates()
self.tableView.endUpdates()
// re-enable Animations
UIView.setAnimationsEnabled(true)
}
cell.preservesSuperviewLayoutMargins = false
cell.separatorInset = UIEdgeInsets.zero
cell.layoutMargins = UIEdgeInsets.zero
return cell
}
let cell = tableView.dequeueReusableCell(withIdentifier: "NonStretchCell", for: indexPath) as! NonStretchCell
// just for demonstration's sake
if indexPath.row % 7 == 5 {
cell.theLabel.text = "Row: \(indexPath.row) - This is just to show the text wrapping onto multiple lines. Pretty standard for auto-sizing UITableView cells."
} else {
cell.theLabel.text = "Row: \(indexPath.row)"
}
cell.preservesSuperviewLayoutMargins = false
cell.separatorInset = UIEdgeInsets.zero
cell.layoutMargins = UIEdgeInsets.zero
return cell
}
}
结果是:
答案 1 :(得分:0)
正如DonMag建议你应该通过调用beginUpdates和endUpdates来触发高度变化。虽然不完全相同,但我在这个答案中实现了非常相似的东西:how to change the height of a single cell when clicked?
我相信你可以轻松地根据自己的需要调整它。