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.
358 lines
12 KiB
358 lines
12 KiB
1 year ago
|
//
|
||
|
// 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<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.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..<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 = ThemeManager.commonTextColor
|
||
|
}
|
||
|
return label
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|