我在UIView
上方有一个UITableView
(如屏幕截图所示)。当用户滚动UIView
时,我将UITableView
从屏幕上移出(从顶部)。 UIView
可以正确移动,但是UIView中的项目保持在原位置。我怎么也可以移动它们?
P.S:我从下面的帖子中得到了帮助,并感谢它的发布者:),也为许多代码感到抱歉,但是我无法决定如何缩小它。
https://github.com/MichiganLabs/AnimatingTableViewHeader
编辑:我通过将所有约束添加到同一视图来做错了,我已解决了该问题,但问题仍然存在。
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.view.backgroundColor = UIColor.white
setupUI()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.headerHeightConstraint.constant = self.maxHeaderHeight
updateHeader()
}
private func setupUI(){
self.view.backgroundColor = UIColor.white
self.tableView.delegate = self
self.tableView.dataSource = self
self.headerView.backgroundColor = Color.Common.welcomeScreenBackgroundColor.withAlphaComponent(0.5)
self.view.addSubview(tableView)
self.view.addSubview(headerView)
headerView.translatesAutoresizingMaskIntoConstraints = false
tableView.translatesAutoresizingMaskIntoConstraints = false
//cityBtn.translatesAutoresizingMaskIntoConstraints = false
cityLbl.text = "İL"
headerView.addSubview(cityLbl)
headerView.addSubview(cityBtn)
//Header = 20 from left edge of screen
let cn1 = NSLayoutConstraint(item: headerView, attribute: .leading, relatedBy: .equal, toItem: self.view, attribute: .leading, multiplier: 1.0, constant: 20)
//Header view trailing end is 20 px from right edge of the screen
let cn2 = NSLayoutConstraint(item: headerView, attribute: .trailing, relatedBy: .equal, toItem: self.view, attribute: .trailing, multiplier: 1.0, constant: -20)
let cn3 = NSLayoutConstraint(item: headerView, attribute: .bottom, relatedBy: .equal, toItem: self.tableView, attribute: .top, multiplier: 1.0, constant: -20)
//Header view height = constant 240
headerHeightConstraint = NSLayoutConstraint(item: headerView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant:230)
//Header view vertical padding from the top edge of the screen = 20
let topConstraint = NSLayoutConstraint(item: headerView, attribute: .top, relatedBy: .equal, toItem: self.topLayoutGuide, attribute: .bottom, multiplier: 1.0, constant: 20)
//Header = 20 from left edge of screen
let tb1 = NSLayoutConstraint(item: tableView, attribute: .leading, relatedBy: .equal, toItem: self.view, attribute: .leading, multiplier: 1.0, constant: 0)
//Header view trailing end is 20 px from right edge of the screen
let tb2 = NSLayoutConstraint(item: tableView, attribute: .trailing, relatedBy: .equal, toItem: self.view, attribute: .trailing, multiplier: 1.0, constant: 0)
let tb3 = NSLayoutConstraint(item: tableView, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1.0, constant: 0)
let tb4 = NSLayoutConstraint(item: tableView, attribute: .top, relatedBy: .equal, toItem: self.headerView, attribute: .bottom, multiplier: 1.0, constant: 0)
//Header view trailing end is 20 px from right edge of the screen
let cb1 = NSLayoutConstraint(item: cityBtn, attribute: .width, relatedBy: .equal, toItem: self.headerView, attribute: .width, multiplier: 0.6, constant: 0)
let cb2 = NSLayoutConstraint(item: cityBtn, attribute: .trailing, relatedBy: .equal, toItem: self.headerView, attribute: .trailing, multiplier: 1.0, constant: -20)
cityBtnTopConstraint = NSLayoutConstraint(item: cityBtn, attribute: .top, relatedBy: .equal, toItem: self.headerView, attribute: .top, multiplier: 1.0, constant: 20)
let cb4 = NSLayoutConstraint(item: cityBtn, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant:50)
self.view.addConstraints([cn1,cn2,cn3,headerHeightConstraint,topConstraint,tb1,tb2,tb3,tb4])
self.headerView.addConstraints([cb1,cb2,cityBtnTopConstraint,cb4])
}
override func viewDidLayoutSubviews() {
cityLbl.leftAnchor.constraint(equalTo: headerView.leftAnchor, constant: 20).isActive = true
cityLbl.centerYAnchor.constraint(equalTo: cityBtn.centerYAnchor).isActive = true
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let scrollDiff = scrollView.contentOffset.y - self.previousScrollOffset
let absoluteTop: CGFloat = 0;
let absoluteBottom: CGFloat = scrollView.contentSize.height - scrollView.frame.size.height;
let isScrollingDown = scrollDiff > 0 && scrollView.contentOffset.y > absoluteTop
let isScrollingUp = scrollDiff < 0 && scrollView.contentOffset.y < absoluteBottom
if canAnimateHeader(scrollView) {
// Calculate new header height
var newHeight = self.headerHeightConstraint.constant
if isScrollingDown {
newHeight = max(self.minHeaderHeight, self.headerHeightConstraint.constant - abs(scrollDiff))
} else if isScrollingUp {
newHeight = min(self.maxHeaderHeight, self.headerHeightConstraint.constant + abs(scrollDiff))
}
// Header needs to animate
if newHeight != self.headerHeightConstraint.constant {
self.headerHeightConstraint.constant = newHeight
self.updateHeader()
self.setScrollPosition(self.previousScrollOffset)
}
self.previousScrollOffset = scrollView.contentOffset.y
}
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
self.scrollViewDidStopScrolling()
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if !decelerate {
self.scrollViewDidStopScrolling()
}
}
func scrollViewDidStopScrolling() {
let range = self.maxHeaderHeight - self.minHeaderHeight
let midPoint = self.minHeaderHeight + (range / 2)
if self.headerHeightConstraint.constant > midPoint {
self.expandHeader()
} else {
self.collapseHeader()
}
}
func canAnimateHeader(_ scrollView: UIScrollView) -> Bool {
// Calculate the size of the scrollView when header is collapsed
let scrollViewMaxHeight = scrollView.frame.height + self.headerHeightConstraint.constant - minHeaderHeight
// Make sure that when header is collapsed, there is still room to scroll
return scrollView.contentSize.height > scrollViewMaxHeight
}
func collapseHeader() {
self.view.layoutIfNeeded()
UIView.animate(withDuration: 0.2, animations: {
self.headerHeightConstraint.constant = self.minHeaderHeight
self.updateHeader()
self.view.layoutIfNeeded()
})
}
func expandHeader() {
self.view.layoutIfNeeded()
UIView.animate(withDuration: 0.2, animations: {
self.headerHeightConstraint.constant = self.maxHeaderHeight
self.updateHeader()
self.view.layoutIfNeeded()
})
}
func setScrollPosition(_ position: CGFloat) {
self.tableView.contentOffset = CGPoint(x: self.tableView.contentOffset.x, y: position)
}
func updateHeader() {
let range = self.maxHeaderHeight - self.minHeaderHeight
let openAmount = self.headerHeightConstraint.constant - self.minHeaderHeight
let percentage = openAmount / range
self.cityBtn.alpha = percentage
//self.titleTopConstraint.constant = -openAmount + 10
//self.logoImageView.alpha = percentage
}
答案 0 :(得分:0)
问题是您将所有约束添加到self.view中,需要在headerView和headerView的子视图之间添加约束,因此请拆分
self.view.addConstraints([cn1,cn2,cn3,headerHeightConstraint,topConstraint,tb1,tb2, tb3,tb4,cb1,cb2,cityBtnTopConstraint,cb4])
到
self.view.addConstraints([cn1,cn2,cn3,headerHeightConstraint,topConstraint,tb1,tb2, tb3,tb4])
&&
headerView.addConstraints([cb1,cb2,cityBtnTopConstraint,cb4])