From 3dba1de84e88f23a4911ec1391a33ae577b3bfa7 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Wed, 12 Apr 2023 09:49:31 +0200 Subject: [PATCH] Implemented the LoadingSpinnerView custom view. --- .../View Components/LoadingSpinnerView.swift | 87 +++++++++++++++++++ DeepLinking.xcodeproj/project.pbxproj | 12 +++ 2 files changed, 99 insertions(+) create mode 100644 Apps/Locations/Sources/View Components/LoadingSpinnerView.swift diff --git a/Apps/Locations/Sources/View Components/LoadingSpinnerView.swift b/Apps/Locations/Sources/View Components/LoadingSpinnerView.swift new file mode 100644 index 0000000..c6865e2 --- /dev/null +++ b/Apps/Locations/Sources/View Components/LoadingSpinnerView.swift @@ -0,0 +1,87 @@ +// +// LoadingSpinnerView.swift +// Locations +// +// Created by Javier Cicchelli on 12/04/2023. +// Copyright © 2023 Röck+Cöde. All rights reserved. +// + +import UIKit + +class LoadingSpinnerView: UIView { + + // MARK: Outlets + + lazy var stack: UIStackView = { + let stack = UIStackView(frame: .zero) + + stack.alignment = .center + stack.axis = .vertical + stack.distribution = .fill + stack.spacing = 8 + stack.translatesAutoresizingMaskIntoConstraints = false + + return stack + }() + + lazy var spinner: UIActivityIndicatorView = { + let spinner = UIActivityIndicatorView(style: .large) + + spinner.translatesAutoresizingMaskIntoConstraints = false + + spinner.startAnimating() + + return spinner + }() + + lazy var label: UILabel = { + let label = UILabel() + + label.translatesAutoresizingMaskIntoConstraints = false + label.font = .preferredFont(forTextStyle: .headline) + label.text = "Loading..." + label.textAlignment = .center + label.numberOfLines = 0 + label.lineBreakMode = .byWordWrapping + + return label + }() + + // MARK: Initialisers + + init() { + super.init(frame: .zero) + + setupView() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} + +// MARK: - Helpers + +private extension LoadingSpinnerView { + + // MARK: Functions + + func setupView() { + backgroundColor = .clear + translatesAutoresizingMaskIntoConstraints = false + + stack.addArrangedSubview(spinner) + stack.addArrangedSubview(label) + + addSubview(stack) + + NSLayoutConstraint.activate([ + topAnchor.constraint(equalTo: stack.topAnchor), + leadingAnchor.constraint(equalTo: stack.leadingAnchor), + trailingAnchor.constraint(equalTo: stack.trailingAnchor), + bottomAnchor.constraint(equalTo: stack.bottomAnchor), + ]) + } + +} diff --git a/DeepLinking.xcodeproj/project.pbxproj b/DeepLinking.xcodeproj/project.pbxproj index 33b73ae..2be6b99 100644 --- a/DeepLinking.xcodeproj/project.pbxproj +++ b/DeepLinking.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 02031EBF29E5F949003C108C /* LocationsAddViewModeling.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02031EBE29E5F949003C108C /* LocationsAddViewModeling.swift */; }; 02031EC629E5FEE4003C108C /* BaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02031EC529E5FEE4003C108C /* BaseViewController.swift */; }; 02031EC929E60B29003C108C /* DependencyService+Keys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02031EC829E60B29003C108C /* DependencyService+Keys.swift */; }; + 02031EE829E68D9B003C108C /* LoadingSpinnerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02031EE729E68D9B003C108C /* LoadingSpinnerView.swift */; }; 46C3B7C629E5BF1500F8F57C /* LocationsListCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46C3B7C529E5BF1500F8F57C /* LocationsListCoordinator.swift */; }; 46C3B7CB29E5CD3200F8F57C /* LocationsListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46C3B7CA29E5CD3200F8F57C /* LocationsListViewModel.swift */; }; 46C3B7CF29E5D00E00F8F57C /* LocationsAddViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46C3B7CE29E5D00E00F8F57C /* LocationsAddViewModel.swift */; }; @@ -124,6 +125,7 @@ 02031EBE29E5F949003C108C /* LocationsAddViewModeling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationsAddViewModeling.swift; sourceTree = ""; }; 02031EC529E5FEE4003C108C /* BaseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseViewController.swift; sourceTree = ""; }; 02031EC829E60B29003C108C /* DependencyService+Keys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DependencyService+Keys.swift"; sourceTree = ""; }; + 02031EE729E68D9B003C108C /* LoadingSpinnerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingSpinnerView.swift; sourceTree = ""; }; 46C3B7C529E5BF1500F8F57C /* LocationsListCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationsListCoordinator.swift; sourceTree = ""; }; 46C3B7CA29E5CD3200F8F57C /* LocationsListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationsListViewModel.swift; sourceTree = ""; }; 46C3B7CE29E5D00E00F8F57C /* LocationsAddViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationsAddViewModel.swift; sourceTree = ""; }; @@ -174,6 +176,14 @@ path = Extensions; sourceTree = ""; }; + 02031EE629E68D7A003C108C /* View Components */ = { + isa = PBXGroup; + children = ( + 02031EE729E68D9B003C108C /* LoadingSpinnerView.swift */, + ); + path = "View Components"; + sourceTree = ""; + }; 0276C96029E5F5DC000B62AF /* Protocols */ = { isa = PBXGroup; children = ( @@ -304,6 +314,7 @@ 46C3B7C429E5BEE900F8F57C /* Coordinators */, 46C3B7C929E5CB8F00F8F57C /* Screens */, 02031EC429E5FEB1003C108C /* View Controllers */, + 02031EE629E68D7A003C108C /* View Components */, ); path = Sources; sourceTree = ""; @@ -521,6 +532,7 @@ 46C3B7CF29E5D00E00F8F57C /* LocationsAddViewModel.swift in Sources */, 02031EC929E60B29003C108C /* DependencyService+Keys.swift in Sources */, 46C3B7D129E5D06D00F8F57C /* LocationsAddViewController.swift in Sources */, + 02031EE829E68D9B003C108C /* LoadingSpinnerView.swift in Sources */, 46C3B7CB29E5CD3200F8F57C /* LocationsListViewModel.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0;