У меня есть UIView
, который привязан к якорям top
, leading
и trailing
. Он имеет начальную высоту 138
и должен уменьшиться до не менее 88
.
У меня есть UITableView
закрепленная вершина к нижней части этого представления, она также привязана к leading
, trailing
и нижней части суперпредставления.
Это не представление заголовка для табличного представления, а отдельное представление.
При прокрутке табличного представления я бы хотел, чтобы мой UIView
уменьшился и вернулся к своему первоначальному размеру, в зависимости от направления прокрутки.
- Прокрутка вверх = сокращение до не менее
88
- Прокрутка вниз = увеличение до не более
138
В настоящее время я могу достичь этого с помощью
func scrollViewDidScroll(_ scrollView: UIScrollView) {
onUserScroll?(scrollView)
}
который через привязку запускает приведенный ниже код
class FeedView: UIView {
private(set) var brandedHeader: UIView!
private(set) var brandedHeaderHeight: NSLayoutConstraint!
private(set) var tableView: UITableView!
private lazy var maxHeaderHeight: CGFloat = 138
private lazy var minHeaderHeight: CGFloat = 88
private var previousScrollOffset: CGFloat = 0
...............
}
extension FeedView {
func setTableViewDelegate(_ delegate: TableViewDelegate) {
tableView.delegate = delegate
tableView.dataSource = delegate
}
func onUserScroll(_ 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
guard canAnimateHeader(scrollView) else { return }
// Calculate new header height
var newHeight = self.brandedHeaderHeight.constant
if isScrollingDown {
newHeight = max(self.minHeaderHeight, self.brandedHeaderHeight.constant - abs(scrollDiff))
} else if isScrollingUp {
newHeight = min(self.maxHeaderHeight, self.brandedHeaderHeight.constant + abs(scrollDiff))
}
// Header needs to animate
if newHeight != self.brandedHeaderHeight.constant {
self.brandedHeaderHeight.constant = newHeight
self.setScrollPosition(self.previousScrollOffset)
}
self.previousScrollOffset = scrollView.contentOffset.y
}
private func canAnimateHeader(_ scrollView: UIScrollView) -> Bool {
// Calculate the size of the scrollView when header is collapsed
let scrollViewMaxHeight = scrollView.frame.height + self.brandedHeaderHeight.constant - minHeaderHeight
// Make sure that when header is collapsed, there is still room to scroll
return scrollView.contentSize.height > scrollViewMaxHeight
}
private func setScrollPosition(_ position: CGFloat) {
self.tableView.contentOffset = CGPoint(x: self.tableView.contentOffset.x, y: position)
}
}
Однако я бы хотел задержать событие изменения размера.
В настоящее время он начинается сразу после прокрутки вверх или вниз, на самом деле, я бы хотел, чтобы он начал изменять размер после того, как пользователь прокрутил сумму X вверх, а затем изменяет размер только при прокрутке вниз, когда он снова проходит эту точку.
Я обновил свой код следующим образом
private var previousScrollOffset: CGFloat = 100 // offset the initial scroll so the header does not shrink immediately on scroll
, а затем также
func onUserScroll(_ scrollView: UIScrollView) {
guard scrollView.contentOffset.y < 200 else { return }
..........
}
Но это не сработало, как ожидалось.
Я надеюсь добиться того же эффекта, что и эффект прокрутки большой панели заголовка.