163 lines
5.7 KiB
Swift
163 lines
5.7 KiB
Swift
|
|
import Chart
|
||
|
|
|
||
|
|
protocol ElevationProfileViewProtocol: AnyObject {
|
||
|
|
var presenter: ElevationProfilePresenterProtocol? { get set }
|
||
|
|
|
||
|
|
var userInteractionEnabled: Bool { get set }
|
||
|
|
var isChartViewHidden: Bool { get set }
|
||
|
|
var isChartViewInfoHidden: Bool { get set }
|
||
|
|
var canReceiveUpdates: Bool { get }
|
||
|
|
|
||
|
|
func setChartData(_ data: ChartPresentationData)
|
||
|
|
func setActivePointDistance(_ distance: Double)
|
||
|
|
func setMyPositionDistance(_ distance: Double)
|
||
|
|
func reloadDescription()
|
||
|
|
}
|
||
|
|
|
||
|
|
final class ElevationProfileViewController: UIViewController {
|
||
|
|
|
||
|
|
private enum Constants {
|
||
|
|
static let descriptionCollectionViewHeight: CGFloat = 52
|
||
|
|
static let descriptionCollectionViewContentInsets = UIEdgeInsets(top: 20, left: 16, bottom: 4, right: 16)
|
||
|
|
static let graphViewContainerInsets = UIEdgeInsets(top: -4, left: 0, bottom: 0, right: 0)
|
||
|
|
static let chartViewInsets = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: -16)
|
||
|
|
static let chartViewVisibleHeight: CGFloat = 176
|
||
|
|
static let chartViewHiddenHeight: CGFloat = .zero
|
||
|
|
}
|
||
|
|
|
||
|
|
var presenter: ElevationProfilePresenterProtocol?
|
||
|
|
|
||
|
|
init() {
|
||
|
|
super.init(nibName: nil, bundle: nil)
|
||
|
|
}
|
||
|
|
|
||
|
|
@available(*, unavailable)
|
||
|
|
required init?(coder: NSCoder) {
|
||
|
|
fatalError("init(coder:) has not been implemented")
|
||
|
|
}
|
||
|
|
|
||
|
|
private var chartView = ChartView()
|
||
|
|
private var graphViewContainer = UIView()
|
||
|
|
private var descriptionCollectionView: UICollectionView = {
|
||
|
|
let layout = UICollectionViewFlowLayout()
|
||
|
|
layout.scrollDirection = .horizontal
|
||
|
|
layout.minimumInteritemSpacing = 0
|
||
|
|
return UICollectionView(frame: .zero, collectionViewLayout: layout)
|
||
|
|
}()
|
||
|
|
private var chartViewHeightConstraint: NSLayoutConstraint!
|
||
|
|
|
||
|
|
|
||
|
|
// MARK: - Lifecycle
|
||
|
|
|
||
|
|
override func viewDidLoad() {
|
||
|
|
super.viewDidLoad()
|
||
|
|
setupViews()
|
||
|
|
layoutViews()
|
||
|
|
presenter?.configure()
|
||
|
|
}
|
||
|
|
|
||
|
|
override func viewWillLayoutSubviews() {
|
||
|
|
super.viewWillLayoutSubviews()
|
||
|
|
descriptionCollectionView.reloadData()
|
||
|
|
}
|
||
|
|
|
||
|
|
// MARK: - Private methods
|
||
|
|
|
||
|
|
private func setupViews() {
|
||
|
|
view.setStyle(.background)
|
||
|
|
setupDescriptionCollectionView()
|
||
|
|
setupChartView()
|
||
|
|
}
|
||
|
|
|
||
|
|
private func setupChartView() {
|
||
|
|
graphViewContainer.translatesAutoresizingMaskIntoConstraints = false
|
||
|
|
chartView.translatesAutoresizingMaskIntoConstraints = false
|
||
|
|
chartView.onSelectedPointChanged = { [weak self] in
|
||
|
|
self?.presenter?.onSelectedPointChanged($0)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private func setupDescriptionCollectionView() {
|
||
|
|
descriptionCollectionView.backgroundColor = .clear
|
||
|
|
descriptionCollectionView.register(cell: ElevationProfileDescriptionCell.self)
|
||
|
|
descriptionCollectionView.dataSource = presenter
|
||
|
|
descriptionCollectionView.delegate = presenter
|
||
|
|
descriptionCollectionView.isScrollEnabled = false
|
||
|
|
descriptionCollectionView.contentInset = Constants.descriptionCollectionViewContentInsets
|
||
|
|
descriptionCollectionView.translatesAutoresizingMaskIntoConstraints = false
|
||
|
|
descriptionCollectionView.showsHorizontalScrollIndicator = false
|
||
|
|
descriptionCollectionView.showsVerticalScrollIndicator = false
|
||
|
|
}
|
||
|
|
|
||
|
|
private func layoutViews() {
|
||
|
|
view.addSubview(descriptionCollectionView)
|
||
|
|
graphViewContainer.addSubview(chartView)
|
||
|
|
view.addSubview(graphViewContainer)
|
||
|
|
|
||
|
|
chartViewHeightConstraint = chartView.heightAnchor.constraint(equalToConstant: Constants.chartViewVisibleHeight)
|
||
|
|
NSLayoutConstraint.activate([
|
||
|
|
descriptionCollectionView.topAnchor.constraint(equalTo: view.topAnchor),
|
||
|
|
descriptionCollectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||
|
|
descriptionCollectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
||
|
|
descriptionCollectionView.heightAnchor.constraint(equalToConstant: Constants.descriptionCollectionViewHeight),
|
||
|
|
descriptionCollectionView.bottomAnchor.constraint(equalTo: graphViewContainer.topAnchor, constant: Constants.graphViewContainerInsets.top),
|
||
|
|
graphViewContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||
|
|
graphViewContainer.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
||
|
|
graphViewContainer.bottomAnchor.constraint(equalTo: view.bottomAnchor),
|
||
|
|
chartView.topAnchor.constraint(equalTo: graphViewContainer.topAnchor),
|
||
|
|
chartView.leadingAnchor.constraint(equalTo: graphViewContainer.leadingAnchor, constant: Constants.chartViewInsets.left),
|
||
|
|
chartView.trailingAnchor.constraint(equalTo: graphViewContainer.trailingAnchor, constant: Constants.chartViewInsets.right),
|
||
|
|
chartView.bottomAnchor.constraint(equalTo: graphViewContainer.bottomAnchor),
|
||
|
|
chartViewHeightConstraint,
|
||
|
|
])
|
||
|
|
}
|
||
|
|
|
||
|
|
private func getPreviewHeight() -> CGFloat {
|
||
|
|
view.height - descriptionCollectionView.frame.minY
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// MARK: - ElevationProfileViewProtocol
|
||
|
|
|
||
|
|
extension ElevationProfileViewController: ElevationProfileViewProtocol {
|
||
|
|
|
||
|
|
var userInteractionEnabled: Bool {
|
||
|
|
get { chartView.isUserInteractionEnabled }
|
||
|
|
set { chartView.isUserInteractionEnabled = newValue }
|
||
|
|
}
|
||
|
|
|
||
|
|
var isChartViewHidden: Bool {
|
||
|
|
get { chartView.isHidden }
|
||
|
|
set {
|
||
|
|
chartView.isHidden = newValue
|
||
|
|
graphViewContainer.isHidden = newValue
|
||
|
|
chartViewHeightConstraint.constant = newValue ? Constants.chartViewHiddenHeight : Constants.chartViewVisibleHeight
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
var isChartViewInfoHidden: Bool {
|
||
|
|
get { chartView.isChartViewInfoHidden }
|
||
|
|
set { chartView.isChartViewInfoHidden = newValue }
|
||
|
|
}
|
||
|
|
|
||
|
|
var canReceiveUpdates: Bool {
|
||
|
|
chartView.chartData != nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func setChartData(_ data: ChartPresentationData) {
|
||
|
|
chartView.chartData = data
|
||
|
|
}
|
||
|
|
|
||
|
|
func setActivePointDistance(_ distance: Double) {
|
||
|
|
chartView.setSelectedPoint(distance)
|
||
|
|
}
|
||
|
|
|
||
|
|
func setMyPositionDistance(_ distance: Double) {
|
||
|
|
chartView.myPosition = distance
|
||
|
|
}
|
||
|
|
|
||
|
|
func reloadDescription() {
|
||
|
|
descriptionCollectionView.reloadData()
|
||
|
|
}
|
||
|
|
}
|