// // SportViewControllers.swift // HPlusFit // // Created by lemo. on 2019/7/14. // Copyright © 2019 lemo. All rights reserved. // import UIKit import RxCocoa // MARK:- 复用 fileprivate enum Resuable { static let sportCell = ReusableCell(nibName: "SportCell") } class SportViewControllers: TableViewController { /// 标题按钮 lazy var titleView: UIButton = { let btn = UIButton().then { $0.setTitleColor(kHexColor(0x2A2A2A), for: .normal) $0.setTitle(MultiLanguageKey.allSportFB.localized, for: .normal) $0.setImage(R.image.sport_history_up(), for: .normal) $0.setImage(R.image.sport_history_down(), for: .selected) $0.titleLabel?.font = SystemMediumFont(20) $0.changgeImageAndTitleEdgeInsets(type: 1, spacing: 5.0) $0.sizeToFit() } return btn }() /// 运动分类选择 lazy var sportCategoryView: SportHistoryCategoryView = { let temp = SportHistoryCategoryView(frame: view.bounds) return temp }() /// 日期选择 private lazy var dateHeaderView: DateSwitchHeaderView = { let view = DateSwitchHeaderView(frame: CGRect(x: 0, y: 0, width: kScreenW, height: kScaleHeight(103))) view.segControlValueChangeClosure = { [weak self] (type) in guard let `self` = self else { return } guard let viewModel = self.viewModel as? SportViewModels else { return } let dateStr: String = DateClass.todayString() var queryType: DataQueryType = .day if type == .week { queryType = .week }else if type == .month { queryType = .month } viewModel.loadSportData(timeStr: dateStr, queryType: queryType) } view.dateSelectedClosure = { [weak self] (selectedDateStr) in guard let `self` = self else { return } guard let viewModel = self.viewModel as? SportViewModels else { return } viewModel.loadSportData(timeStr: selectedDateStr, queryType: nil) } return view }() // 头视图 lazy var sportHeaderView: SportHeaderView = { let nib = UINib.init(nibName: "SportHeaderView", bundle: nil) let v = nib.instantiate(withOwner: nil, options: nil)[0] as! SportHeaderView return v }() let rxDataSource = RxTableViewSectionedReloadDataSource (configureCell: { (dataSource, tv, indexPath, element) in switch element { case .sportItem(let viewModel): let cell = tv.dequeue(Resuable.sportCell, for: indexPath) cell.bind(model: viewModel) return cell default: return UITableViewCell() } }, canEditRowAtIndexPath: { (_ , _) -> Bool in return true }) private lazy var nodataView: NoDataView = { let noDataView = NoDataView(frame: CGRect.zero, tip: MultiLanguageKey.noDataTipFB.localized, type: .sport) noDataView.isHidden = false noDataView.backgroundColor = kHexColor(0xffffff) return noDataView }() override func viewDidLoad() { super.viewDidLoad() //self.bindViewModel() // BluetoothService.shared.syncState // .flatMapLatest { (state) -> Observable in // switch state { // case .normal: NSLog(MultiLanguageKey.syncDataFB.localized) // case .syncing(_): self.bindViewModel() //return Observable.just("\(Int(progrss * 100))%") // default: break // } // // } } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(true) // if BluetoothService.shared.checkBleCmdEnable(isShow: false) { // BluetoothService.shared.sendSyncDeviceData() // // } super.bindViewModel() } override func makeUI() { super.makeUI() view.backgroundColor = .white view.addSubview(dateHeaderView) view.addSubview(nodataView) // titleView navigationItem.leftBarButtonItem = UIBarButtonItem(customView: titleView) // tableView tableViewStyle = .grouped tableView.rx.setDelegate(self).disposed(by: rx.disposeBag) tableView.tableHeaderView = sportHeaderView tableView.register(Resuable.sportCell) tableView.separatorStyle = .none tableView.rowHeight = kScaleHeight(80) tableView.backgroundColor = .white layoutUI() } func layoutUI() { tableView.snp.makeConstraints { (make) in make.top.equalTo(dateHeaderView.snp.bottom) make.left.right.bottom.equalToSuperview() } nodataView.snp.makeConstraints { (make) in make.edges.equalTo(tableView.snp.edges) } view.bringSubviewToFront(nodataView) } override func bindViewModel() { guard let viewModel = viewModel as? SportViewModels else { return } let dataSource = viewModel.relay.asObservable() .share(replay: 1) dataSource .bind(to: tableView.rx.items(dataSource: rxDataSource)) .disposed(by: rx.disposeBag) dataSource.subscribe(onNext: { [weak self] (sections) in // 无数据处理 let isHidden = sections.count != 0 self?.nodataView.isHidden = isHidden }) .disposed(by: rx.disposeBag) // 头部视图数据绑定 dataSource .subscribe(onNext: { [weak self] _ in self?.sportHeaderView.refreshUI(sports: viewModel.sportModelArr) }) .disposed(by: rx.disposeBag) // 运动分类数据绑定 viewModel.sportCategoryVariable.asObservable() .bind(to: sportCategoryView.tableView.rx.items(dataSource: sportCategoryView.rxDataSource)) .disposed(by: rx.disposeBag) // 运动分类高度数据绑定 viewModel.cateforyHieghtVariable.asObservable() .bind(to: sportCategoryView.rx.snpHeight()) .disposed(by: rx.disposeBag) } override func handleEvent() { super.handleEvent() titleView.rx.tap .subscribe({ [weak self] _ in guard let `self` = self else { return } // 点击展示运动分类选择 if self.titleView.isSelected { self.sportCategoryView.dimiss() }else { self.sportCategoryView.show(to: self.view) } self.titleView.isSelected = !self.titleView.isSelected // 禁用0.2秒,动画时间 self.titleView.isUserInteractionEnabled = false DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.2, execute: { self.titleView.isUserInteractionEnabled = true }) }) .disposed(by: rx.disposeBag) sportCategoryView.tableView.rx.modelSelected(SportType.self) .subscribe(onNext: { [weak self] result in guard let `self` = self else { return } guard let viewModel = self.viewModel as? SportViewModels else { return } // 标题视图更新 self.titleView.isSelected = !self.titleView.isSelected self.titleView.setTitle(result.sportTypeName.localized, for: .normal) self.titleView.changgeImageAndTitleEdgeInsets(type: 1, spacing: 5.0) // 切换运动类型 viewModel.switchSportTypeData(sportType: result) // 隐藏 self.sportCategoryView.dimiss() }) .disposed(by: rx.disposeBag) sportCategoryView.touchesBegan = { [weak self] in guard let `self` = self else { return } // 标题视图更新 self.titleView.isSelected = !self.titleView.isSelected } tableView.rx.modelSelected(HealthSectionItem.self) .subscribe(onNext: { [weak self] (item) in switch item { case .sportItem(let viewModel): let vm = SportDetailViewModels(sportModel: viewModel.sportModel) self?.navigator.show(segue: .sportDetail(viewModel: vm), sender: self) default: break } }) .disposed(by: rx.disposeBag) // tableView.rx.modelDeleted(SportModel.self) // .subscribe(onNext: { [weak self] (sportModel) in // guard let `self` = self else { return } // // 删除运动 // ShowMessage(self, "确定删除选中运动吗?", cancelText: "NO", confirmText: "YES", handle: { (result) in // if result { // self.viewModel.deleteSport(sportModel: sportModel) // } // }) // }) // .disposed(by: rx.disposeBag) } } // MARK:- UITableViewDelegate extension SportViewControllers: UITableViewDelegate { func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { return kScaleHeight(40) } func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { let view = UIView() view.backgroundColor = kHexColor(0xFFFFFF) // 时间 let _ = UILabel(frame: CGRect(x: kScaleWidth(15), y: 0, width: 200, height: kScaleHeight(40))).then { $0.text = rxDataSource[section].title $0.font = SystemRegularFont(16) $0.textColor = kHexColor(0x2A2A2A) view.addSubview($0) } // 总里程 / 次数 let items = rxDataSource.sectionModels[section].items var distance = 0 items.forEach { (item) in switch item { case .sportItem(let viewModel): distance += viewModel.sportModel.distance default: break } } let metric = UserDefaultsManager.getUserInfo()?.metricUnit ?? 0 let distanceStr = metric == 0 ? String(format: "%0.2lfkm",CGFloat(distance) / 1000.0) : String(format: "%0.2lfmiles", CGFloat(distance) / 1000.0 * 0.62137) let _ = UILabel(frame: CGRect(x: kScreenW - 200 - kScaleWidth(15), y: 0, width: 200, height: kScaleHeight(40))).then { $0.text = distanceStr + " " + "\(items.count)" + MultiLanguageKey.timeFB.localized $0.font = SystemLightFont(12) $0.textColor = kHexColor(0x2A2A2A) $0.textAlignment = .right view.addSubview($0) } return view } }