You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
357 lines
12 KiB
357 lines
12 KiB
// |
|
// 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_FB.cancelFB.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_FB.confirmFB.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 = ThemeManagerFrieBoltt.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_FB.stepTipFB.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_FB.stepTipFB.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_FB.hourFB.localized],mins, [MultiLanguageKey_FB.minFB.localized]] |
|
let array: [[String]] = [hours, [MultiLanguageKey_FB.hourFB.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_FB.birthdayFB.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<UITouch>, 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_FB.heightFB.localized |
|
case .weight: |
|
titleLabel.text = MultiLanguageKey_FB.weightFB.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..<pickerView.subviews.count { |
|
let singleLine = pickerView.subviews[i] |
|
if singleLine.height <= 1 { |
|
singleLine.backgroundColor = kHexColor(0xEBEBEB) |
|
} |
|
} |
|
// 设置文字 |
|
let label = UILabel().then { |
|
let width = component == 1 ? kScaleWidth(55 * 2 + 32) : kScaleWidth(80) |
|
$0.frame = CGRect(x: 0, y: 0, width: width, height: kScaleWidth(50)) |
|
$0.font = SystemMediumFont(18) |
|
$0.text = dataSource[component][row] |
|
$0.textAlignment = component == 0 ? .right : component == 1 ? .center : .left |
|
$0.textColor = ThemeManagerFrieBoltt.commonTextColor |
|
} |
|
return label |
|
} |
|
|
|
} |
|
|
|
|