761 lines
24 KiB
Swift
761 lines
24 KiB
Swift
//
|
||
// GroupMemberListView.swift
|
||
// QuickLocation
|
||
//
|
||
// Created by 八条 on 2026/6/29.
|
||
//
|
||
|
||
import UIKit
|
||
import RxSwift
|
||
import RxCocoa
|
||
|
||
class GroupMemberListView: UIView {
|
||
|
||
var disposeBag = DisposeBag()
|
||
|
||
func updateArrowVisibility() {
|
||
let offsetX = collectionView.contentOffset.x
|
||
let contentW = collectionView.contentSize.width
|
||
let viewW = collectionView.bounds.width
|
||
memberArrowLeft.isHidden = offsetX <= 0
|
||
memberArrowRight.isHidden = offsetX >= contentW - viewW
|
||
}
|
||
|
||
private func setupRx() {
|
||
backBtn.rx.tap.subscribe(onNext: { _ in
|
||
AppRouter.shared.popOrDismiss()
|
||
}).disposed(by: disposeBag)
|
||
|
||
collectionView.rx.contentOffset
|
||
.subscribe(onNext: { [weak self] _ in
|
||
self?.updateArrowVisibility()
|
||
})
|
||
.disposed(by: disposeBag)
|
||
|
||
// 选中日期变化时更新月份
|
||
selectedDate.subscribe(onNext: { [weak self] date in
|
||
guard let self = self else { return }
|
||
let fmt = DateFormatter()
|
||
fmt.dateFormat = "MM月"
|
||
self.monthLab.text = fmt.string(from: date)
|
||
}).disposed(by: disposeBag)
|
||
|
||
// 往前/往后翻 7 天
|
||
datePreviousBtn.rx.tap.subscribe(onNext: { [weak self] _ in
|
||
guard let self = self else { return }
|
||
let target = self.dateCollectionView.contentOffset.x - self.dateItemWidth * CGFloat(self.daysPerPage)
|
||
self.dateCollectionView.setContentOffset(CGPoint(x: max(0, target), y: 0), animated: true)
|
||
}).disposed(by: disposeBag)
|
||
|
||
dateNextBtn.rx.tap.subscribe(onNext: { [weak self] _ in
|
||
guard let self = self else { return }
|
||
var target = self.dateCollectionView.contentOffset.x + self.dateItemWidth * CGFloat(self.daysPerPage)
|
||
let maxOffset = CGFloat(self.dateItems.count) * self.dateItemWidth - self.dateCollectionView.bounds.width
|
||
target = min(max(0, maxOffset), target)
|
||
self.dateCollectionView.setContentOffset(CGPoint(x: target, y: 0), animated: true)
|
||
}).disposed(by: disposeBag)
|
||
}
|
||
|
||
private func setupUI() {
|
||
addSubview(navBgView)
|
||
addSubview(navBarView)
|
||
navBarView.addSubview(navTitleLabel)
|
||
navBarView.addSubview(backBtn)
|
||
|
||
addSubview(memberArrowLeft)
|
||
addSubview(collectionView)
|
||
addSubview(memberArrowRight)
|
||
addSubview(reportView)
|
||
|
||
navBgView.layoutChain
|
||
.edges(excludingEdge: .bottom)
|
||
.heightToWidth(160/375)
|
||
|
||
navBarView.layoutChain
|
||
.edges(excludingEdge: .bottom)
|
||
.height(kNaviHeight)
|
||
|
||
navTitleLabel.layoutChain
|
||
.top(kStatusBarHeight + 12)
|
||
.centerY(backBtn)
|
||
.centerX()
|
||
|
||
backBtn.layoutChain
|
||
.centerY(navTitleLabel)
|
||
.left(15)
|
||
.width(24)
|
||
.height(24)
|
||
|
||
collectionView.layoutChain
|
||
.topToBottomOfView(navBarView, offset: 0)
|
||
.height(90)
|
||
.edgesHorzontal(28)
|
||
|
||
memberArrowLeft.layoutChain
|
||
.rightToLeftOfView(collectionView, offset: -8)
|
||
.height(14)
|
||
.width(5)
|
||
.centerY(collectionView)
|
||
|
||
memberArrowRight.layoutChain
|
||
.leftToRightOfView(collectionView, offset: 8)
|
||
.height(14)
|
||
.width(5)
|
||
.centerY(collectionView)
|
||
|
||
reportView.layoutChain
|
||
.topToBottomOfView(collectionView, offset: 10)
|
||
.edges(excludingEdge: .top)
|
||
}
|
||
|
||
lazy var navBgView: UIImageView = {
|
||
let iv = UIImageView()
|
||
iv.image = UIImage(named: "Common/navBar_bg_2")
|
||
iv.contentMode = .scaleAspectFill
|
||
return iv
|
||
}()
|
||
|
||
lazy var navBarView: UIView = {
|
||
let view = UIView()
|
||
view.backgroundColor = .clear
|
||
return view
|
||
}()
|
||
|
||
lazy var navTitleLabel: UILabel = {
|
||
let label = UILabel()
|
||
label.text = "圈子成员"
|
||
label.font = .systemFont(ofSize: 18, weight: .medium)
|
||
label.textColor = ThemeManager.shared.color.titleAuxColor
|
||
label.textAlignment = .center
|
||
return label
|
||
}()
|
||
|
||
lazy var backBtn: UIButton = {
|
||
let btn = UIButton(type: .custom)
|
||
btn.setImage(UIImage(named: "Common/back"), for: .normal)
|
||
btn.extendEdgeInsets = UIEdgeInsets(top: 54, left: 15, bottom: 100, right: 100)
|
||
return btn
|
||
}()
|
||
|
||
// MARK: - 成员列表
|
||
lazy var memberArrowLeft: UIImageView = {
|
||
let view = UIImageView()
|
||
view.image = UIImage(named: "GroupMemberList/member_left")
|
||
view.isHidden = true
|
||
return view
|
||
}()
|
||
|
||
lazy var memberArrowRight: UIImageView = {
|
||
let view = UIImageView()
|
||
view.image = UIImage(named: "GroupMemberList/member_right")
|
||
view.isHidden = true
|
||
return view
|
||
}()
|
||
|
||
lazy var collectionView: UICollectionView = {
|
||
let layout = UICollectionViewFlowLayout()
|
||
let cvWidth = kScreenWidth - 56
|
||
layout.itemSize = CGSize(width: 65, height: 90)
|
||
layout.minimumLineSpacing = 4
|
||
layout.scrollDirection = .horizontal
|
||
|
||
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
|
||
cv.backgroundColor = .clear
|
||
cv.showsHorizontalScrollIndicator = false
|
||
cv.register(GroupMemberListCell.self)
|
||
return cv
|
||
}()
|
||
|
||
// MARK: - 报告
|
||
lazy var reportView: UIView = {
|
||
let view = UIView()
|
||
view.backgroundColor = UIColor(hexStr: "#F5FBFF")
|
||
view.layer.cornerRadius = 20
|
||
view.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
|
||
|
||
let monthView = UIView()
|
||
monthView.backgroundColor = UIColor(hexStr: "#57C7FF")
|
||
monthView.cornerRadius = 6
|
||
monthView.addSubview(monthLab)
|
||
monthLab.layoutChain
|
||
.edgesVertical(2)
|
||
.edgesHorzontal(12)
|
||
view.addSubview(monthView)
|
||
monthView.layoutChain
|
||
.top(15)
|
||
.left(15)
|
||
|
||
let totalLab = UILabel()
|
||
totalLab.text = "本周总计里程"
|
||
totalLab.font = .systemFont(ofSize: 10, weight: .medium)
|
||
totalLab.textColor = UIColor(hexStr: "#333333")
|
||
view.addSubview(totalLab)
|
||
totalLab.layoutChain
|
||
.leftToRightOfView(monthView, offset: 21)
|
||
.centerY(monthView)
|
||
view.addSubview(mileageLab)
|
||
mileageLab.layoutChain
|
||
.leftToRightOfView(totalLab, offset: 5)
|
||
.centerY(monthView)
|
||
|
||
let highLab = UILabel()
|
||
highLab.text = "本周最高时速"
|
||
highLab.font = .systemFont(ofSize: 10, weight: .medium)
|
||
highLab.textColor = UIColor(hexStr: "#333333")
|
||
view.addSubview(highLab)
|
||
highLab.layoutChain
|
||
.leftToRightOfView(mileageLab, offset: 23)
|
||
.centerY(monthView)
|
||
view.addSubview(speedLab)
|
||
speedLab.layoutChain
|
||
.leftToRightOfView(highLab, offset: 5)
|
||
.centerY(monthView)
|
||
|
||
view.addSubview(dateView)
|
||
dateView.layoutChain
|
||
.topToBottomOfView(monthView, offset: 10)
|
||
.edgesHorzontal()
|
||
|
||
view.addSubview(scrollView)
|
||
scrollView.layoutChain
|
||
.topToBottomOfView(dateView)
|
||
.edges(excludingEdge: .top)
|
||
|
||
return view
|
||
}()
|
||
|
||
lazy var monthLab: UILabel = {
|
||
let label = UILabel()
|
||
label.text = " "
|
||
label.font = .systemFont(ofSize: 14, weight: .medium)
|
||
label.textColor = UIColor(hexStr: "#0F2846")
|
||
label.textAlignment = .center
|
||
return label
|
||
}()
|
||
|
||
/// 里程
|
||
lazy var mileageLab: UILabel = {
|
||
let label = UILabel()
|
||
label.text = "0km"
|
||
label.font = .systemFont(ofSize: 16, weight: .medium)
|
||
label.textColor = UIColor(hexStr: "#16B3FF")
|
||
return label
|
||
}()
|
||
|
||
/// 速度
|
||
lazy var speedLab: UILabel = {
|
||
let label = UILabel()
|
||
label.text = "0km/h"
|
||
label.font = .systemFont(ofSize: 16, weight: .medium)
|
||
label.textColor = UIColor(hexStr: "#16B3FF")
|
||
return label
|
||
}()
|
||
|
||
// MARK: - 日期
|
||
private var dateItems: [DateItem] = []
|
||
let selectedDate = BehaviorRelay<Date>(value: Date())
|
||
private let daysPerPage = 7
|
||
|
||
/// 当前选中的成员是否是自己
|
||
var selectedMemberIsSelf = true {
|
||
didSet { updateDateSelectability() }
|
||
}
|
||
|
||
struct DateItem {
|
||
let date: Date
|
||
let day: Int
|
||
let isToday: Bool
|
||
let isFuture: Bool
|
||
let isSelectable: Bool
|
||
}
|
||
|
||
/// 根据 VIP 和成员关系计算最大可查询天数
|
||
private var maxSelectableDays: Int {
|
||
switch AppContextManager.shared.vip {
|
||
case 1: return 0 // 非会员不可点
|
||
case 2: return selectedMemberIsSelf ? 7 : 1
|
||
case 3: return selectedMemberIsSelf ? 30 : 14
|
||
default: return 0
|
||
}
|
||
}
|
||
|
||
/// 重新设置 dateItems 的 isSelectable
|
||
private func updateDateSelectability() {
|
||
let calendar = Calendar.current
|
||
let today = Date()
|
||
let maxDays = maxSelectableDays
|
||
dateItems = dateItems.map { item in
|
||
let daysAgo = calendar.dateComponents([.day], from: item.date, to: today).day ?? 0
|
||
return DateItem(date: item.date, day: item.day, isToday: item.isToday,
|
||
isFuture: item.isFuture,
|
||
isSelectable: maxDays > 0 && !item.isFuture && daysAgo <= maxDays - 1)
|
||
}
|
||
dateCollectionView.reloadData()
|
||
}
|
||
|
||
private func generateDateItems() {
|
||
let calendar = Calendar.current
|
||
let today = Date()
|
||
// 31 天前 → 今天 → 之后 3 天 = 35 天,正好 5 页 × 7 天
|
||
let pastDays = 31
|
||
let futureDays = 3
|
||
let totalDays = pastDays + 1 + futureDays // 35
|
||
|
||
dateItems = (0..<totalDays).map { i in
|
||
let offset = i - pastDays
|
||
let date = calendar.date(byAdding: .day, value: offset, to: today) ?? today
|
||
let day = calendar.component(.day, from: date)
|
||
let isFuture = date > today
|
||
let daysAgo = calendar.dateComponents([.day], from: date, to: today).day ?? 0
|
||
return DateItem(date: date, day: day,
|
||
isToday: calendar.isDateInToday(date),
|
||
isFuture: isFuture,
|
||
isSelectable: maxSelectableDays > 0 && !isFuture && daysAgo <= maxSelectableDays - 1)
|
||
}
|
||
}
|
||
|
||
/// 日期
|
||
lazy var dateView: UIView = {
|
||
let view = UIView()
|
||
view.backgroundColor = .clear
|
||
|
||
generateDateItems()
|
||
|
||
view.addSubview(datePreviousBtn)
|
||
view.addSubview(dateNextBtn)
|
||
view.addSubview(dateCollectionView)
|
||
|
||
datePreviousBtn.layoutChain
|
||
.left(15)
|
||
.edgesVertical(10)
|
||
.width(20)
|
||
.height(20)
|
||
|
||
dateNextBtn.layoutChain
|
||
.right(15)
|
||
.centerY()
|
||
.width(20)
|
||
.height(20)
|
||
|
||
dateCollectionView.layoutChain
|
||
.leftToRightOfView(datePreviousBtn, offset: 5)
|
||
.rightToLeftOfView(dateNextBtn, offset: -5)
|
||
.edgesVertical()
|
||
|
||
// 直接翻到最后一页(第 4 页,index 28 开始),今天在第 3 位
|
||
DispatchQueue.main.async {
|
||
let page: CGFloat = 4 // 第 5 页,items 28-34
|
||
let offset = page * CGFloat(self.daysPerPage) * self.dateItemWidth
|
||
self.dateCollectionView.contentOffset.x = offset
|
||
}
|
||
|
||
return view
|
||
}()
|
||
|
||
private var dateItemWidth: CGFloat {
|
||
let available = kScreenWidth - 15 - 20 - 5 - 5 - 20 - 15
|
||
return floor(available / CGFloat(daysPerPage))
|
||
}
|
||
|
||
lazy var dateCollectionView: UICollectionView = {
|
||
let layout = UICollectionViewFlowLayout()
|
||
layout.itemSize = CGSize(width: dateItemWidth, height: 40)
|
||
layout.minimumLineSpacing = 0
|
||
layout.scrollDirection = .horizontal
|
||
layout.sectionInset = .zero
|
||
|
||
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
|
||
cv.backgroundColor = .clear
|
||
cv.showsHorizontalScrollIndicator = false
|
||
cv.isPagingEnabled = true
|
||
cv.register(DateCell.self)
|
||
cv.dataSource = self
|
||
cv.delegate = self
|
||
return cv
|
||
}()
|
||
|
||
lazy var datePreviousBtn: UIButton = {
|
||
let btn = UIButton()
|
||
btn.setImage(UIImage(named: "GroupMemberList/date_left"), for: .normal)
|
||
btn.extendEdgeInsets = UIEdgeInsets(top: 15, left: 15, bottom: 15, right: 0)
|
||
return btn
|
||
}()
|
||
|
||
lazy var dateNextBtn: UIButton = {
|
||
let btn = UIButton()
|
||
btn.setImage(UIImage(named: "GroupMemberList/date_right"), for: .normal)
|
||
btn.extendEdgeInsets = UIEdgeInsets(top: 15, left: 0, bottom: 15, right: 15)
|
||
return btn
|
||
}()
|
||
|
||
// MARK: - 驾驶分析
|
||
lazy var scrollView: UIScrollView = {
|
||
let view = UIScrollView()
|
||
view.backgroundColor = .clear
|
||
view.showsVerticalScrollIndicator = false
|
||
view.bounces = false
|
||
view.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: kSafeBottomMargin, right: 0)
|
||
|
||
let contentView = UIView()
|
||
contentView.backgroundColor = .clear
|
||
view.addSubview(contentView)
|
||
contentView.layoutChain.edges().widthToView(view)
|
||
|
||
contentView.addSubview(drivingAnalysisView)
|
||
drivingAnalysisView.layoutChain
|
||
.top(5)
|
||
.edgesHorzontal(15)
|
||
.height(249)
|
||
.bottom(20)
|
||
|
||
return view
|
||
}()
|
||
|
||
lazy var drivingAnalysisView: UIView = {
|
||
let view = UIView()
|
||
view.backgroundColor = .white
|
||
view.cornerRadius = 10
|
||
|
||
let titleBg = UIImageView(image: UIImage(named: "GroupMemberList/title_bg"))
|
||
view.addSubview(titleBg)
|
||
|
||
let titleLab = UILabel()
|
||
titleLab.text = "驾驶分析"
|
||
titleLab.font = .systemFont(ofSize: 16, weight: .medium)
|
||
view.addSubview(titleLab)
|
||
titleLab.layoutChain
|
||
.top(15)
|
||
.centerX()
|
||
|
||
titleBg.layoutChain
|
||
.centerX()
|
||
.bottomToView(titleLab, offset: 5)
|
||
|
||
view.addSubview(drivingEventCV)
|
||
drivingEventCV.layoutChain
|
||
.topToBottomOfView(titleBg, offset: 20)
|
||
.edgesHorzontal()
|
||
.bottom(20)
|
||
|
||
return view
|
||
}()
|
||
|
||
lazy var drivingEventCV: UICollectionView = {
|
||
let layout = UICollectionViewFlowLayout()
|
||
layout.itemSize = CGSize(width: 66, height: 75)
|
||
layout.minimumLineSpacing = 15
|
||
layout.scrollDirection = .vertical
|
||
layout.sectionInset = UIEdgeInsets(top: 0, left: 12, bottom: 0, right: 12)
|
||
|
||
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
|
||
cv.backgroundColor = .clear
|
||
cv.showsHorizontalScrollIndicator = false
|
||
cv.isScrollEnabled = false
|
||
cv.register(DrivingEventCell.self)
|
||
return cv
|
||
}()
|
||
|
||
override func layoutSubviews() {
|
||
super.layoutSubviews()
|
||
updateArrowVisibility()
|
||
}
|
||
|
||
override init(frame: CGRect) {
|
||
super.init(frame: .zero)
|
||
backgroundColor = .white
|
||
setupUI()
|
||
setupRx()
|
||
}
|
||
|
||
required init?(coder aDecoder: NSCoder) {
|
||
fatalError("init(coder:) has not been implemented")
|
||
}
|
||
}
|
||
|
||
// MARK: - UICollectionViewDataSource & Delegate (日期)
|
||
extension GroupMemberListView: UICollectionViewDataSource, UICollectionViewDelegate {
|
||
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||
dateItems.count
|
||
}
|
||
|
||
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||
let cell: DateCell = collectionView.dequeueReusableCell(for: indexPath)
|
||
let item = dateItems[indexPath.row]
|
||
let isSel = Calendar.current.isDate(item.date, inSameDayAs: selectedDate.value)
|
||
cell.configure(item: item, isSelected: isSel)
|
||
return cell
|
||
}
|
||
|
||
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||
guard collectionView == dateCollectionView else { return }
|
||
let item = dateItems[indexPath.row]
|
||
guard item.isSelectable else { return }
|
||
let oldDate = selectedDate.value
|
||
selectedDate.accept(item.date)
|
||
if let oldRow = dateItems.firstIndex(where: { Calendar.current.isDate($0.date, inSameDayAs: oldDate) }),
|
||
let oldCell = dateCollectionView.cellForItem(at: IndexPath(row: oldRow, section: 0)) as? DateCell {
|
||
oldCell.configure(item: dateItems[oldRow], isSelected: false)
|
||
}
|
||
if let newCell = dateCollectionView.cellForItem(at: indexPath) as? DateCell {
|
||
newCell.configure(item: item, isSelected: true)
|
||
}
|
||
}
|
||
|
||
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
|
||
guard scrollView == dateCollectionView else { return }
|
||
let targetX = targetContentOffset.pointee.x
|
||
let idx = round(targetX / dateItemWidth)
|
||
targetContentOffset.pointee.x = idx * dateItemWidth
|
||
}
|
||
}
|
||
|
||
// MARK: - DateCell
|
||
class DateCell: UICollectionViewCell {
|
||
|
||
private let bgView: UIView = {
|
||
let v = UIView()
|
||
v.backgroundColor = UIColor(hexStr: "#16B3FF")
|
||
v.cornerRadius = 11
|
||
v.isHidden = true
|
||
return v
|
||
}()
|
||
|
||
private let dayLab: UILabel = {
|
||
let l = UILabel()
|
||
l.font = .systemFont(ofSize: 14, weight: .medium)
|
||
l.textAlignment = .center
|
||
return l
|
||
}()
|
||
|
||
override init(frame: CGRect) {
|
||
super.init(frame: frame)
|
||
contentView.addSubview(bgView)
|
||
contentView.addSubview(dayLab)
|
||
bgView.layoutChain.centerX().centerY().width(36).height(22)
|
||
dayLab.layoutChain.centerX().centerY()
|
||
}
|
||
|
||
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
||
|
||
func configure(item: GroupMemberListView.DateItem, isSelected: Bool) {
|
||
dayLab.text = "\(item.day)"
|
||
let disabled = item.isFuture || !item.isSelectable
|
||
bgView.isHidden = !isSelected || disabled
|
||
dayLab.textColor = disabled ? UIColor(hexStr: "#D1D1D6")
|
||
: isSelected ? .white
|
||
: UIColor(hexStr: "#333333")
|
||
}
|
||
}
|
||
|
||
// MARK: - GroupMemberListCell
|
||
class GroupMemberListCell: UICollectionViewCell {
|
||
|
||
func configure(model: GroupMemberModel, isCurrentUser: Bool, isSelected: Bool) {
|
||
avaterImgView.image = model.userIcon
|
||
vipIcon.image = model.vipIcon
|
||
nameLab.text = model.nick_name
|
||
nameLab.textColor = UIColor(hexStr: isCurrentUser ? "#16B3FF" : "#0F2846")
|
||
selectedBgView.isHidden = !isSelected
|
||
// 会员权益
|
||
if AppContextManager.shared.vip > 1, model.is_online {
|
||
batteryInfoView.isHidden = model.battery.int == 0
|
||
// 电量 16是电池图标宽度,右边有电池造型需要减去
|
||
let batteryPercent = min(CGFloat(model.battery.int), 100)
|
||
batteryView.layoutChain.width(CGFloat(16 - 1) * batteryPercent / 100.0)
|
||
batteryLab.text = "\(model.battery)%"
|
||
}
|
||
}
|
||
|
||
private func setupSubviews() {
|
||
contentView.addSubview(selectedBgView)
|
||
contentView.addSubview(avaterImgView)
|
||
contentView.addSubview(vipIcon)
|
||
contentView.addSubview(batteryInfoView)
|
||
batteryInfoView.addSubview(cornerView)
|
||
cornerView.addSubview(batteryView)
|
||
cornerView.addSubview(batteryIcon)
|
||
cornerView.addSubview(batteryLab)
|
||
contentView.addSubview(nameLab)
|
||
|
||
setupLayout()
|
||
}
|
||
|
||
private func setupLayout() {
|
||
selectedBgView.layoutChain.edges()
|
||
|
||
avaterImgView.layoutChain
|
||
.top(11)
|
||
.edgesHorzontal(10)
|
||
.heightToWidth(1)
|
||
|
||
batteryInfoView.layoutChain
|
||
.leftToView(avaterImgView)
|
||
.rightToView(avaterImgView)
|
||
.bottomToView(avaterImgView)
|
||
.height(12)
|
||
|
||
cornerView.layoutChain.edges()
|
||
|
||
batteryIcon.layoutChain
|
||
.left(7)
|
||
.centerY()
|
||
.width(16)
|
||
.height(8)
|
||
|
||
batteryView.layoutChain
|
||
.topToView(batteryIcon)
|
||
.leftToView(batteryIcon, offset: -1)
|
||
.bottomToView(batteryIcon)
|
||
|
||
batteryLab.layoutChain
|
||
.leftToRightOfView(batteryIcon, offset: 4)
|
||
.right(5)
|
||
.centerY()
|
||
|
||
vipIcon.layoutChain
|
||
.topToView(avaterImgView, offset: -8)
|
||
.leftToView(avaterImgView, offset: -6)
|
||
.width(25)
|
||
.height(21)
|
||
|
||
nameLab.layoutChain
|
||
.topToBottomOfView(batteryInfoView, offset: 4)
|
||
.edgesHorzontal()
|
||
|
||
|
||
}
|
||
|
||
lazy var selectedBgView: UIImageView = {
|
||
let view = UIImageView(image: UIImage(named: "GroupMemberList/selected_bg"))
|
||
view.contentMode = .scaleAspectFill
|
||
view.isHidden = true
|
||
return view
|
||
}()
|
||
|
||
lazy var avaterImgView: UIImageView = {
|
||
let view = UIImageView()
|
||
view.backgroundColor = .lightGray
|
||
view.contentMode = .scaleAspectFill
|
||
view.cornerRadius = 25
|
||
return view
|
||
}()
|
||
|
||
lazy var batteryInfoView: UIView = {
|
||
let view = UIView()
|
||
view.backgroundColor = .clear
|
||
view.layer.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.1).cgColor
|
||
view.layer.shadowOffset = CGSize(width: 0, height: 2)
|
||
view.layer.shadowOpacity = 1
|
||
view.layer.shadowRadius = 6
|
||
view.isHidden = true
|
||
return view
|
||
}()
|
||
|
||
lazy var cornerView: UIView = {
|
||
let view = UIView()
|
||
view.backgroundColor = .white
|
||
view.cornerRadius = 6
|
||
return view
|
||
}()
|
||
|
||
lazy var batteryView: UIView = {
|
||
let view = UIView()
|
||
view.backgroundColor = UIColor(hexStr: "#75E582")
|
||
return view
|
||
}()
|
||
|
||
lazy var batteryIcon: UIImageView = {
|
||
let view = UIImageView()
|
||
view.backgroundColor = .clear
|
||
view.image = UIImage(named: "Home/battery")
|
||
return view
|
||
}()
|
||
|
||
lazy var batteryLab: UILabel = {
|
||
let label = UILabel()
|
||
label.textColor = UIColor(hexStr: "#D4D4D4")
|
||
label.font = .systemFont(ofSize: 6, weight: .medium)
|
||
return label
|
||
}()
|
||
|
||
lazy var vipIcon: UIImageView = {
|
||
let view = UIImageView()
|
||
return view
|
||
}()
|
||
|
||
lazy var nameLab: UILabel = {
|
||
let label = UILabel()
|
||
label.textColor = UIColor(hexStr: "#0F2846")
|
||
label.font = .systemFont(ofSize: 12, weight: .medium)
|
||
label.textAlignment = .center
|
||
return label
|
||
}()
|
||
|
||
override func awakeFromNib() {
|
||
super.awakeFromNib()
|
||
// Initialization code
|
||
}
|
||
|
||
override init(frame: CGRect) {
|
||
super.init(frame: frame)
|
||
setupSubviews()
|
||
}
|
||
|
||
required init?(coder: NSCoder) {
|
||
fatalError("init(coder:) has not been implemented")
|
||
}
|
||
}
|
||
|
||
// MARK: - DrivingEventCell
|
||
class DrivingEventCell: UICollectionViewCell {
|
||
|
||
func configure(_ item: DrivingEventItem) {
|
||
iconView.image = UIImage(named: item.iconName)
|
||
nameLab.text = "\(item.title)\n(\(item.count))"
|
||
}
|
||
|
||
private let bgView: UIView = {
|
||
let v = UIView()
|
||
v.backgroundColor = UIColor(hexStr: "#F5FBFF")
|
||
v.cornerRadius = 8
|
||
return v
|
||
}()
|
||
|
||
lazy var iconView: UIImageView = {
|
||
let view = UIImageView()
|
||
view.contentMode = .scaleAspectFill
|
||
return view
|
||
}()
|
||
|
||
lazy var nameLab: UILabel = {
|
||
let l = UILabel()
|
||
l.font = .systemFont(ofSize: 12, weight: .regular)
|
||
l.textAlignment = .center
|
||
l.numberOfLines = 0
|
||
return l
|
||
}()
|
||
|
||
override init(frame: CGRect) {
|
||
super.init(frame: frame)
|
||
contentView.addSubview(bgView)
|
||
contentView.addSubview(iconView)
|
||
contentView.addSubview(nameLab)
|
||
|
||
bgView.layoutChain
|
||
.edges(excludingEdge: .top)
|
||
.height(60)
|
||
|
||
iconView.layoutChain
|
||
.top()
|
||
.centerX()
|
||
.width(32)
|
||
.heightToWidth(1)
|
||
|
||
nameLab.layoutChain
|
||
.topToBottomOfView(iconView, offset: 8)
|
||
.edgesHorzontal()
|
||
}
|
||
|
||
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
||
}
|