@bm-fe/react-native-ui-components 1.0.1 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/design/build.gradle +51 -0
- package/android/design/consumer-rules.pro +1 -0
- package/android/design/proguard-rules.pro +1 -0
- package/android/design/src/main/AndroidManifest.xml +2 -0
- package/android/design/src/main/java/com/bitmart/react/design/DataUriFetcher.kt +42 -0
- package/android/design/src/main/java/com/bitmart/react/design/DesignComponentPackage.kt +35 -0
- package/android/design/src/main/java/com/bitmart/react/design/PrimaryXLargeViewManager.kt +785 -0
- package/android/design/src/main/java/com/bitmart/react/design/TextButtonViewManager.kt +294 -0
- package/ios/DemoProject/NativeDesign/PrimaryButtonViewManager.m +25 -0
- package/ios/DemoProject/NativeDesign/PrimaryButtonViewManager.swift +321 -0
- package/ios/DemoProject/NativeDesign/TextButtonViewManager.m +21 -0
- package/ios/DemoProject/NativeDesign/TextButtonViewManager.swift +184 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/Bitmart Card.imageset/Contents.json +21 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/Bitmart Card.imageset/Property 1=Bitmart Card.svg +3 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/Contents.json +6 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/Credit Debit Card.imageset/Contents.json +21 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/Credit Debit Card.imageset/Property 1=Credit Debit Card.svg +3 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/Crypto Prepaid Card.imageset/Contents.json +21 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/Crypto Prepaid Card.imageset/Property 1=Crypto Prepaid Card.svg +3 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/Mobile Recharge.imageset/Contents.json +21 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/Mobile Recharge.imageset/Mobile Recharge.svg +3 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/P2P Trading.imageset/Contents.json +21 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/P2P Trading.imageset/Property 1=P2P Trading.svg +3 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/SEPA Deposit.imageset/Contents.json +21 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/SEPA Deposit.imageset/SEPA Deposit.svg +3 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/Third-Party Payment.imageset/Contents.json +21 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/Third-Party Payment.imageset/Property 1=Third-Party Payment.svg +3 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/Contents.json +6 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Contents.json +6 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/checkmark.imageset/Contents.json +21 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/checkmark.imageset/checkmark.pdf +0 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/close_icon.imageset/Contents.json +22 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/close_icon.imageset/close_icon@2x.png +0 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/close_icon.imageset/close_icon@3x.png +0 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/cross.imageset/Contents.json +21 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/cross.imageset/cross.pdf +0 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/progress.imageset/Contents.json +21 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/progress.imageset/progress.pdf +0 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/progress_circular.imageset/Contents.json +21 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/progress_circular.imageset/progress_circular.pdf +0 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/refresh_footer_dark.imageset/Contents.json +22 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/refresh_footer_dark.imageset/refresh_footer_dark@2x.png +0 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/refresh_footer_dark.imageset/refresh_footer_dark@3x.png +0 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/refresh_footer_light.imageset/Contents.json +22 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/refresh_footer_light.imageset/refresh_footer_light@2x.png +0 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/refresh_footer_light.imageset/refresh_footer_light@3x.png +0 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/search_icon.imageset/Contents.json +21 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/search_icon.imageset/Group 13994.svg +7 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/sheet_dark_chose.imageset/Contents.json +21 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/sheet_dark_chose.imageset/Frame.svg +3 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/sheet_list_arrow.imageset/Contents.json +22 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/sheet_list_arrow.imageset/sheet_list_arrow@2x.png +0 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/sheet_list_arrow.imageset/sheet_list_arrow@3x.png +0 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/sheet_list_cell_checkbox.imageset/Contents.json +21 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/sheet_list_cell_checkbox.imageset/Frame (1).svg +3 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/sheet_list_chose.imageset/Contents.json +21 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/sheet_list_chose.imageset/Frame.png +0 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/slider_bubble.imageset/Contents.json +22 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/slider_bubble.imageset/slider_bubble@2x.png +0 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/slider_bubble.imageset/slider_bubble@3x.png +0 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/spot_second_floor_refresh_arrow.imageset/Contents.json +21 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/spot_second_floor_refresh_arrow.imageset/spot_second_floor_refresh_arrow.svg +8 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Font/Alexandria-Medium.ttf +0 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Font/Alexandria-Regular.ttf +0 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Font/Alexandria-SemiBold.ttf +0 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Classes/BMFont/BMFont.swift +82 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Classes/BMFont/UIFontExtensions.swift +120 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Classes/Components/AlertView/BMComponentAlertController.swift +574 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Classes/Components/Buttons/BMComponentButton+Examples.swift +77 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Classes/Components/Buttons/BMComponentButton.swift +373 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Classes/Components/Buttons/BMComponentButtonConfiguration.swift +181 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Classes/Components/Popup/BMComponentPopupController.swift +312 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Classes/Components/SegmentView/BMComponentSegmentedTitleCell.swift +294 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Classes/Components/SegmentView/BMComponentSegmentedTitleDataSource.swift +49 -0
- package/ios/Modules/BMUIComponents/BMUIComponents/Classes/Components/SegmentView/BMComponentSegmentedView.swift +292 -0
- package/ios/Modules/BMUIComponents/LICENSE +19 -0
- package/ios/Modules/BMUIComponents/README.md +29 -0
- package/package.json +10 -1
- package/react-native-ui-components.podspec +52 -0
- package/react-native.config.js +16 -0
- package/src/screens/NativeButtonsScreen.tsx +0 -335
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
//
|
|
2
|
+
// BMComponentPopupController.swift
|
|
3
|
+
// Pods
|
|
4
|
+
//
|
|
5
|
+
// Created by james on 2026/1/13.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import UIKit
|
|
9
|
+
import BMTheme
|
|
10
|
+
import BMCore
|
|
11
|
+
import SnapKit
|
|
12
|
+
|
|
13
|
+
/// 从底部弹出的组件控制器
|
|
14
|
+
/// 支持自定义内容视图,可选的标题和关闭按钮
|
|
15
|
+
//public class BMComponentPopupController: UIViewController {
|
|
16
|
+
//
|
|
17
|
+
// // MARK: - Public Properties
|
|
18
|
+
//
|
|
19
|
+
// /// 是否允许点击背景关闭弹窗,默认为 true
|
|
20
|
+
// public var enableClickBackgroundToDismiss: Bool = true
|
|
21
|
+
//
|
|
22
|
+
// /// 是否显示关闭按钮,默认为 true
|
|
23
|
+
// public var showCloseButton: Bool = true
|
|
24
|
+
//
|
|
25
|
+
// /// 是否显示标题栏,默认为 true
|
|
26
|
+
// public var showTitleBar: Bool = true
|
|
27
|
+
//
|
|
28
|
+
// /// 关闭回调
|
|
29
|
+
// public var onDismiss: (() -> Void)?
|
|
30
|
+
//
|
|
31
|
+
// // MARK: - Private Properties
|
|
32
|
+
//
|
|
33
|
+
// private var presentTransitionDelegate: BMPresentTransitionDelgate?
|
|
34
|
+
// private var customContentView: UIView?
|
|
35
|
+
// private var contentHeight: CGFloat = BMSize.screenHeight * 0.6
|
|
36
|
+
// private var hasCalledDismissCallback: Bool = false
|
|
37
|
+
// private var presentTransition: BMPresentTransition?
|
|
38
|
+
// private var hasUpdatedHeight: Bool = false // 标记是否已更新过高度
|
|
39
|
+
//
|
|
40
|
+
// // MARK: - Constants
|
|
41
|
+
//
|
|
42
|
+
// /// 标题栏高度(包括顶部间距和标题与内容的间距)
|
|
43
|
+
// private var titleBarHeight: CGFloat {
|
|
44
|
+
// return showTitleBar ? (24 + 26 + 20) : 20 // 顶部间距24 + 标题栏26 + 标题和内容间距20,或者只有顶部间距20
|
|
45
|
+
// }
|
|
46
|
+
//
|
|
47
|
+
// /// 底部间距(包括底部内边距和 safeArea)
|
|
48
|
+
// private func bottomPadding() -> CGFloat {
|
|
49
|
+
// return 20 + (view.safeAreaInsets.bottom > 0 ? view.safeAreaInsets.bottom : 34) // 底部间距20 + safeArea底部间距(默认34)
|
|
50
|
+
// }
|
|
51
|
+
//
|
|
52
|
+
// /// 计算后的整体弹窗高度
|
|
53
|
+
// private func calculateControllerHeight() -> CGFloat {
|
|
54
|
+
// return contentHeight + titleBarHeight + bottomPadding()
|
|
55
|
+
// }
|
|
56
|
+
//
|
|
57
|
+
// // MARK: - Initializers
|
|
58
|
+
//
|
|
59
|
+
// /// 使用自定义视图初始化
|
|
60
|
+
// /// - Parameters:
|
|
61
|
+
// /// - title: 标题,如果为 nil 则不显示标题栏
|
|
62
|
+
// /// - contentView: 自定义内容视图(可以直接传入,不需要使用 contentBuilder)
|
|
63
|
+
// /// - height: 内容区域的高度,控制器会自动添加标题栏和底部间距的高度。默认为屏幕高度的 60%(减去标题和底部间距)
|
|
64
|
+
// /// - showCloseButton: 是否显示关闭按钮
|
|
65
|
+
// /// - enableClickBackgroundToDismiss: 是否允许点击背景关闭
|
|
66
|
+
// /// - onDismiss: 关闭回调
|
|
67
|
+
// public init(title: String? = nil,
|
|
68
|
+
// contentView: UIView,
|
|
69
|
+
// height: CGFloat? = nil,
|
|
70
|
+
// showCloseButton: Bool = true,
|
|
71
|
+
// enableClickBackgroundToDismiss: Bool = true,
|
|
72
|
+
// onDismiss: (() -> Void)? = nil) {
|
|
73
|
+
// super.init(nibName: nil, bundle: nil)
|
|
74
|
+
//
|
|
75
|
+
// self.customContentView = contentView
|
|
76
|
+
// self.showCloseButton = showCloseButton
|
|
77
|
+
// self.enableClickBackgroundToDismiss = enableClickBackgroundToDismiss
|
|
78
|
+
// self.onDismiss = onDismiss
|
|
79
|
+
// self.showTitleBar = title != nil
|
|
80
|
+
//
|
|
81
|
+
// // 估算标题栏和底部间距的高度(用于初始计算)
|
|
82
|
+
// let estimatedTitleBarHeight: CGFloat = title != nil ? (24 + 26 + 20) : 20
|
|
83
|
+
// let estimatedBottomPadding: CGFloat = 20 + BMSize.bottomSafeAreaHeight
|
|
84
|
+
//
|
|
85
|
+
// if let height = height {
|
|
86
|
+
// self.contentHeight = height
|
|
87
|
+
// } else {
|
|
88
|
+
// // 默认高度:屏幕高度的60%,但需要减去标题和底部间距
|
|
89
|
+
// let defaultTotalHeight = BMSize.screenHeight * 0.6
|
|
90
|
+
// self.contentHeight = defaultTotalHeight - estimatedTitleBarHeight - estimatedBottomPadding
|
|
91
|
+
// }
|
|
92
|
+
//
|
|
93
|
+
// // 限制最大高度:如果整体高度超过屏幕高度的80%,则限制内容高度
|
|
94
|
+
// let maxTotalHeight = BMSize.screenHeight * 0.8
|
|
95
|
+
// let estimatedTotalHeight = self.contentHeight + estimatedTitleBarHeight + estimatedBottomPadding
|
|
96
|
+
// if estimatedTotalHeight > maxTotalHeight {
|
|
97
|
+
// // 限制内容高度 = 最大总高度 - 标题栏高度 - 底部间距
|
|
98
|
+
// self.contentHeight = maxTotalHeight - estimatedTitleBarHeight - estimatedBottomPadding
|
|
99
|
+
// }
|
|
100
|
+
//
|
|
101
|
+
// if let title = title {
|
|
102
|
+
// self.titleLabel.text = title
|
|
103
|
+
// }
|
|
104
|
+
//
|
|
105
|
+
// setupPresentation()
|
|
106
|
+
// setupUI()
|
|
107
|
+
// }
|
|
108
|
+
//
|
|
109
|
+
//
|
|
110
|
+
// required init?(coder: NSCoder) {
|
|
111
|
+
// fatalError("init(coder:) has not been implemented")
|
|
112
|
+
// }
|
|
113
|
+
//
|
|
114
|
+
// deinit {
|
|
115
|
+
// debugPrint("\(type(of: self)) deinit")
|
|
116
|
+
// }
|
|
117
|
+
//
|
|
118
|
+
// // MARK: - Setup Methods
|
|
119
|
+
//
|
|
120
|
+
// private func setupPresentation() {
|
|
121
|
+
// // 使用估算值初始化,实际高度会在 viewDidLayoutSubviews 中更新
|
|
122
|
+
// let estimatedHeight = contentHeight + titleBarHeight + 20 + BMSize.bottomSafeAreaHeight // 使用估算的 safeArea 底部间距
|
|
123
|
+
// presentTransitionDelegate = BMPresentTransitionDelgate(controllerHeight: estimatedHeight)
|
|
124
|
+
// modalPresentationStyle = .custom
|
|
125
|
+
// transitioningDelegate = presentTransitionDelegate
|
|
126
|
+
// }
|
|
127
|
+
//
|
|
128
|
+
// private func setupUI() {
|
|
129
|
+
// view.backgroundColor = .clear
|
|
130
|
+
//
|
|
131
|
+
// // 添加背景按钮
|
|
132
|
+
// view.addSubview(backgroundButton)
|
|
133
|
+
// backgroundButton.snp.makeConstraints { make in
|
|
134
|
+
// make.edges.equalToSuperview()
|
|
135
|
+
// }
|
|
136
|
+
//
|
|
137
|
+
// // 添加容器视图
|
|
138
|
+
// view.addSubview(containerView)
|
|
139
|
+
// containerView.snp.makeConstraints { make in
|
|
140
|
+
// make.leading.trailing.bottom.equalToSuperview()
|
|
141
|
+
// }
|
|
142
|
+
//
|
|
143
|
+
// // 添加标题栏(如果显示)
|
|
144
|
+
// if showTitleBar {
|
|
145
|
+
// containerView.addSubview(titleContainerView)
|
|
146
|
+
// titleContainerView.addSubview(titleLabel)
|
|
147
|
+
//
|
|
148
|
+
// if showCloseButton {
|
|
149
|
+
// titleContainerView.addSubview(closeButton)
|
|
150
|
+
// }
|
|
151
|
+
//
|
|
152
|
+
// titleContainerView.snp.makeConstraints { make in
|
|
153
|
+
// make.top.equalToSuperview().offset(24)
|
|
154
|
+
// make.leading.trailing.equalToSuperview()
|
|
155
|
+
// make.height.equalTo(26)
|
|
156
|
+
// }
|
|
157
|
+
//
|
|
158
|
+
// titleLabel.snp.makeConstraints { make in
|
|
159
|
+
// make.leading.equalTo(16)
|
|
160
|
+
// make.centerY.equalToSuperview()
|
|
161
|
+
// }
|
|
162
|
+
//
|
|
163
|
+
// if showCloseButton {
|
|
164
|
+
// closeButton.snp.makeConstraints { make in
|
|
165
|
+
// make.trailing.equalTo(-16)
|
|
166
|
+
// make.centerY.equalToSuperview()
|
|
167
|
+
// make.size.equalTo(CGSize(width: 20, height: 20))
|
|
168
|
+
// }
|
|
169
|
+
// }
|
|
170
|
+
// }
|
|
171
|
+
//
|
|
172
|
+
// // 添加内容视图
|
|
173
|
+
// if let contentView = customContentView {
|
|
174
|
+
// containerView.addSubview(contentView)
|
|
175
|
+
//
|
|
176
|
+
// if showTitleBar {
|
|
177
|
+
// contentView.snp.makeConstraints { make in
|
|
178
|
+
// make.top.equalTo(titleContainerView.snp.bottom).offset(20)
|
|
179
|
+
// make.leading.trailing.equalToSuperview()
|
|
180
|
+
// make.height.equalTo(contentHeight) // 使用指定的内容高度
|
|
181
|
+
// }
|
|
182
|
+
// } else {
|
|
183
|
+
// contentView.snp.makeConstraints { make in
|
|
184
|
+
// make.top.equalToSuperview().offset(20)
|
|
185
|
+
// make.leading.trailing.equalToSuperview()
|
|
186
|
+
// make.height.equalTo(contentHeight) // 使用指定的内容高度
|
|
187
|
+
// }
|
|
188
|
+
// }
|
|
189
|
+
// }
|
|
190
|
+
//
|
|
191
|
+
// // 设置容器视图的高度约束(使用估算值,会在 viewDidLayoutSubviews 中更新)
|
|
192
|
+
// containerView.snp.makeConstraints { make in
|
|
193
|
+
// make.top.equalToSuperview()
|
|
194
|
+
// make.height.equalTo(contentHeight + titleBarHeight + 20 + BMSize.bottomSafeAreaHeight)
|
|
195
|
+
// }
|
|
196
|
+
// }
|
|
197
|
+
//
|
|
198
|
+
// // MARK: - Actions
|
|
199
|
+
//
|
|
200
|
+
// @objc private func backgroundButtonTapped() {
|
|
201
|
+
// if enableClickBackgroundToDismiss {
|
|
202
|
+
// dismissPopup()
|
|
203
|
+
// }
|
|
204
|
+
// }
|
|
205
|
+
//
|
|
206
|
+
// @objc private func closeButtonTapped() {
|
|
207
|
+
// dismissPopup()
|
|
208
|
+
// }
|
|
209
|
+
//
|
|
210
|
+
// /// 关闭弹窗
|
|
211
|
+
// public func dismissPopup() {
|
|
212
|
+
// guard !hasCalledDismissCallback else { return }
|
|
213
|
+
// hasCalledDismissCallback = true
|
|
214
|
+
// dismiss(animated: true) { [weak self] in
|
|
215
|
+
// self?.onDismiss?()
|
|
216
|
+
// }
|
|
217
|
+
// }
|
|
218
|
+
//
|
|
219
|
+
// // MARK: - Override Methods
|
|
220
|
+
//
|
|
221
|
+
// public override func viewDidLayoutSubviews() {
|
|
222
|
+
// super.viewDidLayoutSubviews()
|
|
223
|
+
// // 设置顶部圆角
|
|
224
|
+
// containerView.bmCornerRadius(corners: [.topLeft, .topRight], radius: 16)
|
|
225
|
+
//
|
|
226
|
+
// // 只在第一次布局时更新高度,避免重复更新导致崩溃
|
|
227
|
+
// guard !hasUpdatedHeight else { return }
|
|
228
|
+
//
|
|
229
|
+
// // 计算实际高度(使用实际的 safeAreaInsets)
|
|
230
|
+
// var actualHeight = calculateControllerHeight()
|
|
231
|
+
//
|
|
232
|
+
// // 再次检查最大高度限制(使用实际的 bottomPadding)
|
|
233
|
+
// let maxTotalHeight = BMSize.screenHeight * 0.8
|
|
234
|
+
// if actualHeight > maxTotalHeight {
|
|
235
|
+
// // 如果超过限制,重新计算内容高度
|
|
236
|
+
// let actualTitleBarHeight = titleBarHeight
|
|
237
|
+
// let actualBottomPadding = bottomPadding()
|
|
238
|
+
// let maxContentHeight = maxTotalHeight - actualTitleBarHeight - actualBottomPadding
|
|
239
|
+
// // 更新内容视图的高度约束
|
|
240
|
+
// if let contentView = customContentView {
|
|
241
|
+
// contentView.snp.updateConstraints { make in
|
|
242
|
+
// make.height.equalTo(maxContentHeight)
|
|
243
|
+
// }
|
|
244
|
+
// }
|
|
245
|
+
// // 更新实际高度
|
|
246
|
+
// actualHeight = maxTotalHeight
|
|
247
|
+
// // 更新 contentHeight 以便后续使用
|
|
248
|
+
// self.contentHeight = maxContentHeight
|
|
249
|
+
// }
|
|
250
|
+
//
|
|
251
|
+
// // 更新 BMPresentTransition 的高度
|
|
252
|
+
// if presentTransition == nil {
|
|
253
|
+
// // 通过 presentationController 属性获取
|
|
254
|
+
// presentTransition = presentationController as? BMPresentTransition
|
|
255
|
+
// }
|
|
256
|
+
//
|
|
257
|
+
// presentTransition?.controllerHeight = actualHeight
|
|
258
|
+
//
|
|
259
|
+
// // 更新容器视图的高度约束(使用 updateConstraints 方法)
|
|
260
|
+
// containerView.snp.updateConstraints { make in
|
|
261
|
+
// make.height.equalTo(actualHeight)
|
|
262
|
+
// }
|
|
263
|
+
//
|
|
264
|
+
// hasUpdatedHeight = true
|
|
265
|
+
// }
|
|
266
|
+
//
|
|
267
|
+
// public override func viewWillDisappear(_ animated: Bool) {
|
|
268
|
+
// super.viewWillDisappear(animated)
|
|
269
|
+
// // 处理通过背景点击或其他方式关闭的情况(如 BMPresentTransition 的 blackView 点击)
|
|
270
|
+
// if isBeingDismissed && !hasCalledDismissCallback {
|
|
271
|
+
// hasCalledDismissCallback = true
|
|
272
|
+
// onDismiss?()
|
|
273
|
+
// }
|
|
274
|
+
// }
|
|
275
|
+
//
|
|
276
|
+
// // MARK: - Lazy Properties
|
|
277
|
+
//
|
|
278
|
+
// private lazy var backgroundButton: UIButton = {
|
|
279
|
+
// let button = UIButton(type: .custom)
|
|
280
|
+
// button.backgroundColor = .clear
|
|
281
|
+
// button.addTarget(self, action: #selector(backgroundButtonTapped), for: .touchUpInside)
|
|
282
|
+
// return button
|
|
283
|
+
// }()
|
|
284
|
+
//
|
|
285
|
+
// private lazy var containerView: UIView = {
|
|
286
|
+
// let view = UIView()
|
|
287
|
+
// view.theme.backgroundColor = .bgColor
|
|
288
|
+
// return view
|
|
289
|
+
// }()
|
|
290
|
+
//
|
|
291
|
+
// private lazy var titleContainerView: UIView = {
|
|
292
|
+
// let view = UIView()
|
|
293
|
+
// view.theme.backgroundColor = .bgColor
|
|
294
|
+
// return view
|
|
295
|
+
// }()
|
|
296
|
+
//
|
|
297
|
+
// private lazy var titleLabel: UILabel = {
|
|
298
|
+
// let label = UILabel()
|
|
299
|
+
// label.font = UIFont.H6Font
|
|
300
|
+
// label.cexTheme.textColor = .primaryColor
|
|
301
|
+
// return label
|
|
302
|
+
// }()
|
|
303
|
+
//
|
|
304
|
+
// private lazy var closeButton: UIButton = {
|
|
305
|
+
// let button = UIButton(type: .custom)
|
|
306
|
+
// button.setImage(UIImage.iconFont(with: .app_icon_close, size: CGSize(width: 20, height: 20)).withRenderingMode(.alwaysTemplate), for: .normal)
|
|
307
|
+
// button.cexTheme.tintColor = .secondaryColor
|
|
308
|
+
// button.addTarget(self, action: #selector(closeButtonTapped), for: .touchUpInside)
|
|
309
|
+
// button.expandSize(edge: UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8))
|
|
310
|
+
// return button
|
|
311
|
+
// }()
|
|
312
|
+
//}
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
//
|
|
2
|
+
// BMComponentSegmentedTitleCell.swift
|
|
3
|
+
// BMComponents
|
|
4
|
+
//
|
|
5
|
+
// Created by james on 2026/1/13.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import UIKit
|
|
9
|
+
import SnapKit
|
|
10
|
+
|
|
11
|
+
//open class BMComponentSegmentedTitleCell: JXSegmentedTitleCell {
|
|
12
|
+
// // MARK: - UI Components
|
|
13
|
+
// private let iconImageView = UIImageView()
|
|
14
|
+
// private let badgeContainer = UIView()
|
|
15
|
+
// private let badgeLabel = UILabel()
|
|
16
|
+
// private let badgeDot = UIView()
|
|
17
|
+
//
|
|
18
|
+
// // MARK: - Lifecycle
|
|
19
|
+
// open override func commonInit() {
|
|
20
|
+
// super.commonInit()
|
|
21
|
+
// // 图标
|
|
22
|
+
// iconImageView.contentMode = .scaleAspectFit
|
|
23
|
+
// contentView.addSubview(iconImageView)
|
|
24
|
+
// // 徽章容器
|
|
25
|
+
// badgeContainer.isHidden = true
|
|
26
|
+
// contentView.addSubview(badgeContainer)
|
|
27
|
+
// // 文字徽章
|
|
28
|
+
// badgeLabel.textAlignment = .center
|
|
29
|
+
// badgeLabel.font = UIFont.systemFont(ofSize: 10, weight: .medium)
|
|
30
|
+
// badgeLabel.textColor = .white
|
|
31
|
+
// badgeLabel.backgroundColor = UIColor(red: 0.2, green: 0.6, blue: 1.0, alpha: 1.0)
|
|
32
|
+
// badgeLabel.layer.cornerRadius = 6 // 减小圆角,使其更紧凑
|
|
33
|
+
// badgeLabel.clipsToBounds = true
|
|
34
|
+
// badgeLabel.isHidden = true
|
|
35
|
+
// badgeContainer.addSubview(badgeLabel)
|
|
36
|
+
//
|
|
37
|
+
// // 红点徽章
|
|
38
|
+
// badgeDot.backgroundColor = .red
|
|
39
|
+
// badgeDot.clipsToBounds = true
|
|
40
|
+
// badgeDot.isHidden = true
|
|
41
|
+
// badgeContainer.addSubview(badgeDot)
|
|
42
|
+
// }
|
|
43
|
+
//
|
|
44
|
+
// open override func layoutSubviews() {
|
|
45
|
+
// // 不调用 super.layoutSubviews(),完全自定义布局
|
|
46
|
+
// guard let itemModel = itemModel as? BMComponentSegmentedTitleItemModel else {
|
|
47
|
+
// super.layoutSubviews()
|
|
48
|
+
// return
|
|
49
|
+
// }
|
|
50
|
+
//
|
|
51
|
+
// let iconSize: CGFloat = 16
|
|
52
|
+
// let iconSpacing: CGFloat = 4
|
|
53
|
+
// let badgeSpacing: CGFloat = 1 // badge 与文字/图标的间距,最小间距使其紧贴
|
|
54
|
+
// let contentCenterX = contentView.bounds.width / 2
|
|
55
|
+
// let contentCenterY = contentView.bounds.height / 2
|
|
56
|
+
//
|
|
57
|
+
// // 计算标题尺寸
|
|
58
|
+
// let titleSize = titleLabel.sizeThatFits(contentView.bounds.size)
|
|
59
|
+
// titleLabel.bounds = CGRect(x: 0, y: 0, width: titleSize.width, height: titleSize.height)
|
|
60
|
+
//
|
|
61
|
+
// // 计算 badge 尺寸
|
|
62
|
+
// let badgeInfo = calculateBadgeInfo(itemModel: itemModel)
|
|
63
|
+
//
|
|
64
|
+
// // 图标布局
|
|
65
|
+
// if let icon = itemModel.icon {
|
|
66
|
+
// iconImageView.isHidden = false
|
|
67
|
+
// iconImageView.image = icon
|
|
68
|
+
// iconImageView.tintColor = titleLabel.textColor
|
|
69
|
+
// iconImageView.frame = CGRect(x: 0, y: 0, width: iconSize, height: iconSize)
|
|
70
|
+
// switch itemModel.iconPosition {
|
|
71
|
+
// case .trailing:
|
|
72
|
+
// // 图标在文字右边:文字 | 图标 | 徽章(text badge)或 文字右上角(dot badge)
|
|
73
|
+
// layoutHorizontalWithIcon(
|
|
74
|
+
// titleSize: titleSize,
|
|
75
|
+
// iconSize: iconSize,
|
|
76
|
+
// iconSpacing: iconSpacing,
|
|
77
|
+
// badgeSpacing: badgeSpacing,
|
|
78
|
+
// badgeInfo: badgeInfo,
|
|
79
|
+
// centerX: contentCenterX,
|
|
80
|
+
// centerY: contentCenterY,
|
|
81
|
+
// itemModel: itemModel
|
|
82
|
+
// )
|
|
83
|
+
// case .top:
|
|
84
|
+
// // 图标在文字上面:图标在上,文字在下,徽章在文字右边(text)或右上角(dot)
|
|
85
|
+
// layoutVerticalWithIcon(
|
|
86
|
+
// titleSize: titleSize,
|
|
87
|
+
// iconSize: iconSize,
|
|
88
|
+
// iconSpacing: iconSpacing,
|
|
89
|
+
// badgeSpacing: badgeSpacing,
|
|
90
|
+
// badgeInfo: badgeInfo,
|
|
91
|
+
// centerX: contentCenterX,
|
|
92
|
+
// centerY: contentCenterY,
|
|
93
|
+
// itemModel: itemModel
|
|
94
|
+
// )
|
|
95
|
+
// }
|
|
96
|
+
// } else {
|
|
97
|
+
// iconImageView.isHidden = true
|
|
98
|
+
// // 没有图标时,只有文字和徽章
|
|
99
|
+
// layoutHorizontalWithoutIcon(
|
|
100
|
+
// titleSize: titleSize,
|
|
101
|
+
// badgeSpacing: badgeSpacing,
|
|
102
|
+
// badgeInfo: badgeInfo,
|
|
103
|
+
// centerX: contentCenterX,
|
|
104
|
+
// centerY: contentCenterY,
|
|
105
|
+
// itemModel: itemModel
|
|
106
|
+
// )
|
|
107
|
+
// }
|
|
108
|
+
//
|
|
109
|
+
// // 更新 maskTitleLabel 位置(用于遮罩效果)
|
|
110
|
+
// maskTitleLabel.bounds = titleLabel.bounds
|
|
111
|
+
// maskTitleLabel.center = titleLabel.center
|
|
112
|
+
// }
|
|
113
|
+
//
|
|
114
|
+
// private func layoutHorizontalWithIcon(
|
|
115
|
+
// titleSize: CGSize,
|
|
116
|
+
// iconSize: CGFloat,
|
|
117
|
+
// iconSpacing: CGFloat,
|
|
118
|
+
// badgeSpacing: CGFloat,
|
|
119
|
+
// badgeInfo: (width: CGFloat, height: CGFloat, isText: Bool),
|
|
120
|
+
// centerX: CGFloat,
|
|
121
|
+
// centerY: CGFloat,
|
|
122
|
+
// itemModel: BMComponentSegmentedTitleItemModel
|
|
123
|
+
// ) {
|
|
124
|
+
// // 计算总宽度(不包括 dot badge,因为它在右上角)
|
|
125
|
+
// var totalWidth = titleSize.width + iconSize + iconSpacing
|
|
126
|
+
// if badgeInfo.isText {
|
|
127
|
+
// totalWidth += badgeInfo.width + badgeSpacing
|
|
128
|
+
// }
|
|
129
|
+
//
|
|
130
|
+
// var currentX = centerX - totalWidth / 2
|
|
131
|
+
//
|
|
132
|
+
// // 标题
|
|
133
|
+
// titleLabel.center = CGPoint(x: currentX + titleSize.width / 2, y: centerY)
|
|
134
|
+
// currentX += titleSize.width + iconSpacing
|
|
135
|
+
//
|
|
136
|
+
// // 图标
|
|
137
|
+
// iconImageView.center = CGPoint(x: currentX + iconSize / 2, y: centerY)
|
|
138
|
+
// currentX += iconSize
|
|
139
|
+
//
|
|
140
|
+
// // 徽章
|
|
141
|
+
// if badgeInfo.isText {
|
|
142
|
+
// // text badge 紧接在图标后面
|
|
143
|
+
// currentX += badgeSpacing
|
|
144
|
+
// layoutTextBadge(at: currentX + badgeInfo.width / 2, centerY: centerY, itemModel: itemModel, width: badgeInfo.width, height: badgeInfo.height)
|
|
145
|
+
// } else if itemModel.badge != nil {
|
|
146
|
+
// // dot badge 在文字右上角
|
|
147
|
+
// let textRightX = titleLabel.center.x + titleSize.width / 2
|
|
148
|
+
// let textTopY = titleLabel.center.y - titleSize.height / 2
|
|
149
|
+
// layoutDotBadge(at: textRightX, topY: textTopY, itemModel: itemModel, size: badgeInfo.width)
|
|
150
|
+
// }
|
|
151
|
+
// }
|
|
152
|
+
//
|
|
153
|
+
// private func layoutVerticalWithIcon(
|
|
154
|
+
// titleSize: CGSize,
|
|
155
|
+
// iconSize: CGFloat,
|
|
156
|
+
// iconSpacing: CGFloat,
|
|
157
|
+
// badgeSpacing: CGFloat,
|
|
158
|
+
// badgeInfo: (width: CGFloat, height: CGFloat, isText: Bool),
|
|
159
|
+
// centerX: CGFloat,
|
|
160
|
+
// centerY: CGFloat,
|
|
161
|
+
// itemModel: BMComponentSegmentedTitleItemModel
|
|
162
|
+
// ) {
|
|
163
|
+
// let totalHeight = iconSize + iconSpacing + titleSize.height
|
|
164
|
+
// let startY = centerY - totalHeight / 2
|
|
165
|
+
//
|
|
166
|
+
// // 图标(居中)
|
|
167
|
+
// iconImageView.center = CGPoint(x: centerX, y: startY + iconSize / 2)
|
|
168
|
+
//
|
|
169
|
+
// // 标题(在图标下方)
|
|
170
|
+
// titleLabel.center = CGPoint(x: centerX, y: startY + iconSize + iconSpacing + titleSize.height / 2)
|
|
171
|
+
//
|
|
172
|
+
// // 徽章
|
|
173
|
+
// if badgeInfo.isText {
|
|
174
|
+
// // text badge 在文字右边
|
|
175
|
+
// let badgeX = centerX + titleSize.width / 2 + badgeSpacing
|
|
176
|
+
// layoutTextBadge(at: badgeX + badgeInfo.width / 2, centerY: titleLabel.center.y, itemModel: itemModel, width: badgeInfo.width, height: badgeInfo.height)
|
|
177
|
+
// } else if itemModel.badge != nil {
|
|
178
|
+
// // dot badge 在文字右上角
|
|
179
|
+
// let textRightX = titleLabel.center.x + titleSize.width / 2
|
|
180
|
+
// let textTopY = titleLabel.center.y - titleSize.height / 2
|
|
181
|
+
// layoutDotBadge(at: textRightX, topY: textTopY, itemModel: itemModel, size: badgeInfo.width)
|
|
182
|
+
// }
|
|
183
|
+
// }
|
|
184
|
+
//
|
|
185
|
+
// private func layoutHorizontalWithoutIcon(
|
|
186
|
+
// titleSize: CGSize,
|
|
187
|
+
// badgeSpacing: CGFloat,
|
|
188
|
+
// badgeInfo: (width: CGFloat, height: CGFloat, isText: Bool),
|
|
189
|
+
// centerX: CGFloat,
|
|
190
|
+
// centerY: CGFloat,
|
|
191
|
+
// itemModel: BMComponentSegmentedTitleItemModel) {
|
|
192
|
+
// // 计算总宽度(不包括 dot badge)
|
|
193
|
+
// var totalWidth = titleSize.width
|
|
194
|
+
// if badgeInfo.isText {
|
|
195
|
+
// totalWidth += badgeInfo.width + badgeSpacing
|
|
196
|
+
// }
|
|
197
|
+
//
|
|
198
|
+
// var currentX = centerX - totalWidth / 2
|
|
199
|
+
//
|
|
200
|
+
// // 标题
|
|
201
|
+
// titleLabel.center = CGPoint(x: currentX + titleSize.width / 2, y: centerY)
|
|
202
|
+
// currentX += titleSize.width
|
|
203
|
+
//
|
|
204
|
+
// // 徽章
|
|
205
|
+
// if badgeInfo.isText {
|
|
206
|
+
// // text badge 紧接在文字后面
|
|
207
|
+
// currentX += badgeSpacing
|
|
208
|
+
// layoutTextBadge(at: currentX + badgeInfo.width / 2, centerY: centerY, itemModel: itemModel, width: badgeInfo.width, height: badgeInfo.height)
|
|
209
|
+
// } else if itemModel.badge != nil {
|
|
210
|
+
// // dot badge 在文字右上角
|
|
211
|
+
// let textRightX = titleLabel.center.x + titleSize.width / 2
|
|
212
|
+
// let textTopY = titleLabel.center.y - titleSize.height / 2
|
|
213
|
+
// layoutDotBadge(at: textRightX, topY: textTopY, itemModel: itemModel, size: badgeInfo.width)
|
|
214
|
+
// }
|
|
215
|
+
// }
|
|
216
|
+
//
|
|
217
|
+
// private func calculateBadgeInfo(itemModel: BMComponentSegmentedTitleItemModel) -> (width: CGFloat, height: CGFloat, isText: Bool) {
|
|
218
|
+
// guard let badge = itemModel.badge else {
|
|
219
|
+
// return (0, 0, false)
|
|
220
|
+
// }
|
|
221
|
+
//
|
|
222
|
+
// switch badge {
|
|
223
|
+
// case .text(let text, _):
|
|
224
|
+
// let tempLabel = UILabel()
|
|
225
|
+
// tempLabel.text = text
|
|
226
|
+
// tempLabel.font = UIFont.systemFont(ofSize: 10, weight: .medium)
|
|
227
|
+
// let size = tempLabel.sizeThatFits(CGSize(width: 100, height: 14))
|
|
228
|
+
// // 减小内边距,使 badge 更紧凑:左右各3pt,总高度14pt
|
|
229
|
+
// return (max(size.width + 6, 16), 14, true)
|
|
230
|
+
// case .dot(_, let size):
|
|
231
|
+
// return (max(size, 8), max(size, 8), false)
|
|
232
|
+
// }
|
|
233
|
+
// }
|
|
234
|
+
//
|
|
235
|
+
// private func layoutTextBadge(at centerX: CGFloat, centerY: CGFloat, itemModel: BMComponentSegmentedTitleItemModel, width: CGFloat, height: CGFloat) {
|
|
236
|
+
// guard case .text(let text, let bgColor) = itemModel.badge else {
|
|
237
|
+
// badgeContainer.isHidden = true
|
|
238
|
+
// return
|
|
239
|
+
// }
|
|
240
|
+
//
|
|
241
|
+
// badgeContainer.isHidden = false
|
|
242
|
+
// badgeLabel.isHidden = false
|
|
243
|
+
// badgeDot.isHidden = true
|
|
244
|
+
//
|
|
245
|
+
// badgeLabel.text = text
|
|
246
|
+
// badgeLabel.backgroundColor = bgColor
|
|
247
|
+
// badgeLabel.layer.cornerRadius = 6 // 与初始化时保持一致
|
|
248
|
+
// badgeLabel.clipsToBounds = true
|
|
249
|
+
//
|
|
250
|
+
// badgeLabel.frame = CGRect(x: 0, y: 0, width: width, height: height)
|
|
251
|
+
// // text badge 与文字垂直居中对齐,稍微向上偏移使其看起来更自然
|
|
252
|
+
// badgeLabel.center = CGPoint(x: centerX, y: centerY - 1)
|
|
253
|
+
// badgeContainer.frame = badgeLabel.frame
|
|
254
|
+
// }
|
|
255
|
+
//
|
|
256
|
+
// private func layoutDotBadge(at rightX: CGFloat, topY: CGFloat, itemModel: BMComponentSegmentedTitleItemModel, size: CGFloat) {
|
|
257
|
+
// guard case .dot(let color, _) = itemModel.badge else {
|
|
258
|
+
// badgeContainer.isHidden = true
|
|
259
|
+
// return
|
|
260
|
+
// }
|
|
261
|
+
//
|
|
262
|
+
// badgeContainer.isHidden = false
|
|
263
|
+
// badgeLabel.isHidden = true
|
|
264
|
+
// badgeDot.isHidden = false
|
|
265
|
+
//
|
|
266
|
+
// badgeDot.backgroundColor = color
|
|
267
|
+
// badgeDot.clipsToBounds = true
|
|
268
|
+
// badgeDot.layer.cornerRadius = size / 2
|
|
269
|
+
//
|
|
270
|
+
// // dot 在文字右上角,位置更靠近文字
|
|
271
|
+
// // 计算位置:文字右边缘稍微向左,文字顶部稍微向下
|
|
272
|
+
// let offsetX: CGFloat = -size / 3 // 向左偏移,使 dot 部分覆盖文字右边缘
|
|
273
|
+
// let offsetY: CGFloat = size / 3 // 向下偏移,使 dot 在文字顶部附近
|
|
274
|
+
//
|
|
275
|
+
// badgeDot.frame = CGRect(x: 0, y: 0, width: size, height: size)
|
|
276
|
+
// badgeDot.center = CGPoint(x: rightX + offsetX, y: topY + offsetY)
|
|
277
|
+
// badgeContainer.frame = badgeDot.frame
|
|
278
|
+
// }
|
|
279
|
+
//
|
|
280
|
+
// open override func reloadData(itemModel: JXSegmentedBaseItemModel, selectedType: JXSegmentedViewItemSelectedType) {
|
|
281
|
+
// super.reloadData(itemModel: itemModel, selectedType: selectedType)
|
|
282
|
+
//
|
|
283
|
+
// guard let myItemModel = itemModel as? BMComponentSegmentedTitleItemModel else {
|
|
284
|
+
// return
|
|
285
|
+
// }
|
|
286
|
+
//
|
|
287
|
+
// // 更新图标颜色以匹配文字颜色
|
|
288
|
+
// if let icon = myItemModel.icon {
|
|
289
|
+
// iconImageView.image = icon.withTintColor(titleLabel.textColor ?? .black)
|
|
290
|
+
// }
|
|
291
|
+
//
|
|
292
|
+
// setNeedsLayout()
|
|
293
|
+
// }
|
|
294
|
+
//}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
//
|
|
2
|
+
// BMComponentSegmentedTitleDataSource.swift
|
|
3
|
+
// BMComponents
|
|
4
|
+
//
|
|
5
|
+
// Created by james on 2026/1/13.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import UIKit
|
|
9
|
+
|
|
10
|
+
// MARK: - Item Model
|
|
11
|
+
//open class BMComponentSegmentedTitleItemModel: JXSegmentedTitleItemModel {
|
|
12
|
+
// open var icon: UIImage?
|
|
13
|
+
// open var badge: BMComponentSegmentedBadge?
|
|
14
|
+
// open var iconPosition: BMComponentSegmentedIconPosition = .trailing
|
|
15
|
+
//}
|
|
16
|
+
//
|
|
17
|
+
//// MARK: - Data Source
|
|
18
|
+
//open class BMComponentSegmentedTitleDataSource: JXSegmentedTitleDataSource {
|
|
19
|
+
// /// 图标数组(可选,与 titles 数量一致)
|
|
20
|
+
// open var icons: [UIImage?]?
|
|
21
|
+
// /// 图标位置数组(可选,与 titles 数量一致)
|
|
22
|
+
// open var iconPositions: [BMComponentSegmentedIconPosition]?
|
|
23
|
+
// /// 徽章数组(可选,与 titles 数量一致)
|
|
24
|
+
// open var badges: [BMComponentSegmentedBadge?]?
|
|
25
|
+
//
|
|
26
|
+
// open override func preferredItemModelInstance() -> JXSegmentedBaseItemModel {
|
|
27
|
+
// return BMComponentSegmentedTitleItemModel()
|
|
28
|
+
// }
|
|
29
|
+
//
|
|
30
|
+
// open override func preferredRefreshItemModel(_ itemModel: JXSegmentedBaseItemModel, at index: Int, selectedIndex: Int) {
|
|
31
|
+
// super.preferredRefreshItemModel(itemModel, at: index, selectedIndex: selectedIndex)
|
|
32
|
+
// guard let myItemModel = itemModel as? BMComponentSegmentedTitleItemModel else {
|
|
33
|
+
// return
|
|
34
|
+
// }
|
|
35
|
+
// myItemModel.icon = icons?[index]
|
|
36
|
+
// myItemModel.iconPosition = iconPositions?[index] ?? .trailing
|
|
37
|
+
// myItemModel.badge = badges?[index]
|
|
38
|
+
// }
|
|
39
|
+
//
|
|
40
|
+
// // MARK: - JXSegmentedViewDataSource
|
|
41
|
+
// open override func registerCellClass(in segmentedView: JXSegmentedView) {
|
|
42
|
+
// segmentedView.collectionView.register(BMComponentSegmentedTitleCell.self, forCellWithReuseIdentifier: "cell")
|
|
43
|
+
// }
|
|
44
|
+
//
|
|
45
|
+
// open override func segmentedView(_ segmentedView: JXSegmentedView, cellForItemAt index: Int) -> JXSegmentedBaseCell {
|
|
46
|
+
// let cell = segmentedView.dequeueReusableCell(withReuseIdentifier: "cell", at: index)
|
|
47
|
+
// return cell
|
|
48
|
+
// }
|
|
49
|
+
//}
|