有人能告诉我如何实现一个有弹性的UITableView页脚。
当用户'过度滚动'时,我希望我的页脚内部的图像可以拉伸/增大尺寸。 (如果用户在UITableView已经位于底部时向下滚动)
当前代码:
private let tableFooterHeight: CGFloat = 300
private var footerCustomView = UIImageView()
func setupFooterView(){
// Footer view
self.footerCustomView = UIImageView(frame: CGRect.zero)
self.footerCustomView.backgroundColor = UIColor.brown
self.footerCustomView.image = UIImage(named: "image")
self.view.addSubview(self.footerCustomView)
// self.view.bringSubview(toFront: self.tableView)
self.tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: self.tableFooterHeight, right: 0)
self.footerCustomView.translatesAutoresizingMaskIntoConstraints = false
let leadingConstraint = NSLayoutConstraint(item: self.footerCustomView,
attribute: .leading,
relatedBy: .equal,
toItem: self.tableView,
attribute: .leading,
multiplier: 1,
constant: 0)
let trailingConstraint = NSLayoutConstraint(item: self.footerCustomView,
attribute: .trailing,
relatedBy: .equal,
toItem: self.tableView,
attribute: .trailing,
multiplier: 1,
constant: 0)
let bottomConstraint = NSLayoutConstraint(item: self.footerCustomView,
attribute: .bottom,
relatedBy: .equal,
toItem: self.tableView,
attribute: .bottom,
multiplier: 1,
constant: 0)
let heightConstraint = NSLayoutConstraint(item: self.footerCustomView,
attribute: .height,
relatedBy: .equal,
toItem: nil,
attribute: .height,
multiplier: 1,
constant: self.tableFooterHeight)
self.view.addConstraints([bottomConstraint, trailingConstraint, heightConstraint, leadingConstraint])
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
self.updateFooterView()
}
func updateFooterView() {
if self.tableView.bounds.origin.y > 1559 { // 1559 is end of tableView
let diff = self.tableView.contentOffset.y - 1559
self.footerCustomView.frame.size.height = self.tableFooterHeight + diff
}
}
谢谢!
答案 0 :(得分:0)
UITableView已经有一个属性tableFooterView
我们可以使用UIImageView,UIScrollView和另一个UIView将UIView子类化为UIImageView的容器。我们称之为StretchyFooterView。
我喜欢使用名为PureLayout的库来添加约束。
class YourView: UIView, UITableViewDelegate {
fileprivate let tableView = UITableView(frame: .zero, style: .plain)
fileprivate let image = UIImage(named: "yourImage")!
// ----------------------------------------------------------------------------
// MARK: Init
// ----------------------------------------------------------------------------
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// ----------------------------------------------------------------------------
// MARK: UIView
// ----------------------------------------------------------------------------
override func updateConstraints() {
tableView.autoPinEdgesToSuperviewEdges()
super.updateConstraints()
}
override func layoutSubviews() {
super.layoutSubviews()
// do this after the view lays out so we know the frame width and height
let imageAspect = image.size.width / image.size.height
let footerWidth = frame.size.width
let footerHeight = footerWidth / imageAspect
let footerSize = CGSize(width: footerWidth, height: footerHeight)
let footerFrame = CGRect(origin: .zero, size: footerSize)
tableView.tableFooterView = StretchyFooterView(frame: footerFrame, image: image)
}
// ----------------------------------------------------------------------------
// MARK: Internal
// ----------------------------------------------------------------------------
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let verticalScrollDistance = scrollView.contentOffset.y
let bottomOfView = frame.height
if let stretchyFooterView = tableView.tableFooterView as? StretchyFooterView {
stretchyFooterView.stretchBy(verticalScrollDistance, bottomBound: bottomOfView)
}
}
// ----------------------------------------------------------------------------
// MARK: Private
// ----------------------------------------------------------------------------
fileprivate func setupViews() {
tableView.delegate = self
addSubview(tableView)
}
}
class StretchyFooterView: UIView {
fileprivate let containerView = UIView()
fileprivate let scrollView = UIScrollView()
fileprivate let imageView = UIImageView()
fileprivate let image: UIImage
// ----------------------------------------------------------------------------
// MARK: Init
// ----------------------------------------------------------------------------
init(frame: CGRect, image: UIImage) {
self.image = image
super.init(frame: frame)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// ----------------------------------------------------------------------------
// MARK: UIView
// ----------------------------------------------------------------------------
override func updateConstraints() {
containerView.autoCenterInSuperview()
containerView.autoMatch(.height, to: .height, of: scrollView)
imageView.autoPinEdgesToSuperviewEdges()
imageView.autoMatch(.width, to: .height, of: scrollView, withMultiplier: image.aspect)
super.updateConstraints()
}
// ----------------------------------------------------------------------------
// MARK: Internal
// ----------------------------------------------------------------------------
func stretchBy(_ distanceScrolled: CGFloat, bottomBound: CGFloat) {
let distanceFromTop = bottomBound + distanceScrolled // the footer could be offscreen, so we need to add the distance scrolled to the bottom of the view
let distanceFromBottom = frame.maxY - distanceFromTop // this is how much we need to scroll
if distanceFromBottom < 0 { // once we hit zero and below, we need to stretch the height
let origin = CGPoint.zero // since we are scrolling, the origin needs to stay at zero
let newSize = CGSize(width: frame.width, height: frame.height - distanceFromBottom) // subtract distanceFromBottom because it's negative
scrollView.frame = CGRect(origin: origin, size: newSize)
}
}
// ----------------------------------------------------------------------------
// MARK: Private
// ----------------------------------------------------------------------------
fileprivate func setupViews() {
imageView.image = image
containerView.addSubview(imageView)
scrollView.frame = bounds
scrollView.addSubview(containerView)
addSubview(scrollView)
}
}
答案 1 :(得分:0)
如果使用情节提要,则为简单变体:
实施 scrollViewDidScroll(_ scrollView: UIScrollView)
:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard scrollView == mainTableView else { return }
updateTableFooterFrame()
}
func updateTableFooterFrame() {
let distanceFromTop = mainTableView.frame.height + mainTableView.contentOffset.y
var distanceScrolled = distanceFromTop - mainTableView.contentSize.height
distanceScrolled = distanceScrolled > 0 ? distanceScrolled : 0
let newFooterFrame = CGRect(
x: 0, y: mainTableView.contentSize.height,
width: mainTableView.frame.width,
height: distanceScrolled
)
tableFooterView.frame = newFooterFrame
}