Replace the pagecontrol with a collection view (#690)
Scrolling wasn't smooth with pageviews, as they do some black magic with scrollviews (like resetting contentOffset). If you depend on contentOffset, this breaks things and makes them hard.
This commit is contained in:
parent
8ff47a72d0
commit
44d85e0263
|
@ -117,8 +117,7 @@
|
|||
D8916DC029211BE500124085 /* ContentSizedTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8916DBF29211BE500124085 /* ContentSizedTableView.swift */; };
|
||||
D8A6AB6C291C5136003AB663 /* MastodonLoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8A6AB6B291C5136003AB663 /* MastodonLoginViewController.swift */; };
|
||||
D8A6FE5B293244B500666A47 /* WelcomeContentPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8A6FE5A293244B500666A47 /* WelcomeContentPage.swift */; };
|
||||
D8A6FE5D293244C300666A47 /* WelcomeContentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8A6FE5C293244C300666A47 /* WelcomeContentViewController.swift */; };
|
||||
D8A6FE5F29324BBC00666A47 /* WelcomeContentPageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8A6FE5E29324BBC00666A47 /* WelcomeContentPageView.swift */; };
|
||||
D8A6FE5F29324BBC00666A47 /* WelcomeContentCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8A6FE5E29324BBC00666A47 /* WelcomeContentCollectionViewCell.swift */; };
|
||||
DB0009A626AEE5DC009B9D2D /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = DB0009A926AEE5DC009B9D2D /* Intents.intentdefinition */; settings = {ATTRIBUTES = (codegen, ); }; };
|
||||
DB0009A726AEE5DC009B9D2D /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = DB0009A926AEE5DC009B9D2D /* Intents.intentdefinition */; };
|
||||
DB0140CF25C42AEE00F9F3CF /* OSLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0140CE25C42AEE00F9F3CF /* OSLog.swift */; };
|
||||
|
@ -666,8 +665,7 @@
|
|||
D8916DBF29211BE500124085 /* ContentSizedTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentSizedTableView.swift; sourceTree = "<group>"; };
|
||||
D8A6AB6B291C5136003AB663 /* MastodonLoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonLoginViewController.swift; sourceTree = "<group>"; };
|
||||
D8A6FE5A293244B500666A47 /* WelcomeContentPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeContentPage.swift; sourceTree = "<group>"; };
|
||||
D8A6FE5C293244C300666A47 /* WelcomeContentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeContentViewController.swift; sourceTree = "<group>"; };
|
||||
D8A6FE5E29324BBC00666A47 /* WelcomeContentPageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeContentPageView.swift; sourceTree = "<group>"; };
|
||||
D8A6FE5E29324BBC00666A47 /* WelcomeContentCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeContentCollectionViewCell.swift; sourceTree = "<group>"; };
|
||||
D8A6FE6129325F5900666A47 /* Intents.stringsdict */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; path = Intents.stringsdict; sourceTree = "<group>"; };
|
||||
D8A6FE6229325F5900666A47 /* app.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = app.json; sourceTree = "<group>"; };
|
||||
D8A6FE6329325F5900666A47 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
||||
|
@ -1607,8 +1605,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
D8A6FE5A293244B500666A47 /* WelcomeContentPage.swift */,
|
||||
D8A6FE5C293244C300666A47 /* WelcomeContentViewController.swift */,
|
||||
D8A6FE5E29324BBC00666A47 /* WelcomeContentPageView.swift */,
|
||||
D8A6FE5E29324BBC00666A47 /* WelcomeContentCollectionViewCell.swift */,
|
||||
);
|
||||
path = Pages;
|
||||
sourceTree = "<group>";
|
||||
|
@ -3336,8 +3333,7 @@
|
|||
DB603113279EBEBA00A935FE /* DataSourceFacade+Block.swift in Sources */,
|
||||
DB63F777279A9A2A00455B82 /* NotificationView+Configuration.swift in Sources */,
|
||||
DB029E95266A20430062874E /* MastodonAuthenticationController.swift in Sources */,
|
||||
DB0C947726A7FE840088FB11 /* NotificationAvatarButton.swift in Sources */,
|
||||
D8A6FE5F29324BBC00666A47 /* WelcomeContentPageView.swift in Sources */,
|
||||
D8A6FE5F29324BBC00666A47 /* WelcomeContentCollectionViewCell.swift in Sources */,
|
||||
5B90C461262599800002E742 /* SettingsLinkTableViewCell.swift in Sources */,
|
||||
DB6180DD263918E30018D199 /* MediaPreviewViewController.swift in Sources */,
|
||||
DBE3CDEC261C6B2900430CC6 /* FavoriteViewController.swift in Sources */,
|
||||
|
@ -3549,7 +3545,6 @@
|
|||
DB1D84382657B275000346B3 /* SegmentedControlNavigateable.swift in Sources */,
|
||||
0F20220726134DA4000C64BF /* HashtagTimelineViewModel+Diffable.swift in Sources */,
|
||||
DB7A9F932818F33C0016AF98 /* MastodonServerRulesViewController+Debug.swift in Sources */,
|
||||
D8A6FE5D293244C300666A47 /* WelcomeContentViewController.swift in Sources */,
|
||||
2D5A3D2825CF8BC9002347D6 /* HomeTimelineViewModel+Diffable.swift in Sources */,
|
||||
DB6B74FC272FF55800C70B6E /* UserSection.swift in Sources */,
|
||||
DB0FCB862796BDA1006C02E2 /* SearchSection.swift in Sources */,
|
||||
|
|
|
@ -7,25 +7,24 @@
|
|||
|
||||
import UIKit
|
||||
|
||||
class WelcomeContentPageView: UIView {
|
||||
class WelcomeContentCollectionViewCell: UICollectionViewCell {
|
||||
|
||||
static let identifier = "WelcomeContentCollectionViewCell"
|
||||
|
||||
//TODO: Put in ScrollView?
|
||||
private let contentStackView: UIStackView
|
||||
private let titleView: UILabel
|
||||
private let label: UILabel
|
||||
private let blurryBackgroundView: UIVisualEffectView
|
||||
|
||||
init(page: WelcomeContentPage) {
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
titleView = UILabel()
|
||||
titleView.font = WelcomeViewController.largeTitleFont
|
||||
titleView.textColor = WelcomeViewController.largeTitleTextColor.resolvedColor(with: UITraitCollection(userInterfaceStyle: .light))
|
||||
titleView.attributedText = page.title
|
||||
titleView.adjustsFontForContentSizeCategory = true
|
||||
titleView.numberOfLines = 0
|
||||
|
||||
label = UILabel()
|
||||
label.text = page.content
|
||||
label.font = WelcomeViewController.subTitleFont
|
||||
label.textColor = WelcomeViewController.largeTitleTextColor.resolvedColor(with: UITraitCollection(userInterfaceStyle: .light))
|
||||
label.adjustsFontForContentSizeCategory = true
|
||||
|
@ -43,7 +42,7 @@ class WelcomeContentPageView: UIView {
|
|||
|
||||
blurryBackgroundView.contentView.addSubview(contentStackView)
|
||||
|
||||
super.init(frame: .zero)
|
||||
super.init(frame: frame)
|
||||
|
||||
addSubview(blurryBackgroundView)
|
||||
|
||||
|
@ -55,16 +54,21 @@ class WelcomeContentPageView: UIView {
|
|||
private func setupConstraints() {
|
||||
let constraints = [
|
||||
blurryBackgroundView.topAnchor.constraint(equalTo: topAnchor),
|
||||
blurryBackgroundView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
|
||||
trailingAnchor.constraint(equalTo: blurryBackgroundView.trailingAnchor, constant: 16),
|
||||
blurryBackgroundView.leadingAnchor.constraint(equalTo: leadingAnchor),
|
||||
trailingAnchor.constraint(equalTo: blurryBackgroundView.trailingAnchor),
|
||||
bottomAnchor.constraint(greaterThanOrEqualTo: blurryBackgroundView.bottomAnchor),
|
||||
|
||||
contentStackView.topAnchor.constraint(equalTo: blurryBackgroundView.contentView.topAnchor, constant: 8),
|
||||
contentStackView.leadingAnchor.constraint(equalTo: blurryBackgroundView.contentView.leadingAnchor, constant: 8),
|
||||
blurryBackgroundView.contentView.trailingAnchor.constraint(equalTo: contentStackView.trailingAnchor, constant: 8),
|
||||
blurryBackgroundView.contentView.bottomAnchor.constraint(equalTo: contentStackView.bottomAnchor, constant: 8),
|
||||
blurryBackgroundView.contentView.trailingAnchor.constraint(equalTo: contentStackView.trailingAnchor),
|
||||
blurryBackgroundView.contentView.bottomAnchor.constraint(equalTo: contentStackView.bottomAnchor),
|
||||
]
|
||||
|
||||
NSLayoutConstraint.activate(constraints)
|
||||
}
|
||||
|
||||
func update(with page: WelcomeContentPage) {
|
||||
titleView.attributedText = page.title
|
||||
label.text = page.content
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
//
|
||||
// WelcomeContentViewController.swift
|
||||
// Mastodon
|
||||
//
|
||||
// Created by Nathan Mattes on 26.11.22.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class WelcomeContentViewController: UIViewController {
|
||||
|
||||
let page: WelcomeContentPage
|
||||
var contentView: WelcomeContentPageView {
|
||||
view as! WelcomeContentPageView
|
||||
}
|
||||
|
||||
init(page: WelcomeContentPage) {
|
||||
self.page = page
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
}
|
||||
|
||||
override func loadView() {
|
||||
let pageView = WelcomeContentPageView(page: page)
|
||||
self.view = pageView
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
||||
}
|
|
@ -29,6 +29,7 @@ final class WelcomeViewController: UIViewController, NeedsDependency {
|
|||
private(set) lazy var dismissBarButtonItem = UIBarButtonItem(barButtonSystemItem: .close, target: self, action: #selector(WelcomeViewController.dismissBarButtonItemDidPressed(_:)))
|
||||
|
||||
let buttonContainer = UIStackView()
|
||||
let educationPages: [WelcomeContentPage] = [.whatIsMastodon, .mastodonIsLikeThat, .howDoIPickAServer]
|
||||
|
||||
private(set) lazy var signUpButton: PrimaryActionButton = {
|
||||
let button = PrimaryActionButton()
|
||||
|
@ -58,13 +59,24 @@ final class WelcomeViewController: UIViewController, NeedsDependency {
|
|||
return button
|
||||
}()
|
||||
|
||||
private(set) lazy var pageViewController: UIPageViewController = {
|
||||
let pageController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal)
|
||||
pageController.setViewControllers([WelcomeContentViewController(page: .whatIsMastodon)], direction: .forward, animated: false)
|
||||
return pageController
|
||||
private(set) lazy var pageCollectionView: UICollectionView = {
|
||||
let flowLayout = UICollectionViewFlowLayout()
|
||||
flowLayout.scrollDirection = .horizontal
|
||||
flowLayout.minimumInteritemSpacing = 0
|
||||
flowLayout.minimumLineSpacing = 0
|
||||
//FIXME: cell-size.
|
||||
flowLayout.itemSize = CGSize(width: self.view.frame.width, height: 300)
|
||||
|
||||
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout)
|
||||
collectionView.translatesAutoresizingMaskIntoConstraints = false
|
||||
collectionView.isPagingEnabled = true
|
||||
collectionView.backgroundColor = nil
|
||||
collectionView.showsHorizontalScrollIndicator = false
|
||||
collectionView.bounces = false
|
||||
collectionView.register(WelcomeContentCollectionViewCell.self, forCellWithReuseIdentifier: WelcomeContentCollectionViewCell.identifier)
|
||||
|
||||
return collectionView
|
||||
}()
|
||||
var currentPage: WelcomeContentPage = .whatIsMastodon
|
||||
var currentPageOffset = 0
|
||||
}
|
||||
|
||||
extension WelcomeViewController {
|
||||
|
@ -121,24 +133,18 @@ extension WelcomeViewController {
|
|||
signUpButton.addTarget(self, action: #selector(signUpButtonDidClicked(_:)), for: .touchUpInside)
|
||||
signInButton.addTarget(self, action: #selector(signInButtonDidClicked(_:)), for: .touchUpInside)
|
||||
|
||||
pageViewController.delegate = self
|
||||
pageViewController.dataSource = self
|
||||
addChild(pageViewController)
|
||||
pageViewController.view.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.addSubview(pageViewController.view)
|
||||
pageViewController.didMove(toParent: self)
|
||||
|
||||
let scrollviews = pageViewController.view.subviews.filter { type(of: $0).isSubclass(of: UIScrollView.self) }.compactMap { $0 as? UIScrollView }
|
||||
|
||||
for scrollView in scrollviews {
|
||||
scrollView.delegate = self
|
||||
}
|
||||
pageCollectionView.delegate = self
|
||||
pageCollectionView.dataSource = self
|
||||
view.addSubview(pageCollectionView)
|
||||
|
||||
let scrollView = pageCollectionView as UIScrollView
|
||||
scrollView.delegate = self
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
pageViewController.view.topAnchor.constraint(equalTo: view.topAnchor, constant: computedTopAnchorInset),
|
||||
pageViewController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||
view.trailingAnchor.constraint(equalTo: pageViewController.view.trailingAnchor),
|
||||
buttonContainer.topAnchor.constraint(equalTo: pageViewController.view.bottomAnchor, constant: 16),
|
||||
pageCollectionView.topAnchor.constraint(equalTo: view.topAnchor, constant: computedTopAnchorInset),
|
||||
pageCollectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||
view.trailingAnchor.constraint(equalTo: pageCollectionView.trailingAnchor),
|
||||
buttonContainer.topAnchor.constraint(equalTo: pageCollectionView.bottomAnchor, constant: 16),
|
||||
])
|
||||
|
||||
viewModel.$needsShowDismissEntry
|
||||
|
@ -287,70 +293,29 @@ extension WelcomeViewController: UIAdaptivePresentationControllerDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
//MARK: - UIPageViewControllerDelegate
|
||||
|
||||
extension WelcomeViewController: UIPageViewControllerDelegate {
|
||||
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
|
||||
guard let currentViewController = pageViewController.viewControllers?.first as? WelcomeContentViewController else { return }
|
||||
|
||||
currentPage = currentViewController.page
|
||||
|
||||
if let pageIndex = WelcomeContentPage.allCases.firstIndex(of: currentPage) {
|
||||
let offset = Int(pageIndex) * Int(pageViewController.view.frame.width)
|
||||
currentPageOffset = offset
|
||||
welcomeIllustrationView.update(contentOffset: CGFloat(offset))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - UIPageViewDataSource
|
||||
|
||||
extension WelcomeViewController: UIPageViewControllerDataSource {
|
||||
|
||||
func presentationIndex(for pageViewController: UIPageViewController) -> Int {
|
||||
WelcomeContentPage.allCases.firstIndex(of: currentPage) ?? 0
|
||||
}
|
||||
|
||||
func presentationCount(for pageViewController: UIPageViewController) -> Int {
|
||||
return WelcomeContentPage.allCases.count
|
||||
}
|
||||
|
||||
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
|
||||
guard let viewController = viewController as? WelcomeContentViewController else { return nil }
|
||||
|
||||
let currentPage = viewController.page
|
||||
|
||||
switch currentPage {
|
||||
case .whatIsMastodon:
|
||||
return nil
|
||||
case .mastodonIsLikeThat:
|
||||
return WelcomeContentViewController(page: .whatIsMastodon)
|
||||
case .howDoIPickAServer:
|
||||
return WelcomeContentViewController(page: .mastodonIsLikeThat)
|
||||
}
|
||||
}
|
||||
|
||||
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
|
||||
guard let viewController = viewController as? WelcomeContentViewController else { return nil }
|
||||
|
||||
let currentPage = viewController.page
|
||||
|
||||
switch currentPage {
|
||||
case .whatIsMastodon:
|
||||
return WelcomeContentViewController(page: .mastodonIsLikeThat)
|
||||
case .mastodonIsLikeThat:
|
||||
return WelcomeContentViewController(page: .howDoIPickAServer)
|
||||
case .howDoIPickAServer:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - UIScrollViewDelegate
|
||||
extension WelcomeViewController: UIScrollViewDelegate {
|
||||
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
let weirdScrollViewJumpingCorrectionFactor = pageViewController.view.frame.width
|
||||
let contentOffset = CGFloat(currentPageOffset) + scrollView.contentOffset.x - weirdScrollViewJumpingCorrectionFactor
|
||||
|
||||
let contentOffset = scrollView.contentOffset.x
|
||||
welcomeIllustrationView.update(contentOffset: contentOffset)
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - UICollectionViewDelegate
|
||||
extension WelcomeViewController: UICollectionViewDelegate { }
|
||||
|
||||
//MARK: - UICollectionViewDataSource
|
||||
extension WelcomeViewController: UICollectionViewDataSource {
|
||||
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
educationPages.count
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: WelcomeContentCollectionViewCell.identifier, for: indexPath) as? WelcomeContentCollectionViewCell else { fatalError("WTF? Wrong cell?") }
|
||||
|
||||
let page = educationPages[indexPath.item]
|
||||
cell.update(with: page)
|
||||
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue