Scroll to bottom when switching albums

Fixes

1. start on "All Photos" which has many pages of content

You're at the bottom, as expected.

2. switch to "Video", which is much shorter

You're at the bottom, as expected.

3. Switch back to "All Photos"

Now you're unexpectedly in the middle of the content somewhere - at whatever
offset the "Videos" content height was.

Note that changes to "scrollToBottom". For some reason calling scroll to bottom
with infinity works fine initially, but subsequent calls hang. Because we only
used the "infinity" hack to account for the fact that we didn't have accurate
safeAreaInsets before `viewDidAppear`, we can accurately use safeAreaInsets
after that point (like here, when switching albums).
This commit is contained in:
Michael Kirk 2019-01-11 18:15:34 -07:00
parent ff2fdcb7e1
commit 924b8b18ba
1 changed files with 30 additions and 22 deletions

View File

@ -116,13 +116,14 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat
reloadDataAndRestoreSelection()
if !hasEverAppeared {
hasEverAppeared = true
scrollToBottom(animated: false)
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
hasEverAppeared = true
// done button may have been disable from the last time we hit "Done"
// make sure to re-enable it if appropriate upon returning to the view
hasPressedDoneSinceAppeared = false
@ -156,31 +157,37 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat
return
}
let verticalOffset: CGFloat
if #available(iOS 11, *) {
// On iOS10 and earlier, we can be precise, but as of iOS11 `collectionView.contentInset`
// is based on `safeAreaInsets`, which isn't accurate until `viewDidAppear` at the earliest.
//
// from https://developer.apple.com/documentation/uikit/uiview/positioning_content_relative_to_the_safe_area
// > Make your modifications in [viewDidAppear] because the safe area insets for a view are
// > not accurate until the view is added to a view hierarchy.
//
// Overshooting like this works without visible animation glitch. on iOS11+
// However, before iOS11, "overshooting" the contentOffset like this produces a broken
// layout or hanging. Luckily for those versions, before the safeAreaInset feature
// existed, we can accurately accesse colletionView.contentInset before `viewDidAppear`
// and calculate a precise content offset.
verticalOffset = CGFloat.greatestFiniteMagnitude
var verticalOffset: CGFloat
let visibleHeight = collectionView.bounds.height - collectionView.contentInset.top
let contentHeight = collectionView.contentSize.height
if contentHeight <= visibleHeight {
verticalOffset = -collectionView.contentInset.top
} else {
let visibleHeight = collectionView.bounds.height - collectionView.contentInset.top
let contentHeight = collectionView.contentSize.height
if contentHeight <= visibleHeight {
verticalOffset = -collectionView.contentInset.top
let topOfLastPage = contentHeight - collectionView.bounds.height
verticalOffset = topOfLastPage
}
if #available(iOS 11, *) {
if hasEverAppeared {
verticalOffset += collectionView.safeAreaInsets.bottom
} else {
let topOfLastPage = contentHeight - collectionView.bounds.height
verticalOffset = topOfLastPage
// On iOS10 and earlier, we can be precise, but as of iOS11 `collectionView.contentInset`
// is based on `safeAreaInsets`, which isn't accurate until `viewDidAppear` at the earliest.
//
// from https://developer.apple.com/documentation/uikit/uiview/positioning_content_relative_to_the_safe_area
// > Make your modifications in [viewDidAppear] because the safe area insets for a view are
// > not accurate until the view is added to a view hierarchy.
//
// Overshooting like this works without visible animation glitch. on iOS11+
// However, before iOS11, "overshooting" the contentOffset like this produces a broken
// layout or hanging. Luckily for those versions, before the safeAreaInset feature
// existed, we can accurately access collectionView.contentInset before `viewDidAppear`
// and calculate a precise content offset.
verticalOffset += 122
}
}
collectionView.setContentOffset(CGPoint(x: 0, y: verticalOffset), animated: animated)
}
@ -478,6 +485,7 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat
}
collectionView?.reloadData()
scrollToBottom(animated: false)
hideCollectionPicker()
}