Commit 11ba9772 by Dmitriy Stepanets

Added generic initialization for the period button

parent e8b2c07d
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
<key>1Weather.xcscheme_^#shared#^_</key> <key>1Weather.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>6</integer> <integer>5</integer>
</dict> </dict>
<key>PG (Playground) 1.xcscheme</key> <key>PG (Playground) 1.xcscheme</key>
<dict> <dict>
......
//
// ForecastDetailPeriodButton.swift
// 1Weather
//
// Created by Dmitry Stepanets on 11.03.2021.
//
import UIKit
class ForecastDetailPeriodButton: PeriodButton {
required init() {
super.init()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func configure(dailyWeather: DailyWeather) {
//
}
override func configure(hourlyWeather: HourlyWeather) {
//
}
}
// //
// PeriodForecastButton.swift // ForecastPeriodButton.swift
// 1Weather // 1Weather
// //
// Created by Dmitry Stepanets on 15.02.2021. // Created by Dmitry Stepanets on 15.02.2021.
...@@ -7,14 +7,14 @@ ...@@ -7,14 +7,14 @@
import UIKit import UIKit
class PeriodForecastButton: UIControl { class ForecastPeriodButton: PeriodButton {
//Private //Private
private static let hourlyFormatter: DateFormatter = { private let hourlyFormatter: DateFormatter = {
let fmt = DateFormatter() let fmt = DateFormatter()
fmt.dateFormat = "h a" fmt.dateFormat = "h a"
return fmt return fmt
}() }()
private static let dailyFormatter: DateFormatter = { private let dailyFormatter: DateFormatter = {
let fmt = DateFormatter() let fmt = DateFormatter()
fmt.dateFormat = "d, E" fmt.dateFormat = "d, E"
return fmt return fmt
...@@ -27,7 +27,6 @@ class PeriodForecastButton: UIControl { ...@@ -27,7 +27,6 @@ class PeriodForecastButton: UIControl {
private let timeLabel = UILabel() private let timeLabel = UILabel()
//Public //Public
var index:Int = -1
var graphRect:CGRect { var graphRect:CGRect {
let topInset = self.tempLabel.frame.origin.y + self.tempLabel.frame.size.height + kGraphInset let topInset = self.tempLabel.frame.origin.y + self.tempLabel.frame.size.height + kGraphInset
...@@ -37,15 +36,15 @@ class PeriodForecastButton: UIControl { ...@@ -37,15 +36,15 @@ class PeriodForecastButton: UIControl {
height: self.minTempLabel.frame.origin.y - self.tempLabel.frame.origin.y - tempLabel.frame.height) height: self.minTempLabel.frame.origin.y - self.tempLabel.frame.origin.y - tempLabel.frame.height)
} }
override init(frame: CGRect) { required init() {
super.init(frame: .zero) super.init()
prepareButton() prepareButton()
prepareForecastImage() prepareForecastImage()
prepareTempLabel() prepareTempLabel()
prepareMinTempLabel()
preparePeriodIndicator()
prepareTimeLabel() prepareTimeLabel()
preparePeriodIndicator()
prepareMinTempLabel()
} }
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
...@@ -80,7 +79,7 @@ class PeriodForecastButton: UIControl { ...@@ -80,7 +79,7 @@ class PeriodForecastButton: UIControl {
} }
//Public //Public
public func configure(dailyWeather: DailyWeather) { override func configure(dailyWeather: DailyWeather) {
self.tempLabel.text = dailyWeather.maxTemp?.shortString self.tempLabel.text = dailyWeather.maxTemp?.shortString
self.minTempLabel.text = dailyWeather.minTemp?.shortString self.minTempLabel.text = dailyWeather.minTemp?.shortString
self.indicatorImageView.image = nil self.indicatorImageView.image = nil
...@@ -89,19 +88,19 @@ class PeriodForecastButton: UIControl { ...@@ -89,19 +88,19 @@ class PeriodForecastButton: UIControl {
self.timeLabel.text = "day.today".localized() self.timeLabel.text = "day.today".localized()
} }
else { else {
self.timeLabel.text = PeriodForecastButton.dailyFormatter.string(from: dailyWeather.date) self.timeLabel.text = dailyFormatter.string(from: dailyWeather.date)
} }
} }
public func configure(hourlyWeather: HourlyWeather) { override func configure(hourlyWeather: HourlyWeather) {
self.tempLabel.text = hourlyWeather.temp?.shortString self.tempLabel.text = hourlyWeather.temp?.shortString
self.minTempLabel.text = nil self.minTempLabel.text = nil
self.indicatorImageView.image = nil self.indicatorImageView.image = nil
self.timeLabel.text = PeriodForecastButton.hourlyFormatter.string(from: hourlyWeather.date) self.timeLabel.text = hourlyFormatter.string(from: hourlyWeather.date)
} }
} }
private extension PeriodForecastButton { private extension ForecastPeriodButton {
func prepareButton() { func prepareButton() {
clipsToBounds = false clipsToBounds = false
backgroundColor = UIColor.white backgroundColor = UIColor.white
...@@ -143,7 +142,7 @@ private extension PeriodForecastButton { ...@@ -143,7 +142,7 @@ private extension PeriodForecastButton {
minTempLabel.snp.makeConstraints { (make) in minTempLabel.snp.makeConstraints { (make) in
make.centerX.equalToSuperview() make.centerX.equalToSuperview()
make.top.greaterThanOrEqualTo(tempLabel.snp.bottom).offset(55) make.bottom.equalTo(indicatorImageView.snp.top).offset(-10)
} }
} }
...@@ -156,7 +155,7 @@ private extension PeriodForecastButton { ...@@ -156,7 +155,7 @@ private extension PeriodForecastButton {
indicatorImageView.snp.makeConstraints { (make) in indicatorImageView.snp.makeConstraints { (make) in
make.width.height.equalTo(12) make.width.height.equalTo(12)
make.centerX.equalToSuperview() make.centerX.equalToSuperview()
make.top.equalTo(minTempLabel.snp.bottom).offset(10) make.bottom.equalTo(timeLabel.snp.top).offset(-15)
} }
} }
...@@ -168,7 +167,6 @@ private extension PeriodForecastButton { ...@@ -168,7 +167,6 @@ private extension PeriodForecastButton {
addSubview(timeLabel) addSubview(timeLabel)
timeLabel.snp.makeConstraints { (make) in timeLabel.snp.makeConstraints { (make) in
make.top.equalTo(indicatorImageView.snp.bottom).offset(15)
make.centerX.equalToSuperview() make.centerX.equalToSuperview()
make.bottom.equalToSuperview().inset(20) make.bottom.equalToSuperview().inset(20)
} }
......
...@@ -20,6 +20,8 @@ class ForecastTimePeriodView: UIView { ...@@ -20,6 +20,8 @@ class ForecastTimePeriodView: UIView {
//Private //Private
private let scrollView = UIScrollView() private let scrollView = UIScrollView()
private let stackView = UIStackView() private let stackView = UIStackView()
private let buttonType:PeriodButton.Type
private var buttonProtocol:PeriodButtonProtocol.Type!
private let graphView = GraphView() private let graphView = GraphView()
private var graphRect:CGRect = .zero private var graphRect:CGRect = .zero
private var currentTimePeriod = TimePeriod.daily private var currentTimePeriod = TimePeriod.daily
...@@ -31,7 +33,9 @@ class ForecastTimePeriodView: UIView { ...@@ -31,7 +33,9 @@ class ForecastTimePeriodView: UIView {
} }
} }
init() { //MARK:- View life cycle
init<T: PeriodButton>(buttonType: T.Type) {
self.buttonType = buttonType
super.init(frame: .zero) super.init(frame: .zero)
preapreView() preapreView()
...@@ -40,6 +44,12 @@ class ForecastTimePeriodView: UIView { ...@@ -40,6 +44,12 @@ class ForecastTimePeriodView: UIView {
prepareGraphView() prepareGraphView()
} }
convenience init<T: PeriodButtonProtocol>(buttonProtocol: T) {
self.init(buttonType: PeriodButton.self)
self.buttonProtocol = T.self
}
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
...@@ -55,6 +65,14 @@ class ForecastTimePeriodView: UIView { ...@@ -55,6 +65,14 @@ class ForecastTimePeriodView: UIView {
} }
//Private //Private
private func createButton<T: PeriodButton>(typeThing:T.Type) -> T {
return typeThing.init()
}
private func createFromProtocol<T: PeriodButtonProtocol>(typeThing: T.Type) -> T {
return typeThing.init()
}
private func rebuildButtons() { private func rebuildButtons() {
stackView.arrangedSubviews.forEach { stackView.arrangedSubviews.forEach {
stackView.removeArrangedSubview($0) stackView.removeArrangedSubview($0)
...@@ -64,21 +82,29 @@ class ForecastTimePeriodView: UIView { ...@@ -64,21 +82,29 @@ class ForecastTimePeriodView: UIView {
switch currentTimePeriod { switch currentTimePeriod {
case .daily: case .daily:
for index in 0..<forecastTimePeriod.daily.count { for index in 0..<forecastTimePeriod.daily.count {
let forecastButton = PeriodForecastButton() let forecastButton = self.createButton(typeThing: buttonType)
forecastButton.configure(dailyWeather: forecastTimePeriod.daily[index]) forecastButton.configure(dailyWeather: forecastTimePeriod.daily[index])
forecastButton.index = index forecastButton.index = index
forecastButton.addTarget(self, action: #selector(handleForecastButton(button:)), for: .touchUpInside) forecastButton.addTarget(self, action: #selector(handleForecastButton(button:)), for: .touchUpInside)
forecastButton.isSelected = index == 1 forecastButton.isSelected = index == 1
stackView.addArrangedSubview(forecastButton) stackView.addArrangedSubview(forecastButton)
forecastButton.snp.makeConstraints { (make) in
make.height.equalToSuperview()
}
} }
case .hourly: case .hourly:
for index in 0..<forecastTimePeriod.hourly.count { for index in 0..<forecastTimePeriod.hourly.count {
let forecastButton = PeriodForecastButton() let forecastButton = self.createButton(typeThing: buttonType)
forecastButton.configure(hourlyWeather: forecastTimePeriod.hourly[index]) forecastButton.configure(hourlyWeather: forecastTimePeriod.hourly[index])
forecastButton.index = index forecastButton.index = index
forecastButton.addTarget(self, action: #selector(handleForecastButton(button:)), for: .touchUpInside) forecastButton.addTarget(self, action: #selector(handleForecastButton(button:)), for: .touchUpInside)
forecastButton.isSelected = index == 1 forecastButton.isSelected = index == 1
stackView.addArrangedSubview(forecastButton) stackView.addArrangedSubview(forecastButton)
forecastButton.snp.makeConstraints { (make) in
make.height.equalToSuperview()
}
} }
} }
stackView.layoutIfNeeded() stackView.layoutIfNeeded()
...@@ -87,7 +113,7 @@ class ForecastTimePeriodView: UIView { ...@@ -87,7 +113,7 @@ class ForecastTimePeriodView: UIView {
private func updateGraphLayout() { private func updateGraphLayout() {
print("[ForecastTimePeriod] Update graph layout") print("[ForecastTimePeriod] Update graph layout")
graphRect = (stackView.arrangedSubviews.first as? PeriodForecastButton)?.graphRect ?? .zero graphRect = (stackView.arrangedSubviews.first as? ForecastPeriodButton)?.graphRect ?? .zero
graphView.frame = .init(x: 0, graphView.frame = .init(x: 0,
y: graphRect.origin.y, y: graphRect.origin.y,
width: stackView.frame.width, width: stackView.frame.width,
...@@ -116,7 +142,7 @@ class ForecastTimePeriodView: UIView { ...@@ -116,7 +142,7 @@ class ForecastTimePeriodView: UIView {
var maxPoints = [CGPoint]() var maxPoints = [CGPoint]()
var minPoints = [CGPoint]() var minPoints = [CGPoint]()
for index in 0..<daysCount { for index in 0..<daysCount {
guard let stackButton = stackView.arrangedSubviews[index] as? PeriodForecastButton else { continue } guard let stackButton = stackView.arrangedSubviews[index] as? ForecastPeriodButton else { continue }
let buttonRightSide = stackButton.frame.origin.x + stackButton.bounds.width let buttonRightSide = stackButton.frame.origin.x + stackButton.bounds.width
let buttonCenterX = (buttonRightSide + stackButton.frame.origin.x) / 2 let buttonCenterX = (buttonRightSide + stackButton.frame.origin.x) / 2
...@@ -152,7 +178,7 @@ class ForecastTimePeriodView: UIView { ...@@ -152,7 +178,7 @@ class ForecastTimePeriodView: UIView {
var points = [CGPoint]() var points = [CGPoint]()
for index in 0..<hoursCount { for index in 0..<hoursCount {
guard let stackButton = stackView.arrangedSubviews[index] as? PeriodForecastButton else { continue } guard let stackButton = stackView.arrangedSubviews[index] as? ForecastPeriodButton else { continue }
let buttonRightSide = stackButton.frame.origin.x + stackButton.bounds.width let buttonRightSide = stackButton.frame.origin.x + stackButton.bounds.width
let buttonCenterX = (buttonRightSide + stackButton.frame.origin.x) / 2 let buttonCenterX = (buttonRightSide + stackButton.frame.origin.x) / 2
...@@ -173,7 +199,7 @@ class ForecastTimePeriodView: UIView { ...@@ -173,7 +199,7 @@ class ForecastTimePeriodView: UIView {
private func drawGraph() { private func drawGraph() {
guard guard
let periodButtons = stackView.arrangedSubviews as? [PeriodForecastButton], let periodButtons = stackView.arrangedSubviews as? [ForecastPeriodButton],
let selectedButton = (periodButtons.first{ $0.isSelected }) let selectedButton = (periodButtons.first{ $0.isSelected })
else { else {
return return
...@@ -193,7 +219,7 @@ class ForecastTimePeriodView: UIView { ...@@ -193,7 +219,7 @@ class ForecastTimePeriodView: UIView {
print("[ForecastTimePeriod] Draw graph") print("[ForecastTimePeriod] Draw graph")
} }
private func tintGraphAt(button:PeriodForecastButton) { private func tintGraphAt(button:ForecastPeriodButton) {
switch currentTimePeriod { switch currentTimePeriod {
case .daily: case .daily:
self.graphView.tintGraphFrom(startPointX: button.frame.origin.x, self.graphView.tintGraphFrom(startPointX: button.frame.origin.x,
...@@ -207,9 +233,9 @@ class ForecastTimePeriodView: UIView { ...@@ -207,9 +233,9 @@ class ForecastTimePeriodView: UIView {
} }
} }
@objc private func handleForecastButton(button:PeriodForecastButton) { @objc private func handleForecastButton(button:ForecastPeriodButton) {
stackView.arrangedSubviews.forEach { stackView.arrangedSubviews.forEach {
if let periodButton = $0 as? PeriodForecastButton { if let periodButton = $0 as? ForecastPeriodButton {
periodButton.isSelected = periodButton === button periodButton.isSelected = periodButton === button
if periodButton.isSelected { if periodButton.isSelected {
......
//
// PeriodButton.swift
// 1Weather
//
// Created by Dmitry Stepanets on 12.03.2021.
//
import UIKit
class PeriodButton: UIControl {
//Public
public var index:Int = -1
required init() {
super.init(frame: .zero)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public func configure(dailyWeather: DailyWeather) {
}
public func configure(hourlyWeather: HourlyWeather) {
}
}
//
// PeriodButtonProtocol.swift
// 1Weather
//
// Created by Dmitry Stepanets on 11.03.2021.
//
import UIKit
public protocol PeriodButtonProtocol {
init()
func configure(dailyWeather: DailyWeather)
func configure(hourlyWeather: HourlyWeather)
}
struct PeriodButtonType: PeriodButtonProtocol {
func configure(dailyWeather: DailyWeather) {}
func configure(hourlyWeather: HourlyWeather) {}
}
...@@ -39,6 +39,7 @@ class ForecastCellFactory { ...@@ -39,6 +39,7 @@ class ForecastCellFactory {
switch cellType { switch cellType {
case .forecastPeriod: case .forecastPeriod:
let cell = dequeueReusableCell(type: ForecastTimePeriodCell.self, tableView: tableView, indexPath: indexPath) let cell = dequeueReusableCell(type: ForecastTimePeriodCell.self, tableView: tableView, indexPath: indexPath)
cell.configure(with: loc)
return cell return cell
} }
} }
......
...@@ -12,6 +12,7 @@ class ForecastTimePeriodCell: UITableViewCell { ...@@ -12,6 +12,7 @@ class ForecastTimePeriodCell: UITableViewCell {
private let periodSegmentedControl = ForecastTimePeriodControl(items: ["forecast.timePeriod.daily".localized(), private let periodSegmentedControl = ForecastTimePeriodControl(items: ["forecast.timePeriod.daily".localized(),
"forecast.timePeriod.hourly".localized()]) "forecast.timePeriod.hourly".localized()])
private let forecastTimePeriodView = ForecastTimePeriodView(buttonType: ForecastDetailPeriodButton.self)
private let gradientView = GradientView(startColor: UIColor(hex: 0xffffff).withAlphaComponent(0), private let gradientView = GradientView(startColor: UIColor(hex: 0xffffff).withAlphaComponent(0),
endColor: UIColor(hex: 0xdaddec), endColor: UIColor(hex: 0xdaddec),
opacity: 0.5) opacity: 0.5)
...@@ -22,6 +23,7 @@ class ForecastTimePeriodCell: UITableViewCell { ...@@ -22,6 +23,7 @@ class ForecastTimePeriodCell: UITableViewCell {
prepareCell() prepareCell()
prepareSegmentedControl() prepareSegmentedControl()
prepareGradient() prepareGradient()
prepareForecastTimePeriodView()
} }
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
...@@ -30,6 +32,8 @@ class ForecastTimePeriodCell: UITableViewCell { ...@@ -30,6 +32,8 @@ class ForecastTimePeriodCell: UITableViewCell {
//Public //Public
public func configure(with location:Location) { public func configure(with location:Location) {
let forecastTimePeriod = ForecastTimePeriod(daily: location.daily, hourly: location.hourly)
self.forecastTimePeriodView.set(forecastTimePeriod: forecastTimePeriod)
} }
@objc private func handleSegmentDidChange() { @objc private func handleSegmentDidChange() {
...@@ -55,6 +59,17 @@ private extension ForecastTimePeriodCell { ...@@ -55,6 +59,17 @@ private extension ForecastTimePeriodCell {
} }
} }
func prepareForecastTimePeriodView() {
contentView.addSubview(forecastTimePeriodView)
forecastTimePeriodView.snp.makeConstraints { (make) in
make.left.equalToSuperview()
make.right.equalToSuperview()
make.top.equalTo(periodSegmentedControl.snp.bottom).offset(20).priority(.medium)
make.bottom.equalToSuperview().inset(30)
make.height.equalTo(267)
}
}
func prepareGradient() { func prepareGradient() {
contentView.addSubview(gradientView) contentView.addSubview(gradientView)
gradientView.snp.makeConstraints { (make) in gradientView.snp.makeConstraints { (make) in
......
...@@ -11,7 +11,7 @@ class CityForecastTimePeriodCell: UITableViewCell { ...@@ -11,7 +11,7 @@ class CityForecastTimePeriodCell: UITableViewCell {
//Private //Private
private let periodSegmentedControl = ForecastTimePeriodControl(items: ["forecast.timePeriod.daily".localized(), private let periodSegmentedControl = ForecastTimePeriodControl(items: ["forecast.timePeriod.daily".localized(),
"forecast.timePeriod.hourly".localized()]) "forecast.timePeriod.hourly".localized()])
private let forecastTimePeriodView = ForecastTimePeriodView() private let forecastTimePeriodView = ForecastTimePeriodView(buttonType: ForecastPeriodButton.self)
private let summaryView = UIView() private let summaryView = UIView()
private let summaryImageView = UIImageView() private let summaryImageView = UIImageView()
private let summaryLabel = UILabel() private let summaryLabel = UILabel()
......
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
<key>XMLCoder.xcscheme_^#shared#^_</key> <key>XMLCoder.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>5</integer> <integer>6</integer>
</dict> </dict>
</dict> </dict>
<key>SuppressBuildableAutocreation</key> <key>SuppressBuildableAutocreation</key>
......
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