From 38cafae28b6da7cc0925517626e31045be17a8d9 Mon Sep 17 00:00:00 2001 From: Nathan Mattes Date: Sun, 4 Dec 2022 21:07:11 +0100 Subject: [PATCH] [WIP] Move layoutcode and move plane (#690) Turns out: Changing the constant of a layoutconstraint does the job, but is' laggy af, so I have to come up with another solution. --- .../View/WelcomeIllustrationView.swift | 419 ++++++++++-------- .../Welcome/WelcomeViewController.swift | 127 +----- 2 files changed, 247 insertions(+), 299 deletions(-) diff --git a/Mastodon/Scene/Onboarding/Welcome/View/WelcomeIllustrationView.swift b/Mastodon/Scene/Onboarding/Welcome/View/WelcomeIllustrationView.swift index 317fead61..984c5cd86 100644 --- a/Mastodon/Scene/Onboarding/Welcome/View/WelcomeIllustrationView.swift +++ b/Mastodon/Scene/Onboarding/Welcome/View/WelcomeIllustrationView.swift @@ -12,202 +12,239 @@ import MastodonUI import MastodonLocalization final class WelcomeIllustrationView: UIView { - - let cloudBaseImageView = UIImageView() - let rightHillImageView = UIImageView() - let leftHillImageView = UIImageView() - let centerHillImageView = UIImageView() - - private let cloudBaseImage = Asset.Scene.Welcome.Illustration.cloudBase.image - private let cloudBaseExtendImage = Asset.Scene.Welcome.Illustration.cloudBaseExtend.image - private let elephantThreeOnGrassWithTreeTwoImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrassWithTreeTwo.image - private let elephantThreeOnGrassWithTreeThreeImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrassWithTreeThree.image - private let elephantThreeOnGrassImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrass.image - private let elephantThreeOnGrassExtendImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrassExtend.image - - // layout outside - let elephantOnAirplaneWithContrailImageView: UIImageView = { - let imageView = UIImageView(image: Asset.Scene.Welcome.Illustration.elephantOnAirplaneWithContrail.image) - imageView.contentMode = .scaleAspectFill - return imageView - }() - - var layout: Layout = .compact { - didSet { - setNeedsLayout() - } - } - var aspectLayoutConstraint: NSLayoutConstraint! - override init(frame: CGRect) { - super.init(frame: frame) - _init() + let cloudBaseImageView = UIImageView() + let rightHillImageView = UIImageView() + let leftHillImageView = UIImageView() + let centerHillImageView = UIImageView() + + private let cloudBaseImage = Asset.Scene.Welcome.Illustration.cloudBase.image + private let cloudBaseExtendImage = Asset.Scene.Welcome.Illustration.cloudBaseExtend.image + private let elephantThreeOnGrassWithTreeTwoImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrassWithTreeTwo.image + private let elephantThreeOnGrassWithTreeThreeImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrassWithTreeThree.image + private let elephantThreeOnGrassImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrass.image + private let elephantThreeOnGrassExtendImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrassExtend.image + + var bottomAnchorLayoutConstraint: NSLayoutConstraint? + var elephantOnAirplaneLeftConstraint: NSLayoutConstraint? + + let elephantOnAirplaneWithContrailImageView: UIImageView = { + let imageView = UIImageView(image: Asset.Scene.Welcome.Illustration.elephantOnAirplaneWithContrail.image) + imageView.translatesAutoresizingMaskIntoConstraints = false + imageView.contentMode = .scaleAspectFill + return imageView + }() + + var layout: Layout = .compact { + didSet { + setNeedsLayout() } - - required init?(coder: NSCoder) { - super.init(coder: coder) - _init() - } - + } + var aspectLayoutConstraint: NSLayoutConstraint! + + override init(frame: CGRect) { + super.init(frame: frame) + _init() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + _init() + } + } extension WelcomeIllustrationView { - enum Layout { - case compact - case regular - - var artworkImageSize: CGSize { - switch self { - case .compact: return CGSize(width: 375, height: 1500) - case .regular: return CGSize(width: 547, height: 3000) - } - } + enum Layout { + case compact + case regular + + var artworkImageSize: CGSize { + switch self { + case .compact: return CGSize(width: 375, height: 1500) + case .regular: return CGSize(width: 547, height: 3000) + } } -} - -extension WelcomeIllustrationView { - - private func _init() { - backgroundColor = Asset.Scene.Welcome.Illustration.backgroundCyan.color - - let topPaddingView = UIView() - - topPaddingView.translatesAutoresizingMaskIntoConstraints = false - addSubview(topPaddingView) - NSLayoutConstraint.activate([ - topPaddingView.topAnchor.constraint(equalTo: topAnchor), - topPaddingView.leadingAnchor.constraint(equalTo: leadingAnchor), - topPaddingView.trailingAnchor.constraint(equalTo: trailingAnchor), - ]) - - cloudBaseImageView.translatesAutoresizingMaskIntoConstraints = false - addSubview(cloudBaseImageView) - NSLayoutConstraint.activate([ - cloudBaseImageView.topAnchor.constraint(equalTo: topPaddingView.bottomAnchor), - cloudBaseImageView.leadingAnchor.constraint(equalTo: leadingAnchor), - cloudBaseImageView.trailingAnchor.constraint(equalTo: trailingAnchor), - cloudBaseImageView.bottomAnchor.constraint(equalTo: bottomAnchor), - ]) - - [ - rightHillImageView, - leftHillImageView, - centerHillImageView, - ].forEach { imageView in - imageView.translatesAutoresizingMaskIntoConstraints = false - addSubview(imageView) - imageView.pinTo(to: cloudBaseImageView) - } - - aspectLayoutConstraint = cloudBaseImageView.widthAnchor.constraint(equalTo: cloudBaseImageView.heightAnchor, multiplier: layout.artworkImageSize.width / layout.artworkImageSize.height) - aspectLayoutConstraint.isActive = true - } - - override func layoutSubviews() { - super.layoutSubviews() - - switch layout { - case .compact: - layoutCompact() - case .regular: - layoutRegular() - } - - aspectLayoutConstraint.isActive = false - aspectLayoutConstraint = cloudBaseImageView.widthAnchor.constraint(equalTo: cloudBaseImageView.heightAnchor, multiplier: layout.artworkImageSize.width / layout.artworkImageSize.height) - aspectLayoutConstraint.isActive = true - } - - private func layoutCompact() { - let size = layout.artworkImageSize - let width = size.width - let height = size.height - - cloudBaseImageView.image = UIGraphicsImageRenderer(size: size).image { context in - // clear background - UIColor.clear.setFill() - context.fill(CGRect(origin: .zero, size: size)) - - // draw cloud - cloudBaseImage.draw(at: CGPoint(x: 0, y: height - cloudBaseImage.size.height)) - } - - rightHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in - // clear background - UIColor.clear.setFill() - context.fill(CGRect(origin: .zero, size: size)) - - // draw elephantThreeOnGrassWithTreeTwoImage - // elephantThreeOnGrassWithTreeTwo.bottomY - 25 align to elephantThreeOnGrassImage.centerY - elephantThreeOnGrassWithTreeTwoImage.draw(at: CGPoint(x: width - elephantThreeOnGrassWithTreeTwoImage.size.width, y: height - 0.5 * elephantThreeOnGrassImage.size.height - elephantThreeOnGrassWithTreeTwoImage.size.height + 25)) - } - - leftHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in - // clear background - UIColor.clear.setFill() - context.fill(CGRect(origin: .zero, size: size)) - - // draw elephantThreeOnGrassWithTreeThree - // elephantThreeOnGrassWithTreeThree.bottomY + 30 align to elephantThreeOnGrassImage.centerY - elephantThreeOnGrassWithTreeThreeImage.draw(at: CGPoint(x: 0, y: height - 0.5 * elephantThreeOnGrassImage.size.height - elephantThreeOnGrassWithTreeThreeImage.size.height - 30)) - } - - centerHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in - // clear background - UIColor.clear.setFill() - context.fill(CGRect(origin: .zero, size: size)) - - // draw elephantThreeOnGrass - elephantThreeOnGrassImage.draw(at: CGPoint(x: 0, y: height - elephantThreeOnGrassImage.size.height)) - } - } - - private func layoutRegular() { - let size = layout.artworkImageSize - let width = size.width - let height = size.height - - cloudBaseImageView.image = UIGraphicsImageRenderer(size: size).image { context in - // clear background - UIColor.clear.setFill() - context.fill(CGRect(origin: .zero, size: size)) - - // draw cloud - cloudBaseExtendImage.draw(at: CGPoint(x: 0, y: height - cloudBaseExtendImage.size.height)) - - rightHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in - // clear background - UIColor.clear.setFill() - context.fill(CGRect(origin: .zero, size: size)) - - // draw elephantThreeOnGrassWithTreeTwoImage - // elephantThreeOnGrassWithTreeTwo.bottomY - 25 align to elephantThreeOnGrassImage.centerY - elephantThreeOnGrassWithTreeTwoImage.draw(at: CGPoint(x: width - elephantThreeOnGrassWithTreeTwoImage.size.width, y: height - 0.5 * elephantThreeOnGrassImage.size.height - elephantThreeOnGrassWithTreeTwoImage.size.height - 20)) - } - - leftHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in - // clear background - UIColor.clear.setFill() - context.fill(CGRect(origin: .zero, size: size)) - - // draw elephantThreeOnGrassWithTreeThree - // elephantThreeOnGrassWithTreeThree.bottomY + 30 align to elephantThreeOnGrassImage.centerY - elephantThreeOnGrassWithTreeThreeImage.draw(at: CGPoint(x: -160, y: height - 0.5 * elephantThreeOnGrassImage.size.height - elephantThreeOnGrassWithTreeThreeImage.size.height - 80)) - } - - centerHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in - // clear background - UIColor.clear.setFill() - context.fill(CGRect(origin: .zero, size: size)) - - // draw elephantThreeOnGrass - elephantThreeOnGrassExtendImage.draw(at: CGPoint(x: 0, y: height - elephantThreeOnGrassExtendImage.size.height)) - } - } - } - - func update(contentOffset: CGFloat) { - //TODO: @zeitschlag update frames - print(Int(contentOffset)) + } +} + +extension WelcomeIllustrationView { + + private func _init() { + backgroundColor = Asset.Scene.Welcome.Illustration.backgroundCyan.color + + cloudBaseImageView.translatesAutoresizingMaskIntoConstraints = false + addSubview(cloudBaseImageView) + NSLayoutConstraint.activate([ + cloudBaseImageView.leadingAnchor.constraint(equalTo: leadingAnchor), + cloudBaseImageView.trailingAnchor.constraint(equalTo: trailingAnchor), + cloudBaseImageView.bottomAnchor.constraint(equalTo: bottomAnchor), + ]) + + addSubview(elephantOnAirplaneWithContrailImageView) + + let elephantOnAirplaneLeftConstraint = leftAnchor.constraint(equalTo: elephantOnAirplaneWithContrailImageView.leftAnchor, constant: 178) // add 12pt bleeding + NSLayoutConstraint.activate([ + elephantOnAirplaneLeftConstraint, + elephantOnAirplaneWithContrailImageView.bottomAnchor.constraint(equalTo: centerYAnchor), + // make a little bit large + elephantOnAirplaneWithContrailImageView.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 0.84), + ]) + + self.elephantOnAirplaneLeftConstraint = elephantOnAirplaneLeftConstraint + [ + rightHillImageView, + leftHillImageView, + centerHillImageView, + ].forEach { imageView in + imageView.translatesAutoresizingMaskIntoConstraints = false + addSubview(imageView) + imageView.pinTo(to: cloudBaseImageView) + } + + aspectLayoutConstraint = cloudBaseImageView.widthAnchor.constraint(equalTo: cloudBaseImageView.heightAnchor, multiplier: layout.artworkImageSize.width / layout.artworkImageSize.height) + aspectLayoutConstraint.isActive = true + } + + override func layoutSubviews() { + super.layoutSubviews() + + switch layout { + case .compact: + layoutCompact() + case .regular: + layoutRegular() + } + + aspectLayoutConstraint.isActive = false + aspectLayoutConstraint = cloudBaseImageView.widthAnchor.constraint(equalTo: cloudBaseImageView.heightAnchor, multiplier: layout.artworkImageSize.width / layout.artworkImageSize.height) + aspectLayoutConstraint.isActive = true + } + + private func layoutCompact() { + let size = layout.artworkImageSize + let width = size.width + let height = size.height + + cloudBaseImageView.image = UIGraphicsImageRenderer(size: size).image { context in + // clear background + UIColor.clear.setFill() + context.fill(CGRect(origin: .zero, size: size)) + + // draw cloud + cloudBaseImage.draw(at: CGPoint(x: 0, y: height - cloudBaseImage.size.height)) + } + + rightHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in + // clear background + UIColor.clear.setFill() + context.fill(CGRect(origin: .zero, size: size)) + + // draw elephantThreeOnGrassWithTreeTwoImage + // elephantThreeOnGrassWithTreeTwo.bottomY - 25 align to elephantThreeOnGrassImage.centerY + elephantThreeOnGrassWithTreeTwoImage.draw(at: CGPoint(x: width - elephantThreeOnGrassWithTreeTwoImage.size.width, y: height - 0.5 * elephantThreeOnGrassImage.size.height - elephantThreeOnGrassWithTreeTwoImage.size.height + 25)) + } + + leftHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in + // clear background + UIColor.clear.setFill() + context.fill(CGRect(origin: .zero, size: size)) + + // draw elephantThreeOnGrassWithTreeThree + // elephantThreeOnGrassWithTreeThree.bottomY + 30 align to elephantThreeOnGrassImage.centerY + elephantThreeOnGrassWithTreeThreeImage.draw(at: CGPoint(x: 0, y: height - 0.5 * elephantThreeOnGrassImage.size.height - elephantThreeOnGrassWithTreeThreeImage.size.height - 30)) + } + + centerHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in + // clear background + UIColor.clear.setFill() + context.fill(CGRect(origin: .zero, size: size)) + + // draw elephantThreeOnGrass + elephantThreeOnGrassImage.draw(at: CGPoint(x: 0, y: height - elephantThreeOnGrassImage.size.height)) + } + } + + private func layoutRegular() { + let size = layout.artworkImageSize + let width = size.width + let height = size.height + + cloudBaseImageView.image = UIGraphicsImageRenderer(size: size).image { context in + // clear background + UIColor.clear.setFill() + context.fill(CGRect(origin: .zero, size: size)) + + // draw cloud + cloudBaseExtendImage.draw(at: CGPoint(x: 0, y: height - cloudBaseExtendImage.size.height)) + + rightHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in + // clear background + UIColor.clear.setFill() + context.fill(CGRect(origin: .zero, size: size)) + + // draw elephantThreeOnGrassWithTreeTwoImage + // elephantThreeOnGrassWithTreeTwo.bottomY - 25 align to elephantThreeOnGrassImage.centerY + elephantThreeOnGrassWithTreeTwoImage.draw(at: CGPoint(x: width - elephantThreeOnGrassWithTreeTwoImage.size.width, y: height - 0.5 * elephantThreeOnGrassImage.size.height - elephantThreeOnGrassWithTreeTwoImage.size.height - 20)) + } + + leftHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in + // clear background + UIColor.clear.setFill() + context.fill(CGRect(origin: .zero, size: size)) + + // draw elephantThreeOnGrassWithTreeThree + // elephantThreeOnGrassWithTreeThree.bottomY + 30 align to elephantThreeOnGrassImage.centerY + elephantThreeOnGrassWithTreeThreeImage.draw(at: CGPoint(x: -160, y: height - 0.5 * elephantThreeOnGrassImage.size.height - elephantThreeOnGrassWithTreeThreeImage.size.height - 80)) + } + + centerHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in + // clear background + UIColor.clear.setFill() + context.fill(CGRect(origin: .zero, size: size)) + + // draw elephantThreeOnGrass + elephantThreeOnGrassExtendImage.draw(at: CGPoint(x: 0, y: height - elephantThreeOnGrassExtendImage.size.height)) + } + } + } + + func setup() { + layout = { + switch traitCollection.userInterfaceIdiom { + case .phone: + return .compact + default: + return .regular + } + }() + + // set illustration + guard superview == nil else { + return + } + contentMode = .scaleAspectFit + + cloudBaseImageView.addMotionEffect( + UIInterpolatingMotionEffect.motionEffect(minX: -5, maxX: 5, minY: -5, maxY: 5) + ) + rightHillImageView.addMotionEffect( + UIInterpolatingMotionEffect.motionEffect(minX: -15, maxX: 25, minY: -10, maxY: 10) + ) + leftHillImageView.addMotionEffect( + UIInterpolatingMotionEffect.motionEffect(minX: -25, maxX: 15, minY: -15, maxY: 15) + ) + centerHillImageView.addMotionEffect( + UIInterpolatingMotionEffect.motionEffect(minX: -14, maxX: 14, minY: -5, maxY: 25) + ) + + elephantOnAirplaneWithContrailImageView.addMotionEffect( + UIInterpolatingMotionEffect.motionEffect(minX: -20, maxX: 12, minY: -20, maxY: 12) // maxX should not larger then the bleeding (12pt) + ) + } + + func update(contentOffset: CGFloat) { + // updating the constraints doesn't work smoothly. + elephantOnAirplaneLeftConstraint?.constant = -(contentOffset / 50) + 111 } } diff --git a/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift b/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift index 3b5fa8f57..eaf2faf5b 100644 --- a/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift +++ b/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift @@ -21,29 +21,9 @@ final class WelcomeViewController: UIViewController, NeedsDependency { private(set) lazy var viewModel = WelcomeViewModel(context: context) let welcomeIllustrationView = WelcomeIllustrationView() - var welcomeIllustrationViewBottomAnchorLayoutConstraint: NSLayoutConstraint? private(set) lazy var dismissBarButtonItem = UIBarButtonItem(barButtonSystemItem: .close, target: self, action: #selector(WelcomeViewController.dismissBarButtonItemDidPressed(_:))) - private(set) lazy var logoImageView: UIImageView = { - let image = Asset.Scene.Welcome.mastodonLogo.image - let imageView = UIImageView(image: image) - imageView.translatesAutoresizingMaskIntoConstraints = false - imageView.isHidden = true - return imageView - }() - - private(set) lazy var sloganLabel: UILabel = { - let label = UILabel() - label.font = UIFontMetrics(forTextStyle: .largeTitle).scaledFont(for: .systemFont(ofSize: 34, weight: .bold)) - label.textColor = Asset.Colors.Label.primary.color - label.text = L10n.Scene.Welcome.slogan - label.adjustsFontForContentSizeCategory = true - label.translatesAutoresizingMaskIntoConstraints = false - label.numberOfLines = 0 - return label - }() - let buttonContainer = UIStackView() private(set) lazy var signUpButton: PrimaryActionButton = { @@ -101,7 +81,20 @@ extension WelcomeViewController { view.overrideUserInterfaceStyle = .light setupOnboardingAppearance() - setupIllustrationLayout() + + view.addSubview(welcomeIllustrationView) + welcomeIllustrationView.translatesAutoresizingMaskIntoConstraints = false + + let bottomAnchorLayoutConstraint = welcomeIllustrationView.bottomAnchor.constraint(equalTo: view.bottomAnchor) + + NSLayoutConstraint.activate([ + welcomeIllustrationView.topAnchor.constraint(equalTo: view.topAnchor), + welcomeIllustrationView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + view.trailingAnchor.constraint(equalTo: welcomeIllustrationView.trailingAnchor), + bottomAnchorLayoutConstraint + ]) + + welcomeIllustrationView.bottomAnchorLayoutConstraint = bottomAnchorLayoutConstraint buttonContainer.axis = .vertical buttonContainer.spacing = 12 @@ -147,6 +140,8 @@ extension WelcomeViewController { 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 { @@ -183,7 +178,7 @@ extension WelcomeViewController { if view.safeAreaInsets.bottom == 0 { overlap += 56 } - welcomeIllustrationViewBottomAnchorLayoutConstraint?.constant = overlap + welcomeIllustrationView.bottomAnchorLayoutConstraint?.constant = overlap } override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { @@ -194,7 +189,6 @@ extension WelcomeViewController { setupIllustrationLayout() setupButtonShadowView() } - } extension WelcomeViewController { @@ -245,91 +239,7 @@ extension WelcomeViewController { } private func setupIllustrationLayout() { - welcomeIllustrationView.layout = { - switch traitCollection.userInterfaceIdiom { - case .phone: - return .compact - default: - return .regular - } - }() - - // set logo - if logoImageView.superview == nil { - view.addSubview(logoImageView) - NSLayoutConstraint.activate([ - logoImageView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor), - logoImageView.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor, constant: 35), - view.readableContentGuide.trailingAnchor.constraint(equalTo: logoImageView.trailingAnchor, constant: 35), - logoImageView.heightAnchor.constraint(equalTo: logoImageView.widthAnchor, multiplier: 75.0/269.0), - ]) - logoImageView.setContentHuggingPriority(.defaultHigh, for: .vertical) - } - - // set illustration - guard welcomeIllustrationView.superview == nil else { - return - } - welcomeIllustrationView.contentMode = .scaleAspectFit - - welcomeIllustrationView.translatesAutoresizingMaskIntoConstraints = false - welcomeIllustrationViewBottomAnchorLayoutConstraint = welcomeIllustrationView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 5) - - view.addSubview(welcomeIllustrationView) - // welcomeIllustrationView.isHidden = true - NSLayoutConstraint.activate([ - view.leftAnchor.constraint(equalTo: welcomeIllustrationView.leftAnchor, constant: 15), - welcomeIllustrationView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 15), - welcomeIllustrationViewBottomAnchorLayoutConstraint!.priority(.required - 1), - ]) - - welcomeIllustrationView.cloudBaseImageView.addMotionEffect( - UIInterpolatingMotionEffect.motionEffect(minX: -5, maxX: 5, minY: -5, maxY: 5) - ) - welcomeIllustrationView.rightHillImageView.addMotionEffect( - UIInterpolatingMotionEffect.motionEffect(minX: -15, maxX: 25, minY: -10, maxY: 10) - ) - welcomeIllustrationView.leftHillImageView.addMotionEffect( - UIInterpolatingMotionEffect.motionEffect(minX: -25, maxX: 15, minY: -15, maxY: 15) - ) - welcomeIllustrationView.centerHillImageView.addMotionEffect( - UIInterpolatingMotionEffect.motionEffect(minX: -14, maxX: 14, minY: -5, maxY: 25) - ) - - let topPaddingView = UIView() - topPaddingView.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(topPaddingView) - NSLayoutConstraint.activate([ - topPaddingView.topAnchor.constraint(equalTo: logoImageView.bottomAnchor), - topPaddingView.leadingAnchor.constraint(equalTo: logoImageView.leadingAnchor), - topPaddingView.trailingAnchor.constraint(equalTo: logoImageView.trailingAnchor), - ]) - welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(welcomeIllustrationView.elephantOnAirplaneWithContrailImageView) - NSLayoutConstraint.activate([ - view.leftAnchor.constraint(equalTo: welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.leftAnchor, constant: 12), // add 12pt bleeding - welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.topAnchor.constraint(equalTo: topPaddingView.bottomAnchor), - // make a little bit large - welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.84), - welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.heightAnchor.constraint(equalTo: welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.widthAnchor, multiplier: 105.0/318.0), - ]) - let bottomPaddingView = UIView() - bottomPaddingView.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(bottomPaddingView) - NSLayoutConstraint.activate([ - bottomPaddingView.topAnchor.constraint(equalTo: welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.bottomAnchor), - bottomPaddingView.leadingAnchor.constraint(equalTo: logoImageView.leadingAnchor), - bottomPaddingView.trailingAnchor.constraint(equalTo: logoImageView.trailingAnchor), - bottomPaddingView.bottomAnchor.constraint(equalTo: view.centerYAnchor), - bottomPaddingView.heightAnchor.constraint(equalTo: topPaddingView.heightAnchor, multiplier: 4), - ]) - - welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.addMotionEffect( - UIInterpolatingMotionEffect.motionEffect(minX: -20, maxX: 12, minY: -20, maxY: 12) // maxX should not larger then the bleeding (12pt) - ) - - view.bringSubviewToFront(logoImageView) - view.bringSubviewToFront(sloganLabel) + welcomeIllustrationView.setup() } } @@ -410,6 +320,7 @@ extension WelcomeViewController: UIPageViewControllerDelegate { if let pageIndex = WelcomeContentPage.allCases.firstIndex(of: currentPage) { let offset = Int(pageIndex) * Int(pageViewController.view.frame.width) currentPageOffset = offset + welcomeIllustrationView.update(contentOffset: CGFloat(offset)) } } }