Skip to content
This repository was archived by the owner on Jun 17, 2023. It is now read-only.

Commit c3f2f72

Browse files
author
Amir Khorsandi
committed
Add optional support for slider values,
1 parent eff5252 commit c3f2f72

File tree

5 files changed

+220
-164
lines changed

5 files changed

+220
-164
lines changed

Samples/PagingLayoutSamples/Modules/LayoutDesigner/LayoutDesignerViewModel.swift

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -54,22 +54,22 @@ class LayoutDesignerViewModel {
5454

5555
optionViewModels = [
5656
.init(title: "Min scale", kind: .singleSlider(current: options.minScale) { n in
57-
update { $0.minScale = n }
57+
update { $0.minScale = n! }
5858
}),
5959
.init(title: "Max scale", kind: .singleSlider(current: options.maxScale) { n in
60-
update { $0.maxScale = n }
60+
update { $0.maxScale = n! }
6161
}),
6262
.init(title: "Scale ratio", kind: .singleSlider(current: options.scaleRatio) { n in
63-
update { $0.scaleRatio = n }
63+
update { $0.scaleRatio = n! }
6464
}),
6565
.init(title: "Translation ratio", kind: .doubleSlider(current: options.translationRatio.pair) { n in
66-
update { $0.translationRatio = .by(pair: n) }
66+
update { $0.translationRatio = .by(pair: n!) }
6767
}),
68-
.init(title: "Min translation ratio", kind: .doubleSlider(current: options.minTranslationRatio?.pair) { n in
69-
update { $0.minTranslationRatio = .by(pair: n) }
68+
.init(title: "Min translation ratio", kind: .doubleSlider(current: options.minTranslationRatio?.pair, optional: true) { n in
69+
update { $0.minTranslationRatio = n.map { .by(pair: $0) } }
7070
}),
71-
.init(title: "Max translation ratio", kind: .doubleSlider(current: options.maxTranslationRatio?.pair) { n in
72-
update { $0.maxTranslationRatio = .by(pair: n) }
71+
.init(title: "Max translation ratio", kind: .doubleSlider(current: options.maxTranslationRatio?.pair, optional: true) { n in
72+
update { $0.maxTranslationRatio = n.map { .by(pair: $0) } }
7373
}),
7474
.init(title: "Keep vertical spacing equal", kind: .toggleSwitch(current: options.keepVerticalSpacingEqual) { n in
7575
update { $0.keepVerticalSpacingEqual = n }
@@ -89,55 +89,55 @@ class LayoutDesignerViewModel {
8989

9090
optionViewModels = [
9191
.init(title: "Scale factor", kind: .singleSlider(current: options.scaleFactor) { n in
92-
update { $0.scaleFactor = n }
92+
update { $0.scaleFactor = n! }
9393
}),
94-
.init(title: "Min scale", kind: .singleSlider(current: options.minScale) { n in
94+
.init(title: "Min scale", kind: .singleSlider(current: options.minScale, optional: true) { n in
9595
update { $0.minScale = n }
9696
}),
97-
.init(title: "Max scale", kind: .singleSlider(current: options.maxScale) { n in
97+
.init(title: "Max scale", kind: .singleSlider(current: options.maxScale, optional: true) { n in
9898
update { $0.maxScale = n }
9999
}),
100100
.init(title: "Spacing factor", kind: .singleSlider(current: options.spacingFactor) { n in
101-
update { $0.spacingFactor = n }
101+
update { $0.spacingFactor = n! }
102102
}),
103-
.init(title: "Max spacing", kind: .singleSlider(current: options.maxSpacing) { n in
103+
.init(title: "Max spacing", kind: .singleSlider(current: options.maxSpacing, optional: true) { n in
104104
update { $0.maxSpacing = n }
105105
}),
106106
.init(title: "Alpha factor", kind: .singleSlider(current: options.alphaFactor) { n in
107-
update { $0.alphaFactor = n }
107+
update { $0.alphaFactor = n! }
108108
}),
109109
.init(title: "Bottom stack alpha speed factor", kind: .singleSlider(current: options.bottomStackAlphaSpeedFactor) { n in
110-
update { $0.bottomStackAlphaSpeedFactor = n }
110+
update { $0.bottomStackAlphaSpeedFactor = n! }
111111
}),
112112
.init(title: "Top stack alpha speed factor", kind: .singleSlider(current: options.topStackAlphaSpeedFactor) { n in
113-
update { $0.topStackAlphaSpeedFactor = n }
113+
update { $0.topStackAlphaSpeedFactor = n! }
114114
}),
115115
.init(title: "Perspective ratio", kind: .singleSlider(current: options.perspectiveRatio) { n in
116-
update { $0.perspectiveRatio = n }
116+
update { $0.perspectiveRatio = n! }
117117
}),
118118
.init(title: "Shadow enabled", kind: .toggleSwitch(current: options.shadowEnabled) { n in
119119
update { $0.shadowEnabled = n }
120120
}),
121121
.init(title: "Shadow opacity", kind: .singleSlider(current: CGFloat(options.shadowOpacity)) { n in
122-
update { $0.shadowOpacity = Float(n) }
122+
update { $0.shadowOpacity = Float(n!) }
123123
}),
124124
.init(title: "Shadow offset", kind: .doubleSlider(current: options.shadowOffset.pair) { n in
125-
update { $0.shadowOffset = .by(pair: n) }
125+
update { $0.shadowOffset = .by(pair: n!) }
126126
}),
127127
.init(title: "Shadow radius", kind: .singleSlider(current: options.shadowRadius) { n in
128-
update { $0.shadowRadius = n }
128+
update { $0.shadowRadius = n! }
129129
}),
130130
.init(title: "Rotate angel", kind: .singleSlider(current: options.stackRotateAngel) { n in
131-
update { $0.stackRotateAngel = n }
131+
update { $0.stackRotateAngel = n! }
132132
}),
133133
.init(title: "Pop angle", kind: .singleSlider(current: options.popAngle) { n in
134-
update { $0.popAngle = n }
134+
update { $0.popAngle = n! }
135135
}),
136136
.init(title: "Pop offset ratio", kind: .doubleSlider(current: options.popOffsetRatio.pair) { n in
137-
update { $0.popOffsetRatio = .by(pair: n) }
137+
update { $0.popOffsetRatio = .by(pair: n!) }
138138
}),
139139
.init(title: "Stack position", kind: .doubleSlider(current: options.stackPosition.pair) { n in
140-
update { $0.stackPosition = .by(pair: n) }
140+
update { $0.stackPosition = .by(pair: n!) }
141141
}),
142142
.init(title: "Reverse", kind: .toggleSwitch(current: options.reverse) { n in
143143
update { $0.reverse = n }
@@ -146,7 +146,7 @@ class LayoutDesignerViewModel {
146146
update { $0.blurEffectEnabled = n }
147147
}),
148148
.init(title: "Max blur radius", kind: .singleSlider(current: options.maxBlurEffectRadius) { n in
149-
update { $0.maxBlurEffectRadius = n }
149+
update { $0.maxBlurEffectRadius = n! }
150150
}),
151151
.init(title: "Blur effect style", kind: .segmented(options: UIBlurEffect.Style.all.map(\.name), current: options.blurEffectStyle.name) { n in
152152
update { $0.blurEffectStyle = .by(name: n)! }
@@ -159,19 +159,19 @@ class LayoutDesignerViewModel {
159159
}
160160
optionViewModels = [
161161
.init(title: "Piece size ratio", kind: .doubleSlider(current: options.pieceSizeRatio.pair) { n in
162-
update { $0.pieceSizeRatio = .by(pair: n) }
162+
update { $0.pieceSizeRatio = .by(pair: n!) }
163163
}),
164164
.init(title: "Container scale ratio", kind: .singleSlider(current: options.containerScaleRatio) { n in
165-
update { $0.containerScaleRatio = n }
165+
update { $0.containerScaleRatio = n! }
166166
}),
167167
.init(title: "Container translation ratio", kind: .doubleSlider(current: options.containerTranslationRatio.pair) { n in
168-
update { $0.containerTranslationRatio = .by(pair: n) }
168+
update { $0.containerTranslationRatio = .by(pair: n!) }
169169
}),
170-
.init(title: "Container min translation ratio", kind: .doubleSlider(current: options.containerMinTranslationRatio?.pair) { n in
171-
update { $0.containerMinTranslationRatio = .by(pair: n) }
170+
.init(title: "Container min translation ratio", kind: .doubleSlider(current: options.containerMinTranslationRatio?.pair, optional: true) { n in
171+
update { $0.containerMinTranslationRatio = n.map { .by(pair: $0) } }
172172
}),
173-
.init(title: "Container max translation ratio", kind: .doubleSlider(current: options.containerMaxTranslationRatio?.pair) { n in
174-
update { $0.containerMaxTranslationRatio = .by(pair: n) }
173+
.init(title: "Container max translation ratio", kind: .doubleSlider(current: options.containerMaxTranslationRatio?.pair, optional: true) { n in
174+
update { $0.containerMaxTranslationRatio = n.map { .by(pair: $0) } }
175175
})
176176
]
177177
}

Samples/PagingLayoutSamples/Modules/LayoutDesigner/Options/LayoutDesignerOptionsTableView.swift

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ class LayoutDesignerOptionsTableView: UITableView {
3131

3232
private func configure() {
3333
dataSource = self
34-
delegate = self
3534
register(LayoutDesignerOptionCell.self)
3635
backgroundColor = .clear
3736
separatorStyle = .none
@@ -53,10 +52,3 @@ extension LayoutDesignerOptionsTableView: UITableViewDataSource {
5352
return cell
5453
}
5554
}
56-
57-
extension LayoutDesignerOptionsTableView: UITableViewDelegate {
58-
59-
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
60-
64
61-
}
62-
}

Samples/PagingLayoutSamples/Modules/LayoutDesigner/Options/cell/LayoutDesignerOptionCell.swift

Lines changed: 87 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,23 @@ class LayoutDesignerOptionCell: UITableViewCell, NibBased {
1919
}
2020

2121
@IBOutlet private weak var label: UILabel!
22-
@IBOutlet private weak var slider1: UISlider!
23-
@IBOutlet private weak var input1: UITextField!
24-
@IBOutlet private weak var slider2: UISlider!
25-
@IBOutlet private weak var input2: UITextField!
22+
@IBOutlet private weak var singleSlider: UISlider!
23+
@IBOutlet private weak var singleSliderInput: UITextField!
24+
@IBOutlet private weak var doubleSliderStackView: UIStackView!
25+
@IBOutlet private weak var doubleSlider1: UISlider!
26+
@IBOutlet private weak var doubleSliderInput1: UITextField!
27+
@IBOutlet private weak var doubleSlider2: UISlider!
28+
@IBOutlet private weak var doubleSliderInput2: UITextField!
2629
@IBOutlet private weak var segmentedControl: UISegmentedControl!
30+
@IBOutlet private weak var nilLabel: UILabel!
2731
@IBOutlet private weak var switchView: UISwitch!
28-
private var equalWidthConstraint: NSLayoutConstraint?
2932

30-
private var onSlider1Change: (CGFloat) -> Void = { _ in }
31-
private var onInput1Change: (CGFloat) -> Void = { _ in }
32-
private var onSlider2Change: (CGFloat) -> Void = { _ in }
33-
private var onInput2Change: (CGFloat) -> Void = { _ in }
33+
private var onSingleSliderChange: (CGFloat) -> Void = { _ in }
34+
private var onSingleSliderInputChange: (CGFloat) -> Void = { _ in }
35+
private var onDoubleSlider1Change: (CGFloat) -> Void = { _ in }
36+
private var onDoubleSliderInput1Change: (CGFloat) -> Void = { _ in }
37+
private var onDoubleSlider2Change: (CGFloat) -> Void = { _ in }
38+
private var onDoubleSliderInput2Change: (CGFloat) -> Void = { _ in }
3439
private var onSwitchChange: (Bool) -> Void = { _ in }
3540
private var onSelectedSegmentChange: (Int) -> Void = { _ in }
3641

@@ -49,14 +54,15 @@ class LayoutDesignerOptionCell: UITableViewCell, NibBased {
4954
private func setupViews() {
5055
backgroundColor = .clear
5156
label.textColor = UIColor.white.withAlphaComponent(0.7)
52-
[slider1, slider2].forEach {
57+
nilLabel.textColor = UIColor.white.withAlphaComponent(0.7)
58+
[singleSlider, doubleSlider1, doubleSlider2].forEach {
5359
$0?.tintColor = .white
5460
$0?.thumbTintColor = .white
5561
$0?.maximumTrackTintColor = UIColor.white.withAlphaComponent(0.3)
5662
$0?.minimumTrackTintColor = .white
5763
$0?.addTarget(self, action: #selector(onSliderChange(slider:)), for: .valueChanged)
5864
}
59-
[input1, input2].forEach {
65+
[singleSliderInput, doubleSliderInput1, doubleSliderInput2].forEach {
6066
$0?.backgroundColor = .white
6167
$0?.textAlignment = .center
6268
$0?.layer.cornerRadius = 8
@@ -93,68 +99,93 @@ class LayoutDesignerOptionCell: UITableViewCell, NibBased {
9399

94100
private func onSliderChange(slider: UISlider, fromInput: Bool) {
95101
let value = CGFloat(slider.value)
96-
if slider == slider1, !(slider1.value == Float(value) && fromInput) {
97-
onSlider1Change(value)
98-
onInputChange(input: input1, fromSlider: true)
99-
input1.set(value: value)
100-
} else if slider == slider2, !(slider2.value == Float(value) && fromInput) {
101-
onSlider2Change(value)
102-
onInputChange(input: input2, fromSlider: true)
103-
input2.set(value: value)
102+
if slider == singleSlider, !(singleSlider.value == Float(value) && fromInput) {
103+
onSingleSliderChange(value)
104+
onInputChange(input: singleSliderInput, fromSlider: true)
105+
singleSliderInput.set(value: value)
106+
} else if slider == doubleSlider1, !(doubleSlider1.value == Float(value) && fromInput) {
107+
onDoubleSlider1Change(value)
108+
onInputChange(input: doubleSliderInput1, fromSlider: true)
109+
doubleSliderInput1.set(value: value)
110+
} else if slider == doubleSlider2, !(doubleSlider2.value == Float(value) && fromInput) {
111+
onDoubleSlider2Change(value)
112+
onInputChange(input: doubleSliderInput2, fromSlider: true)
113+
doubleSliderInput2.set(value: value)
104114
}
105115
}
106116

107117
private func onInputChange(input: UITextField, fromSlider: Bool) {
108118
let value = input.floatValue
109-
if input == input1, !(input1.floatValue == value && fromSlider) {
110-
onInput1Change(CGFloat(value))
111-
onSliderChange(slider: slider1, fromInput: true)
112-
slider1.value = value
113-
} else if input == input2, !(input2.floatValue == value && fromSlider) {
114-
onInput2Change(CGFloat(value))
115-
onSliderChange(slider: slider2, fromInput: true)
116-
slider2.value = value
119+
if input == singleSliderInput, !(singleSliderInput.floatValue == value && fromSlider) {
120+
onSingleSliderInputChange(CGFloat(value))
121+
onSliderChange(slider: singleSlider, fromInput: true)
122+
singleSlider.value = value
123+
} else if input == doubleSliderInput1, !(doubleSliderInput1.floatValue == value && fromSlider) {
124+
onDoubleSliderInput1Change(CGFloat(value))
125+
onSliderChange(slider: doubleSlider1, fromInput: true)
126+
doubleSlider1.value = value
127+
} else if input == doubleSliderInput2, !(doubleSliderInput2.floatValue == value && fromSlider) {
128+
onDoubleSliderInput2Change(CGFloat(value))
129+
onSliderChange(slider: doubleSlider2, fromInput: true)
130+
doubleSlider2.value = value
117131
}
118132
}
119133

120134
private func updateViews() {
121135
guard let viewModel = viewModel, label != nil else { return }
122136

123137
label.text = viewModel.title
124-
slider1.isHidden = true
125-
input1.isHidden = true
126-
slider2.isHidden = true
127-
input2.isHidden = true
138+
singleSlider.isHidden = true
139+
singleSliderInput.isHidden = true
140+
doubleSliderStackView.isHidden = true
128141
segmentedControl.isHidden = true
129142
switchView.isHidden = true
130-
equalWidthConstraint?.isActive = false
131-
slider2.superview?.isHidden = true
143+
nilLabel.isHidden = true
132144

133145
switch viewModel.kind {
134146

135-
case let .singleSlider(current, onChange):
136-
slider1.isHidden = false
137-
input1.isHidden = false
138-
input1.set(value: current ?? 0)
139-
slider1.value = Float(current ?? 0)
140-
onSlider1Change = onChange
147+
case let .singleSlider(current, optional, onChange):
148+
singleSlider.isHidden = false
149+
singleSliderInput.isHidden = false
150+
singleSliderInput.set(value: current ?? 0)
151+
singleSlider.value = Float(current ?? 0)
152+
onSingleSliderChange = onChange
153+
if optional {
154+
switchView.isHidden = false
155+
switchView.isOn = current == nil
156+
nilLabel.isHidden = false
157+
onSwitchChange = { [weak self] in
158+
guard let self = self else { return }
159+
onChange($0 ? nil : CGFloat(self.singleSlider.value))
160+
self.singleSlider.isHidden = $0
161+
self.singleSliderInput.isHidden = $0
162+
}
163+
onSwitchChange(switchView.isOn)
164+
}
165+
166+
case let .doubleSlider(current, optional, onChange):
167+
doubleSliderStackView.isHidden = false
168+
doubleSliderStackView.alpha = 1
169+
doubleSliderInput1.set(value: current?.0 ?? 0)
170+
doubleSlider1.value = Float(current?.0 ?? 0)
171+
doubleSliderInput2.set(value: current?.1 ?? 0)
172+
doubleSlider2.value = Float(current?.1 ?? 0)
173+
let getValues = { [weak self] in self.map { (CGFloat($0.doubleSlider1.value), CGFloat($0.doubleSlider2.value)) } }
174+
175+
onDoubleSlider1Change = { _ in onChange(getValues()) }
176+
onDoubleSlider2Change = { _ in onChange(getValues()) }
177+
if optional {
178+
switchView.isHidden = false
179+
switchView.isOn = current == nil
180+
nilLabel.isHidden = false
181+
onSwitchChange = { [weak self] in
182+
guard let self = self else { return }
183+
onChange($0 ? nil : getValues())
184+
self.doubleSliderStackView.alpha = $0 ? 0 : 1
185+
}
186+
onSwitchChange(switchView.isOn)
187+
}
141188

142-
case let .doubleSlider(current, onChange):
143-
equalWidthConstraint = slider1.widthAnchor.constraint(equalTo: slider2.widthAnchor, multiplier: 1)
144-
equalWidthConstraint?.isActive = true
145-
slider1.isHidden = false
146-
input1.isHidden = false
147-
slider2.superview?.isHidden = false
148-
input1.set(value: current?.0 ?? 0)
149-
slider1.value = Float(current?.0 ?? 0)
150-
slider2.isHidden = false
151-
input2.isHidden = false
152-
input2.set(value: current?.1 ?? 0)
153-
slider2.value = Float(current?.1 ?? 0)
154-
onSlider1Change = { [weak self] in onChange(($0, CGFloat(self?.slider2.value ?? 0))) }
155-
onSlider2Change = { [weak self] in onChange((CGFloat(self?.slider1.value ?? 0), $0)) }
156-
onInput1Change = { [weak self] in onChange(($0, CGFloat(self?.input2.floatValue ?? 0))) }
157-
onInput2Change = { [weak self] in onChange((CGFloat(self?.input1.floatValue ?? 0), $0)) }
158189

159190
case let .toggleSwitch(current, onChange):
160191
switchView.isHidden = false
@@ -168,7 +199,7 @@ class LayoutDesignerOptionCell: UITableViewCell, NibBased {
168199
segmentedControl.insertSegment(withTitle: $0, at: 0, animated: false)
169200
}
170201
onSelectedSegmentChange = { onChange(options[$0]) }
171-
if let current = current, let index = options.firstIndex(of: current) {
202+
if let index = options.firstIndex(of: current) {
172203
segmentedControl.selectedSegmentIndex = index
173204
}
174205
}

0 commit comments

Comments
 (0)