Commit 4bad4c86 by Dmitriy Stepanets

Starting working on RadarController

parent 6957e2c8
No preview for this file type
......@@ -29,7 +29,7 @@ class AppCoordinator: Coordinator {
forecastCoordinator.start()
childCoordinators.append(forecastCoordinator)
let radarCoordinator = ForecastCoordinator(tabBarController: tabBarController)
let radarCoordinator = RadarCoordinator(tabBarController: tabBarController)
radarCoordinator.start()
childCoordinators.append(radarCoordinator)
......
//
// RadarCoordinator.swift
// 1Weather
//
// Created by Dmitry Stepanets on 09.04.2021.
//
import UIKit
class RadarCoordinator: Coordinator {
//Private
private let navigationController = UINavigationController(nibName: nil, bundle: nil)
private var tabBarController:UITabBarController?
//Public
var childCoordinators = [Coordinator]()
var parentCoordinator: Coordinator?
init(tabBarController:UITabBarController) {
self.tabBarController = tabBarController
}
func start() {
let radarViewController = RadarViewController(coordinator: self)
navigationController.viewControllers = [radarViewController]
tabBarController?.add(viewController: navigationController)
}
func viewControllerDidEnd(controller: UIViewController) {
//
}
}
{
"images" : [
{
"filename" : "map_fullscreen.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}
{
"images" : [
{
"filename" : "map_layers.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}
{
"images" : [
{
"filename" : "map_precipitation.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}
{
"images" : [
{
"filename" : "map_radar.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}
{
"images" : [
{
"filename" : "map_time_bubble.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}
{
"images" : [
{
"filename" : "pause_icon.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}
{
"images" : [
{
"filename" : "play_icon.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "253",
"green" : "247",
"red" : "246"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "26",
"green" : "23",
"red" : "23"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
......@@ -110,4 +110,9 @@ struct DefaultTheme: ThemeProtocol {
var graphTintColor: UIColor {
return UIColor(named: "graph_tint_color") ?? .red
}
//Map
var mapControlsColor: UIColor {
return UIColor(named: "map_controls_color") ?? .red
}
}
......@@ -46,4 +46,7 @@ public protocol ThemeProtocol {
//Graph
var graphColor:UIColor { get }
var graphTintColor:UIColor { get }
//Map
var mapControlsColor:UIColor { get }
}
//
// MapButton.swift
// 1Weather
//
// Created by Dmitry Stepanets on 09.04.2021.
//
import UIKit
class MapButton: UIControl {
//Private
private let imageView = UIImageView()
private let gradient = CAGradientLayer()
init(image: UIImage?) {
super.init(frame: .zero)
self.imageView.image = image
prepareButton()
prepareGradient()
prepareImageView()
updateUI()
}
override func layoutSubviews() {
super.layoutSubviews()
self.layer.cornerRadius = (self.bounds.height / 2).rounded(.down)
self.gradient.frame = self.bounds
self.gradient.cornerRadius = (self.bounds.height / 2).rounded(.down)
self.layer.shadowPath = UIBezierPath(roundedRect: self.bounds, cornerRadius: self.layer.cornerRadius).cgPath
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
updateUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
UIView.performWithoutAnimation {
self.alpha = 0.7
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
UIView.performWithoutAnimation {
self.alpha = 1
}
}
//Private
private func updateUI() {
switch interfaceStyle {
case .light:
self.gradient.opacity = 0
self.backgroundColor = ThemeManager.currentTheme.mapControlsColor.withAlphaComponent(0.8)
self.imageView.tintColor = UIColor(hex: 0x3a4044)
case .dark:
self.gradient.opacity = 0.8
self.backgroundColor = .clear
self.imageView.tintColor = .white
}
}
}
//MARK:- Prepare
private extension MapButton {
func prepareButton() {
self.clipsToBounds = false
layer.shadowColor = UIColor.black.withAlphaComponent(0.3).cgColor
layer.shadowOffset = .init(width: 0, height: 3)
layer.shadowOpacity = 1
layer.shadowRadius = 5
}
func prepareGradient() {
gradient.startPoint = .init(x: 0.5, y: 0)
gradient.endPoint = .init(x: 0.5, y: 1)
gradient.colors = [UIColor(hex: 0x49494d).cgColor, UIColor(hex: 0x29292d).cgColor]
gradient.opacity = 0.8
layer.insertSublayer(gradient, at: 0)
}
func prepareImageView() {
imageView.isUserInteractionEnabled = false
imageView.contentMode = .center
imageView.clipsToBounds = true
addSubview(imageView)
imageView.snp.makeConstraints { (make) in
make.edges.equalToSuperview()
}
}
}
//
// CurrentTimeView.swift
// 1Weather
//
// Created by Dmitry Stepanets on 09.04.2021.
//
import UIKit
class CurrentTimeView: UIView {
private let imageView = UIImageView()
private let tempLabel = UILabel()
private let timeLabel = UILabel()
init() {
super.init(frame: .zero)
prepareView()
prepareImageView()
prepareLabels()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
//MARK:- Prepare
private extension CurrentTimeView {
func prepareView() {
self.backgroundColor = .clear
}
func prepareImageView() {
imageView.contentMode = .scaleAspectFit
imageView.image = UIImage(named: "map_time_bubble")
imageView.tintColor = ThemeManager.currentTheme.graphTintColor
addSubview(imageView)
imageView.snp.makeConstraints { (make) in
make.edges.equalToSuperview()
}
}
func prepareLabels() {
tempLabel.font = AppFont.SFPro.bold(size: 14)
tempLabel.textColor = .white
tempLabel.text = "49°"
tempLabel.setContentHuggingPriority(.fittingSizeLevel, for: .vertical)
addSubview(tempLabel)
timeLabel.font = AppFont.SFPro.bold(size: 10)
timeLabel.textColor = .white
timeLabel.text = "2:50 PM"
addSubview(timeLabel)
//Constraints
tempLabel.snp.makeConstraints { (make) in
make.top.equalToSuperview().inset(4)
make.centerX.equalToSuperview()
}
timeLabel.snp.makeConstraints { (make) in
make.top.equalTo(tempLabel.snp.bottom)
make.left.right.equalToSuperview().inset(4)
make.bottom.equalToSuperview().inset(9)
}
}
}
//
// MapTimeControlView.swift
// 1Weather
//
// Created by Dmitry Stepanets on 09.04.2021.
//
import UIKit
class MapTimeControlView: UIView {
//Private
private let container = UIView()
private let playButton = UIButton()
private let playButtonGradient = CAGradientLayer()
private let stackView = UIStackView()
private let currenTimeView = CurrentTimeView()
init() {
super.init(frame: .zero)
prepareView()
prepareContainer()
preparePlayButton()
prepareStackView()
prepareCurrentTimeView()
updateUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
container.layoutIfNeeded()
playButton.layoutIfNeeded()
playButton.layer.cornerRadius = (playButton.bounds.width / 2).rounded(.down)
playButtonGradient.frame = playButton.bounds
playButtonGradient.cornerRadius = playButton.layer.cornerRadius
container.layer.shadowPath = UIBezierPath(roundedRect: self.container.bounds,
cornerRadius: 14).cgPath
playButton.layer.shadowPath = UIBezierPath(roundedRect: self.playButton.bounds,
cornerRadius: self.playButton.layer.cornerRadius).cgPath
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
updateUI()
}
private func updateUI() {
container.backgroundColor = ThemeManager.currentTheme.mapControlsColor
switch interfaceStyle {
case .light:
playButtonGradient.colors = [UIColor(hex: 0xffffff).cgColor, UIColor(hex: 0xeceef6).cgColor]
case .dark:
playButtonGradient.colors = [UIColor(hex: 0x49494d).cgColor, UIColor(hex: 0x29292d).cgColor]
}
}
}
//MARK:- Prepare
private extension MapTimeControlView {
func prepareView() {
backgroundColor = .clear
}
func prepareContainer() {
container.layer.cornerRadius = 14
container.layer.shadowColor = UIColor(hex:0x0c192f).withAlphaComponent(0.06).cgColor
container.layer.shadowOffset = .init(width: 0, height: 5)
container.layer.shadowRadius = 20
container.layer.shadowOpacity = 1
addSubview(container)
container.snp.makeConstraints { (make) in
make.left.bottom.right.equalToSuperview()
make.height.equalTo(46)
}
}
func preparePlayButton() {
playButton.setImage(UIImage(named: "play_icon"), for: .normal)
playButton.tintColor = ThemeManager.currentTheme.graphTintColor
playButton.layer.shadowColor = UIColor.black.withAlphaComponent(0.12).cgColor
playButton.layer.shadowOffset = .init(width: 0, height: 3)
playButton.layer.shadowRadius = 8
playButton.layer.shadowOpacity = 1
playButtonGradient.startPoint = .init(x: 0.5, y: 0)
playButtonGradient.endPoint = .init(x: 0.5, y: 1)
playButton.layer.insertSublayer(playButtonGradient, below: playButton.imageView?.layer)
container.addSubview(playButton)
playButton.snp.makeConstraints { (make) in
make.width.height.equalTo(24)
make.centerY.equalToSuperview()
make.left.equalToSuperview().inset(12)
}
}
func prepareStackView() {
stackView.axis = .horizontal
stackView.distribution = .fillProportionally
stackView.clipsToBounds = false
container.addSubview(stackView)
stackView.snp.makeConstraints { (make) in
make.top.bottom.equalToSuperview()
make.left.equalTo(playButton.snp.right).offset(8)
make.right.equalToSuperview().inset(8)
}
for _ in 0..<5 {
let view = MapTimeView()
stackView.addArrangedSubview(view)
}
}
func prepareCurrentTimeView() {
addSubview(currenTimeView)
currenTimeView.snp.makeConstraints { (make) in
make.top.equalToSuperview()
make.bottom.equalTo(container.snp.top)
make.centerX.equalToSuperview()
}
}
}
//
// MapTimeView.swift
// 1Weather
//
// Created by Dmitry Stepanets on 09.04.2021.
//
import UIKit
class MapTimeView: UIView {
private let tempLabel = UILabel()
private let timeLabel = UILabel()
init() {
super.init(frame: .zero)
prepareLabels()
updateUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
updateUI()
}
private func updateUI() {
switch interfaceStyle {
case .light:
tempLabel.textColor = ThemeManager.currentTheme.secondaryTextColor
timeLabel.textColor = ThemeManager.currentTheme.secondaryTextColor
case .dark:
tempLabel.textColor = ThemeManager.currentTheme.primaryTextColor
timeLabel.textColor = ThemeManager.currentTheme.primaryTextColor
}
}
}
private extension MapTimeView {
func prepareLabels() {
tempLabel.text = "45°"
tempLabel.font = AppFont.SFPro.regular(size: 10)
addSubview(tempLabel)
timeLabel.text = "2:00"
timeLabel.textAlignment = .center
timeLabel.font = AppFont.SFPro.regular(size: 14)
timeLabel.setContentCompressionResistancePriority(.fittingSizeLevel, for: .vertical)
addSubview(timeLabel)
//Constraints
tempLabel.snp.makeConstraints { (make) in
make.top.equalToSuperview().inset(10)
make.centerX.equalToSuperview()
}
timeLabel.snp.makeConstraints { (make) in
make.bottom.equalToSuperview().inset(5)
make.top.equalTo(tempLabel.snp.bottom).offset(4)
make.left.right.equalToSuperview().inset(2)
}
}
}
//
// RadarViewController.swift
// 1Weather
//
// Created by Dmitry Stepanets on 09.04.2021.
//
import UIKit
import MapKit
class RadarViewController: UIViewController {
//Private
private let coordinator:RadarCoordinator
private let cityButton = NavigationCityButton()
private var localizationObserver:Any?
private let mapView = MKMapView()
//Buttons
private let fullScreenButton = MapButton(image: UIImage(named: "map_fullscreen"))
private let precipitationButton = MapButton(image: UIImage(named: "map_precipitation"))
private let layersButton = MapButton(image: UIImage(named: "map_layers"))
private let radarButton = MapButton(image: UIImage(named: "map_radar"))
private let mapTimeControlView = MapTimeControlView()
private let locationButton = UIButton()
init(coordinator:RadarCoordinator) {
self.coordinator = coordinator
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
updateUI()
}
override func viewDidLoad() {
super.viewDidLoad()
prepareNavigationBar()
prepareViewController()
// prepareMapView()
prepareLocationButton()
prepareMapButtons()
prepareMapTimeControl()
updateUI()
}
//Private
private func updateUI() {
view.backgroundColor = ThemeManager.currentTheme.baseBackgroundColor
locationButton.backgroundColor = ThemeManager.currentTheme.mapControlsColor
}
@objc private func handleCityButton() {
}
@objc private func handleNotificationButton() {
}
@objc private func handleFullScreenButton() {
}
@objc private func handlePrecipitationButton() {
}
@objc private func handleLayersButton() {
}
@objc private func handleRadarButton() {
}
@objc private func handleLocationButton() {
}
}
//MARK:- Prepare
private extension RadarViewController {
func prepareViewController() {
localizationObserver = NotificationCenter.default.addObserver(forName: .localizationChange, object: nil, queue: .main, using: { _ in
})
}
func prepareNavigationBar() {
//City button
cityButton.addTarget(self, action: #selector(handleCityButton), for: .touchUpInside)
let cityBarItem = UIBarButtonItem(customView: cityButton)
let barSpacer = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
barSpacer.width = 18
//Notification button
let notificationButton = UIButton()
notificationButton.frame = .init(origin: .zero, size: .init(width: 40, height: 40))
notificationButton.setImage(UIImage(named: "bell"), for: .normal)
notificationButton.tintColor = ThemeManager.currentTheme.primaryTextColor
notificationButton.addTarget(self, action: #selector(handleNotificationButton), for: .touchUpInside)
let notificationBarButton = UIBarButtonItem(customView: notificationButton)
notificationButton.contentEdgeInsets = .init(top: 0, left: 16, bottom: 0, right: 0)
self.navigationItem.leftBarButtonItems = [barSpacer, cityBarItem]
self.navigationItem.rightBarButtonItem = notificationBarButton
}
func prepareMapView() {
mapView.showsCompass = false
view.addSubview(mapView)
mapView.snp.makeConstraints { (make) in
make.edges.equalToSuperview()
}
}
func prepareMapButtons() {
//Full screen
fullScreenButton.addTarget(self, action: #selector(handleFullScreenButton), for: .touchUpInside)
view.addSubview(fullScreenButton)
fullScreenButton.snp.makeConstraints { (make) in
make.width.height.equalTo(40)
make.top.equalToSuperview().inset(16)
make.right.equalToSuperview().inset(8)
}
//Precipitation
precipitationButton.addTarget(self, action: #selector(handlePrecipitationButton), for: .touchUpInside)
view.addSubview(precipitationButton)
precipitationButton.snp.makeConstraints { (make) in
make.width.height.equalTo(46)
make.right.equalToSuperview().inset(8)
make.bottom.equalTo(locationButton.snp.top).offset(-18)
}
//Layers
layersButton.addTarget(self, action: #selector(handleLayersButton), for: .touchUpInside)
view.addSubview(layersButton)
layersButton.snp.makeConstraints { (make) in
make.width.height.equalTo(46)
make.right.equalToSuperview().inset(8)
make.bottom.equalTo(precipitationButton.snp.top).offset(-18)
}
//Radar
radarButton.addTarget(self, action: #selector(handleRadarButton), for: .touchUpInside)
view.addSubview(radarButton)
radarButton.snp.makeConstraints { (make) in
make.width.height.equalTo(46)
make.right.equalToSuperview().inset(8)
make.bottom.equalTo(layersButton.snp.top).offset(-18)
}
}
func prepareLocationButton() {
locationButton.setImage(UIImage(named: "location_arrow"), for: .normal)
locationButton.layer.cornerRadius = 14
locationButton.addTarget(self, action: #selector(handleLocationButton), for: .touchUpInside)
locationButton.tintColor = ThemeManager.currentTheme.graphTintColor
view.addSubview(locationButton)
locationButton.snp.makeConstraints { (make) in
make.width.height.equalTo(46)
make.right.equalToSuperview().inset(8)
make.bottom.equalToSuperview().inset(4)
}
}
func prepareMapTimeControl() {
view.addSubview(mapTimeControlView)
mapTimeControlView.snp.makeConstraints { (make) in
make.left.bottom.equalToSuperview().inset(4)
make.right.equalTo(locationButton.snp.left).offset(-4)
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment