// // PickerView.swift // HPlusFit // // Created by lemo. on 2019/8/1. // Copyright © 2019 lemo. All rights reserved. // import UIKit // MARK:- 常量 fileprivate struct Metric { static let backgroundColor = kHexColor(0xFFFFFF) static let cancleColor = kHexColor(0xED3131) static let confirmColor = kHexColor(0x2C7AFF) static let titleColor = kHexColor(0x888888) static let generalFont = SystemLightFont(18) } enum PikcerType: Int { case step, height, weight, birthday, duration, step1 } class PickerView: UIView { // 当前选中值 var currenValues: ((Int) -> ())? // 类型 var type: PikcerType = .height private lazy var backgroundView: UIView = { let view = UIView().then { $0.backgroundColor = .white addSubview($0) } return view }() private lazy var cancleBtn: UIButton = { let btn = UIButton().then { $0.setTitle(MultiLanguageKey.cancel.localized, for: .normal) $0.setTitleColor(Metric.cancleColor, for: .normal) $0.titleLabel?.font = Metric.generalFont backgroundView.addSubview($0) } return btn }() private lazy var comfirmBtn: UIButton = { let btn = UIButton(type: .custom).then { $0.setTitle(MultiLanguageKey.confirm.localized, for: .normal) $0.setTitleColor(Metric.confirmColor, for: .normal) $0.titleLabel?.font = Metric.generalFont backgroundView.addSubview($0) } return btn }() private lazy var titleLabel: UILabel = { let label = UILabel().then { $0.font = Metric.generalFont $0.textColor = Metric.titleColor backgroundView.addSubview($0) } return label }() private lazy var pickerView: UIPickerView = { let picker = UIPickerView().then { $0.delegate = self $0.dataSource = self backgroundView.addSubview($0) } return picker }() private lazy var datePicker: UIDatePicker = { let pick = UIDatePicker() pick.datePickerMode = .date pick.backgroundColor = .white pick.locale = Locale(identifier: "zh") pick.backgroundColor = ThemeManager.bgColor let dayTimestamp: Int64 = 86400 let seconds: Int64 = Int64(dayTimestamp * 365 * 100) pick.minimumDate = Date(timeInterval: -TimeInterval(seconds), since: Date()) if #available(iOS 13.4, *) { pick.preferredDatePickerStyle = .wheels } else { // Fallback on earlier versions } // 最大值为当前时间 pick.maximumDate = Date() backgroundView.addSubview(pick) return pick }() // 各类型数据源 private var dataSource: [[String]] = [] private lazy var steps: Array = { () -> [[String]] in var steps: [String] = [] for step in stride(from: 3000, to: 100500, by: 500) { steps.append(String(step)) } let array: [[String]] = [[], steps, [MultiLanguageKey.stepTip.localized]] return array }() private lazy var steps1: Array = { () -> [[String]] in var steps1: [String] = [] for step1 in stride(from: 5000, to: 51000, by: 1000) { steps1.append(String(step1)) } let array1: [[String]] = [[], steps1, [MultiLanguageKey.stepTip.localized]] return array1 }() private lazy var heights: Array = { () -> [[String]] in var heights: [String] = [] for height in 90...240 { heights.append(String(height)) } let array: [[String]] = [[], heights, ["cm"]] return array }() private lazy var weights: Array = { () -> [[String]] in var weights: [String] = [] for weight in 10...178 { weights.append(String(weight)) } let array: [[String]] = [[], weights, ["kg"]] return array }() private lazy var durations: Array = { () -> [[String]] in var hours: [String] = [] for hour in 1...23 { hours.append(String(hour)) } // var mins: [String] = [] // for min in 0...59 { // mins.append(String(min)) // } // let array: [[String]] = [hours, [MultiLanguageKey.hour.localized],mins, [MultiLanguageKey.min.localized]] let array: [[String]] = [hours, [MultiLanguageKey.hour.localized]] return array }() override init(frame: CGRect) { super.init(frame: frame) setUpUI() handleEvent() } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } } extension PickerView { /// 展示选择框 /// - Parameters: /// - values: 值 /// - type: 弹出类型 /// - view: 视图 func show(values: Int, type: PikcerType = .height, view: UIView) { self.type = type switch type { case .step, .height, .weight: pickerView.isHidden = false datePicker.isHidden = true switchDataSource(type: type) let intervalIndex = dataSource[1].firstIndex(of: "\(values)") ?? 0 pickerView.selectRow(intervalIndex, inComponent: 1, animated: false) case .birthday: pickerView.isHidden = true datePicker.isHidden = false let date = Date(timeIntervalSince1970: TimeInterval(values)) datePicker.setDate(date, animated: false) titleLabel.text = MultiLanguageKey.birthday.localized case .duration: pickerView.isHidden = false datePicker.isHidden = true switchDataSource(type: type) let hourIndex = values // let hourIndex = values / 60 // let minIndex = values % 60 pickerView.selectRow(hourIndex-1, inComponent: 0, animated: false) // pickerView.selectRow(minIndex, inComponent: 2, animated: false) case .step1: pickerView.isHidden = false datePicker.isHidden = true switchDataSource(type: type) let intervalIndex = dataSource[1].firstIndex(of: "\(values)") ?? 0 pickerView.selectRow(intervalIndex, inComponent: 1, animated: false) } animation(isShow: true, view: view) } func dimiss() { animation(isShow: false) } override func touchesBegan(_ touches: Set, with event: UIEvent?) { dimiss() } } extension PickerView { fileprivate func setUpUI() { backgroundColor = .clear frame = CGRect(x: 0, y: 0, width: kScreenW, height: kScreenH - kNavibarH) backgroundView.snp.makeConstraints { (make) in make.height.equalTo(kScaleHeight(252)) make.left.right.equalToSuperview() make.bottom.equalToSuperview().offset(kScaleHeight(252)) } cancleBtn.snp.makeConstraints { (make) in make.left.equalTo(kNavBarItemMargin) make.top.equalToSuperview() make.height.equalTo(kScaleHeight(50)) make.width.equalTo(60) } comfirmBtn.snp.makeConstraints { (make) in make.right.equalTo(-kNavBarItemMargin) make.top.equalToSuperview() make.height.equalTo(kScaleHeight(50)) make.width.equalTo(60) } titleLabel.snp.makeConstraints { (make) in make.top.equalTo(kScaleHeight(13)) make.height.equalTo(kScaleHeight(25)) make.centerX.equalToSuperview() } pickerView.snp.makeConstraints { (make) in make.top.equalTo(kScaleHeight(50)) make.left.right.bottom.equalToSuperview() } datePicker.snp.makeConstraints { (make) in make.top.equalTo(kScaleHeight(50)) make.left.right.bottom.equalToSuperview() } } fileprivate func handleEvent() { cancleBtn.rx.tap .subscribe(onNext: { [weak self] in self?.dimiss() }) .disposed(by: rx.disposeBag) comfirmBtn.rx.tap .subscribe(onNext: { [weak self] in var value = 0 guard let `self` = self else { return } switch self.type { case .step, .height, .weight: value = self.dataSource[1][self.pickerView.selectedRow(inComponent: 1)].integerValue case .step1: value = self.dataSource[1][self.pickerView.selectedRow(inComponent: 1)].integerValue case .birthday: value = Int(self.datePicker.date.timeIntervalSince1970) case .duration: let hour = self.dataSource[0][self.pickerView.selectedRow(inComponent: 0)].integerValue // let min = self.dataSource[2][self.pickerView.selectedRow(inComponent: 2)].integerValue // value = hour * 60 + min value = hour } if let result = self.currenValues { result(value) } self.dimiss() }) .disposed(by: rx.disposeBag) } fileprivate func animation(isShow: Bool, view: UIView? = nil) { self.layoutIfNeeded() if isShow { guard let view = view else { return } view.addSubview(self) UIView.animate(withDuration: 0.3) { self.backgroundView.snp.updateConstraints { (make) in make.bottom.equalToSuperview().offset(0) } self.layoutIfNeeded() } return }else { UIView.animate(withDuration: 0.3, animations: { self.backgroundView.snp.updateConstraints { (make) in make.bottom.equalToSuperview().offset(252) } self.layoutIfNeeded() }) { _ in self.removeFromSuperview() } } } fileprivate func switchDataSource(type: PikcerType) { // 标题 switch type { case .height: titleLabel.text = MultiLanguageKey.height.localized case .weight: titleLabel.text = MultiLanguageKey.weight.localized default: break } // 数据源 switch type { case .step: dataSource = steps case .step1: dataSource = steps1 case .height: dataSource = heights case .weight: dataSource = weights case .duration: dataSource = durations default: break } pickerView.reloadAllComponents() } } extension PickerView: UIPickerViewDelegate, UIPickerViewDataSource { func numberOfComponents(in pickerView: UIPickerView) -> Int { return dataSource.count } func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { return dataSource[component].count } func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat { return kScaleHeight(50) } func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView { // 设置分割线的颜色 for i in 0..