Я пытаюсь реализовать настраиваемую верхнюю панель, которая работает аналогично панели навигации с большим заголовком в iOS 11+, где большой раздел заголовка на панели сворачивается при прокрутке содержимого вниз:
Разница в том, что моему бару нужна настраиваемая высота, а также нижняя часть, которая не сворачивается при прокрутке.Мне удалось заставить эту часть работать:
Панель реализована с использованием UIStackView и с некоторыми необязательными ограничениями макета, но я считаю, что ее внутренняяреализация не актуальна.Самое главное, что высота панели привязана к вершине scrollview contentInset
.Они управляются методом contentOffset
в UIScrollViewDelegate.scrollViewDidScroll
от scrollview:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let topInset = (-scrollView.contentOffset.y).limitedBy(topBarHeightRange)
// changes both contentInset and scrollIndicatorInsets
adjustTopContentInset(topInset)
// changes top bar height
heightConstraint?.constant = topInset
adjustSmallTitleAlpha()
}
topBarHeightRange
хранит минимальную и максимальную высоту бара
Одна проблема, с которой у меня возникает проблема, эточто, когда пользователь прекращает прокручивать вид прокрутки, возможно, что панель окажется в полусвернутом состоянии.Опять же, давайте посмотрим на желаемое поведение:
Смещение содержимого привязывается к компактной или расширенной высоте, в зависимости от того, что ближе.Я пытаюсь добиться того же в методе UIScrollViewDelegate.scrollViewWillEndDragging
:
func scrollViewWillEndDragging(_ scrollView: UIScrollView,
withVelocity velocity: CGPoint,
targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let targetY = targetContentOffset.pointee.y
// snaps to a "closer" value
let snappedTargetY = targetY.snappedTo([topBarHeightRange.lowerBound, topBarHeightRange.upperBound].map(-))
targetContentOffset.pointee.y = snappedTargetY
print("Snapped: \(targetY) -> \(snappedTargetY)")
}
Эффект далек от совершенства:
Когда я смотрю нараспечатка показывает, что targetContentOffset
изменен правильно.Однако визуально в приложении смещение содержимого привязывается только к компактной высоте, но не к увеличенной высоте (вы можете заметить, что большая метка «Заголовок» в конечном итоге обрезается пополам, а не обратно в «расширенную» позицию.
Я подозреваю, что эта проблема связана с изменением contentInset.top
во время прокрутки, но я не могу понять, как исправить это поведение.
Это немного сложно объяснитьпроблема, поэтому я надеюсь, что GIF-файлы помогут. Вот репозиторий: https://github.com/AleksanderMaj/ScrollView
Есть какие-нибудь идеи, как сделать комбо scrollview / bar привязанным к компактной / расширенной высоте должным образом?