99 lines
2.8 KiB
Swift
99 lines
2.8 KiB
Swift
import UIKit
|
|
import React
|
|
|
|
@objc(SegmentedControlView)
|
|
final class SegmentedControlView: UIView {
|
|
|
|
private let segmentedControl = UISegmentedControl()
|
|
|
|
// MARK: - Lifecycle
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
setup()
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
super.init(coder: coder)
|
|
setup()
|
|
}
|
|
|
|
private func setup() {
|
|
segmentedControl.addTarget(self, action: #selector(handleValueChanged(_:)), for: .valueChanged)
|
|
addSubview(segmentedControl)
|
|
segmentedControl.translatesAutoresizingMaskIntoConstraints = false
|
|
NSLayoutConstraint.activate([
|
|
segmentedControl.leadingAnchor.constraint(equalTo: leadingAnchor),
|
|
segmentedControl.trailingAnchor.constraint(equalTo: trailingAnchor),
|
|
segmentedControl.topAnchor.constraint(equalTo: topAnchor),
|
|
segmentedControl.bottomAnchor.constraint(equalTo: bottomAnchor),
|
|
])
|
|
}
|
|
|
|
// MARK: - Prop setters
|
|
|
|
@objc var values: NSArray = [] {
|
|
didSet { rebuildSegments() }
|
|
}
|
|
|
|
@objc var selectedIndex: Int = 0 {
|
|
didSet {
|
|
guard segmentedControl.numberOfSegments > 0 else { return }
|
|
let clamped = min(max(selectedIndex, 0), segmentedControl.numberOfSegments - 1)
|
|
if segmentedControl.selectedSegmentIndex != clamped {
|
|
segmentedControl.selectedSegmentIndex = clamped
|
|
}
|
|
}
|
|
}
|
|
|
|
@objc var enabled: Bool = true {
|
|
didSet { segmentedControl.isEnabled = enabled }
|
|
}
|
|
|
|
@objc var momentary: Bool = false {
|
|
didSet { segmentedControl.isMomentary = momentary }
|
|
}
|
|
|
|
@objc var textColor: UIColor? {
|
|
didSet { applyTextAttributes() }
|
|
}
|
|
|
|
@objc var onChange: RCTBubblingEventBlock?
|
|
|
|
override var tintColor: UIColor! {
|
|
didSet { segmentedControl.selectedSegmentTintColor = tintColor }
|
|
}
|
|
|
|
override var backgroundColor: UIColor? {
|
|
didSet { segmentedControl.backgroundColor = backgroundColor }
|
|
}
|
|
|
|
// MARK: - Private helpers
|
|
|
|
private func rebuildSegments() {
|
|
let titles = values as? [String] ?? []
|
|
segmentedControl.removeAllSegments()
|
|
for (i, title) in titles.enumerated() {
|
|
segmentedControl.insertSegment(withTitle: title, at: i, animated: false)
|
|
}
|
|
guard !titles.isEmpty else { return }
|
|
let clamped = min(max(selectedIndex, 0), titles.count - 1)
|
|
segmentedControl.selectedSegmentIndex = clamped
|
|
}
|
|
|
|
private func applyTextAttributes() {
|
|
if let color = textColor {
|
|
segmentedControl.setTitleTextAttributes([.foregroundColor: color], for: .normal)
|
|
segmentedControl.setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)
|
|
} else {
|
|
segmentedControl.setTitleTextAttributes(nil, for: .normal)
|
|
segmentedControl.setTitleTextAttributes(nil, for: .selected)
|
|
}
|
|
}
|
|
|
|
@objc private func handleValueChanged(_ sender: UISegmentedControl) {
|
|
onChange?(["selectedIndex": sender.selectedSegmentIndex])
|
|
}
|
|
}
|
|
|