Commit 11ba9772 by Dmitriy Stepanets

Added generic initialization for the period button

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