Commit 92fda9d3 by Dmitriy Stepanets

Added sync between DayControlsButton and ForecastTimePeriodCell

parent bbf41fed
...@@ -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>4</integer> <integer>5</integer>
</dict> </dict>
<key>PG (Playground) 1.xcscheme</key> <key>PG (Playground) 1.xcscheme</key>
<dict> <dict>
......
...@@ -60,9 +60,23 @@ class ForecastTimePeriodView: UIView { ...@@ -60,9 +60,23 @@ class ForecastTimePeriodView: UIView {
} }
} }
public func set(timePeriod:TimePeriod, buttonType: PeriodButtonProtocol.Type, selectedIndex:Int = 0) { public func set(timePeriod:TimePeriod, buttonType: PeriodButtonProtocol.Type) {
self.currentTimePeriod = timePeriod self.currentTimePeriod = timePeriod
rebuildButtons(buttonType: buttonType, selectedIndex: selectedIndex) rebuildButtons(buttonType: buttonType)
}
public func selectButtonAt(index:Int) {
guard let buttons = self.stackView.arrangedSubviews as? [PeriodButtonProtocol] else {
return
}
buttons.enumerated().forEach {
$1.isSelected = $0 == index
if $1.isSelected {
self.scrollView.scrollRectToVisible($1.frame, animated: true)
}
}
} }
//Private //Private
...@@ -79,7 +93,7 @@ class ForecastTimePeriodView: UIView { ...@@ -79,7 +93,7 @@ class ForecastTimePeriodView: UIView {
} }
} }
private func rebuildButtons(buttonType: PeriodButtonProtocol.Type, selectedIndex:Int) { private func rebuildButtons(buttonType: PeriodButtonProtocol.Type) {
stackView.removeAll() stackView.removeAll()
let numberOfButtons:Int let numberOfButtons:Int
...@@ -100,7 +114,7 @@ class ForecastTimePeriodView: UIView { ...@@ -100,7 +114,7 @@ class ForecastTimePeriodView: UIView {
} }
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 == selectedIndex forecastButton.isSelected = index == 0
stackView.addArrangedSubview(forecastButton) stackView.addArrangedSubview(forecastButton)
forecastButton.snp.makeConstraints { (make) in forecastButton.snp.makeConstraints { (make) in
......
...@@ -47,7 +47,8 @@ class ForecastCellFactory { ...@@ -47,7 +47,8 @@ class ForecastCellFactory {
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.delegate = self cell.delegate = self
cell.selectDayButtonAt(index: forecastViewModel.selectedDailyWeatherIndex)
if let daily = forecastViewModel.location?.daily, if let daily = forecastViewModel.location?.daily,
let hourly = forecastViewModel.location?.hourly { let hourly = forecastViewModel.location?.hourly {
cell.configure(daily: daily, hourly: hourly) cell.configure(daily: daily, hourly: hourly)
...@@ -100,6 +101,11 @@ class ForecastCellFactory { ...@@ -100,6 +101,11 @@ class ForecastCellFactory {
//MARK:- ForecastTimePeriodCell Delegate //MARK:- ForecastTimePeriodCell Delegate
extension ForecastCellFactory: ForecastTimePeriodCellDelegate { extension ForecastCellFactory: ForecastTimePeriodCellDelegate {
func timePeriodCell(cell: ForecastTimePeriodCell, didSelectButtonAt index: Int) { func timePeriodCell(cell: ForecastTimePeriodCell, didSelectButtonAt index: Int) {
guard forecastViewModel.currentTimePeriod == .daily else { return }
forecastViewModel.selectDailyWeather(at: index) forecastViewModel.selectDailyWeather(at: index)
} }
func timePeriodCell(cell: ForecastTimePeriodCell, didSelectTimePeriod timePeriod: TimePeriod) {
forecastViewModel.setTimePeriod(timePeriod: timePeriod)
}
} }
...@@ -9,6 +9,7 @@ import UIKit ...@@ -9,6 +9,7 @@ import UIKit
protocol ForecastTimePeriodCellDelegate:class { protocol ForecastTimePeriodCellDelegate:class {
func timePeriodCell(cell:ForecastTimePeriodCell, didSelectButtonAt index:Int) func timePeriodCell(cell:ForecastTimePeriodCell, didSelectButtonAt index:Int)
func timePeriodCell(cell:ForecastTimePeriodCell, didSelectTimePeriod timePeriod:TimePeriod)
} }
class ForecastTimePeriodCell: UITableViewCell { class ForecastTimePeriodCell: UITableViewCell {
...@@ -48,6 +49,10 @@ class ForecastTimePeriodCell: UITableViewCell { ...@@ -48,6 +49,10 @@ class ForecastTimePeriodCell: UITableViewCell {
} }
} }
public func selectDayButtonAt(index:Int) {
self.forecastTimePeriodView.selectButtonAt(index: index)
}
@objc private func handleSegmentDidChange() { @objc private func handleSegmentDidChange() {
guard let timePeriod = TimePeriod(rawValue: self.periodSegmentedControl.selectedSegmentIndex) else { guard let timePeriod = TimePeriod(rawValue: self.periodSegmentedControl.selectedSegmentIndex) else {
return return
...@@ -59,6 +64,8 @@ class ForecastTimePeriodCell: UITableViewCell { ...@@ -59,6 +64,8 @@ class ForecastTimePeriodCell: UITableViewCell {
case .hourly: case .hourly:
self.forecastTimePeriodView.set(timePeriod: timePeriod, buttonType: ForecastPeriodButton.self) self.forecastTimePeriodView.set(timePeriod: timePeriod, buttonType: ForecastPeriodButton.self)
} }
delegate?.timePeriodCell(cell: self, didSelectTimePeriod: timePeriod)
} }
} }
......
...@@ -7,6 +7,10 @@ ...@@ -7,6 +7,10 @@
import UIKit import UIKit
protocol DaysControlViewDelegate:class {
func didSelectButtonAt(index:Int)
}
class DaysControlView: UIView { class DaysControlView: UIView {
//Private //Private
private let scrollView = UIScrollView() private let scrollView = UIScrollView()
...@@ -14,10 +18,14 @@ class DaysControlView: UIView { ...@@ -14,10 +18,14 @@ class DaysControlView: UIView {
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)
//Public
weak var delegate:DaysControlViewDelegate?
private var statusBarHeight: CGFloat { private var statusBarHeight: CGFloat {
var statusBarHeight: CGFloat = 0 var statusBarHeight: CGFloat = 0
if #available(iOS 13.0, *) { if #available(iOS 13.0, *) {
let window = UIApplication.shared.windows.filter {$0.isKeyWindow}.first let window = UIApplication.shared.windows.filter{ $0.isKeyWindow }.first
statusBarHeight = window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0 statusBarHeight = window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
} else { } else {
statusBarHeight = UIApplication.shared.statusBarFrame.height statusBarHeight = UIApplication.shared.statusBarFrame.height
...@@ -39,10 +47,7 @@ class DaysControlView: UIView { ...@@ -39,10 +47,7 @@ class DaysControlView: UIView {
} }
public func configure(dailyWeather: [DailyWeather]) { public func configure(dailyWeather: [DailyWeather]) {
stackView.arrangedSubviews.forEach { stackView.removeAll()
stackView.removeArrangedSubview($0)
$0.removeFromSuperview()
}
for index in 0..<dailyWeather.count { for index in 0..<dailyWeather.count {
let button = DayControlButton() let button = DayControlButton()
...@@ -54,11 +59,29 @@ class DaysControlView: UIView { ...@@ -54,11 +59,29 @@ class DaysControlView: UIView {
stackView.layoutIfNeeded() stackView.layoutIfNeeded()
} }
public func selectDayAt(index:Int) {
guard let buttons = stackView.arrangedSubviews as? [DayControlButton] else {
return
}
buttons.enumerated().forEach {
$1.isSelected = $0 == index
if $1.isSelected {
scrollView.scrollRectToVisible($1.frame, animated: true)
}
}
}
@objc private func handleDayButton(button:DayControlButton) { @objc private func handleDayButton(button:DayControlButton) {
guard let buttons = stackView.arrangedSubviews as? [DayControlButton] else { return } guard let buttons = stackView.arrangedSubviews as? [DayControlButton] else { return }
buttons.forEach { buttons.enumerated().forEach {
$0.isSelected = $0 === button $1.isSelected = $1 === button
if $1.isSelected {
self.delegate?.didSelectButtonAt(index: $0)
}
} }
} }
} }
...@@ -80,7 +103,7 @@ private extension DaysControlView { ...@@ -80,7 +103,7 @@ private extension DaysControlView {
addSubview(scrollView) addSubview(scrollView)
scrollView.snp.makeConstraints { (make) in scrollView.snp.makeConstraints { (make) in
make.top.equalToSuperview().inset(statusBarHeight + 22) make.top.equalToSuperview().inset(statusBarHeight)
make.left.right.equalToSuperview() make.left.right.equalToSuperview()
make.bottom.equalToSuperview().inset(18) make.bottom.equalToSuperview().inset(18)
make.height.greaterThanOrEqualTo(50) make.height.greaterThanOrEqualTo(50)
...@@ -94,7 +117,7 @@ private extension DaysControlView { ...@@ -94,7 +117,7 @@ private extension DaysControlView {
stackView.spacing = 10 stackView.spacing = 10
stackView.clipsToBounds = false stackView.clipsToBounds = false
stackView.isLayoutMarginsRelativeArrangement = true stackView.isLayoutMarginsRelativeArrangement = true
stackView.layoutMargins = .init(top: 0, left: 10, bottom: 0, right: 10) stackView.layoutMargins = .init(top: 0, left: 6, bottom: 0, right: 6)
scrollView.addSubview(stackView) scrollView.addSubview(stackView)
stackView.snp.makeConstraints { (make) in stackView.snp.makeConstraints { (make) in
......
...@@ -36,7 +36,9 @@ class ForecastViewController: UIViewController { ...@@ -36,7 +36,9 @@ class ForecastViewController: UIViewController {
prepareNavigationBar() prepareNavigationBar()
prepareTableView() prepareTableView()
prepareDayControlsView() prepareDayControlsView()
refreshCityButton() refreshCityButton()
refreshDayButtons()
} }
private func refreshCityButton() { private func refreshCityButton() {
...@@ -44,6 +46,15 @@ class ForecastViewController: UIViewController { ...@@ -44,6 +46,15 @@ class ForecastViewController: UIViewController {
cityButton.isHidden = false cityButton.isHidden = false
} }
private func refreshDayButtons() {
if let dailyWeather = viewModel.location?.daily {
daysControlView.configure(dailyWeather: dailyWeather)
}
else {
daysControlView.alpha = 0
}
}
@objc private func handleCityButton() { @objc private func handleCityButton() {
print("Handle city button") print("Handle city button")
} }
...@@ -87,6 +98,7 @@ private extension ForecastViewController { ...@@ -87,6 +98,7 @@ private extension ForecastViewController {
func prepareDayControlsView() { func prepareDayControlsView() {
daysControlView.alpha = 0 daysControlView.alpha = 0
daysControlView.delegate = self
view.addSubview(daysControlView) view.addSubview(daysControlView)
daysControlView.snp.makeConstraints { (make) in daysControlView.snp.makeConstraints { (make) in
make.top.left.right.equalToSuperview() make.top.left.right.equalToSuperview()
...@@ -116,7 +128,8 @@ extension ForecastViewController: UITableViewDelegate { ...@@ -116,7 +128,8 @@ extension ForecastViewController: UITableViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) { func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard guard
let navVC = self.navigationController, let navVC = self.navigationController,
viewModel.location?.daily.isEmpty == false viewModel.location?.daily.isEmpty == false,
viewModel.currentTimePeriod == .daily
else { else {
return return
} }
...@@ -167,13 +180,7 @@ extension ForecastViewController: ForecastViewModelDelegate { ...@@ -167,13 +180,7 @@ extension ForecastViewController: ForecastViewModelDelegate {
func viewModelDidChange<P>(model: P) where P : ViewModelProtocol { func viewModelDidChange<P>(model: P) where P : ViewModelProtocol {
refreshCityButton() refreshCityButton()
tableView.reloadData() tableView.reloadData()
refreshDayButtons()
if let dailyWeather = viewModel.location?.daily {
daysControlView.configure(dailyWeather: dailyWeather)
}
else {
daysControlView.alpha = 0
}
} }
func selectedDailyWeatherDidChange() { func selectedDailyWeatherDidChange() {
...@@ -185,5 +192,21 @@ extension ForecastViewController: ForecastViewModelDelegate { ...@@ -185,5 +192,21 @@ extension ForecastViewController: ForecastViewModelDelegate {
} }
tableView.reloadRows(at: indexPathToReload, with: .none) tableView.reloadRows(at: indexPathToReload, with: .none)
daysControlView.selectDayAt(index: viewModel.selectedDailyWeatherIndex)
}
func selectedTimePeriodDidChange() {
guard let timePeriodCell = tableView.cellForRow(at: [0,0]) as? ForecastTimePeriodCell else {
return
}
timePeriodCell.selectDayButtonAt(index: viewModel.selectedDailyWeatherIndex)
}
}
//MARK:- DaysControlView Delegate
extension ForecastViewController: DaysControlViewDelegate {
func didSelectButtonAt(index: Int) {
viewModel.selectDailyWeather(at: index)
} }
} }
...@@ -9,6 +9,7 @@ import UIKit ...@@ -9,6 +9,7 @@ import UIKit
protocol ForecastViewModelDelegate:ViewModelDelegate { protocol ForecastViewModelDelegate:ViewModelDelegate {
func selectedDailyWeatherDidChange() func selectedDailyWeatherDidChange()
func selectedTimePeriodDidChange()
} }
class ForecastViewModel: ViewModelProtocol { class ForecastViewModel: ViewModelProtocol {
...@@ -16,6 +17,18 @@ class ForecastViewModel: ViewModelProtocol { ...@@ -16,6 +17,18 @@ class ForecastViewModel: ViewModelProtocol {
public weak var delegate:ForecastViewModelDelegate? public weak var delegate:ForecastViewModelDelegate?
public private(set) var location: Location? public private(set) var location: Location?
public private(set) var selectedDailyWeather:DailyWeather? public private(set) var selectedDailyWeather:DailyWeather?
public private(set) var currentTimePeriod = TimePeriod.daily
public var selectedDailyWeatherIndex:Int {
guard let loc = self.location else { return -1 }
for (index, day) in loc.daily.enumerated() {
if day == selectedDailyWeather {
return index
}
}
return -1
}
//Private //Private
private var locationManager: LocationManager private var locationManager: LocationManager
...@@ -47,6 +60,11 @@ class ForecastViewModel: ViewModelProtocol { ...@@ -47,6 +60,11 @@ class ForecastViewModel: ViewModelProtocol {
} }
self.delegate?.selectedDailyWeatherDidChange() self.delegate?.selectedDailyWeatherDidChange()
} }
public func setTimePeriod(timePeriod:TimePeriod) {
self.currentTimePeriod = timePeriod
self.delegate?.selectedTimePeriodDidChange()
}
} }
//MARK:- LocationManager Delegate //MARK:- LocationManager Delegate
......
...@@ -40,14 +40,14 @@ ...@@ -40,14 +40,14 @@
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>1</integer> <integer>2</integer>
</dict> </dict>
<key>SnapKit.xcscheme</key> <key>SnapKit.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>2</integer> <integer>3</integer>
</dict> </dict>
<key>XMLCoder.xcscheme_^#shared#^_</key> <key>XMLCoder.xcscheme_^#shared#^_</key>
<dict> <dict>
......
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