Skip to content

Commit 4a9a9c6

Browse files
committed
Added methods to handle currently selected tab state with imperative syntax.
1 parent 9de0fd2 commit 4a9a9c6

File tree

7 files changed

+69
-25
lines changed

7 files changed

+69
-25
lines changed

AxisSegmentedViewExample/Shared/CustomStyleView.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ struct CustomStyleView: View {
3434
}
3535
} style: {
3636
CustomStyle(color: .blue)
37+
} onTapReceive: { selectionTap in
38+
/// Imperative syntax
39+
print("---------------------")
40+
print("Selection : ", selectionTap)
41+
print("Already selected : ", self.selection == selectionTap)
3742
}
3843
.frame(width: 44)
3944

@@ -56,6 +61,11 @@ struct CustomStyleView: View {
5661
}
5762
} style: {
5863
CustomStyle(color: .red)
64+
} onTapReceive: { selectionTap in
65+
/// Imperative syntax
66+
print("---------------------")
67+
print("Selection : ", selectionTap)
68+
print("Already selected : ", self.selection == selectionTap)
5969
}
6070
.frame(height: 44)
6171
}

AxisSegmentedViewExample/Shared/SegmentedViewWithControl.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,16 @@ struct SegmentedViewWithControl<Tabs: View, Style: View> : View {
5050
}
5151

5252
private var segmentedView: some View {
53-
AxisSegmentedView(selection: $selection, constant: constant, {
53+
AxisSegmentedView(selection: $selection, constant: constant) {
5454
tabs()
55-
}, style: {
55+
} style: {
5656
style()
57-
})
57+
} onTapReceive: { selectionTap in
58+
/// Imperative syntax
59+
print("---------------------")
60+
print("Selection : ", selectionTap)
61+
print("Already selected : ", self.selection == selectionTap)
62+
}
5863
.font(.system(size: 20))
5964
}
6065

AxisSegmentedViewExample/Shared/WithoutStyleView.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,20 @@ struct WithoutStyleView: View {
2121
VStack {
2222
AxisSegmentedView(selection: $selection1, constant: constant1) {
2323
TabViews()
24+
} onTapReceive: { selectionTap in
25+
/// Imperative syntax
26+
print("---------------------")
27+
print("Selection : ", selectionTap)
28+
print("Already selected : ", self.selection1 == selectionTap)
2429
}
2530
.clipped()
2631
AxisSegmentedView(selection: $selection2, constant: constant2) {
2732
TabViews()
33+
} onTapReceive: { selectionTap in
34+
/// Imperative syntax
35+
print("---------------------")
36+
print("Selection : ", selectionTap)
37+
print("Already selected : ", self.selection2 == selectionTap)
2838
}
2939
.clipped()
3040
}

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ AxisSegmentedView(selection: $selection, constant: .init()) {
4242
}
4343
} style: {
4444
ASBasicStyle()
45+
} onTapReceive: { selectionTap in
46+
/// Imperative syntax
47+
print("---------------------")
48+
print("Selection : ", selectionTap)
49+
print("Already selected : ", self.selection == selectionTap)
4550
}
4651
.frame(height: 44)
4752
```

Sources/AxisSegmentedView/AxisSegmentedView.swift

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,14 @@ public extension AxisSegmentedView where SelectionValue: Hashable, Content: View
107107
/// - constant: A constant value for segmented view.
108108
/// - content: Content views with tab items applied.
109109
/// - style: The style of the segmented view.
110+
/// - onTapReceive: Method that treats the currently selected tab as imperative syntax.
110111
init(selection: Binding<SelectionValue>,
111112
constant: ASConstant = .init(),
112113
@ViewBuilder _ content: @escaping () -> Content,
113-
@ViewBuilder style: @escaping () -> Style) {
114+
@ViewBuilder style: @escaping () -> Style,
115+
onTapReceive: ((SelectionValue) -> Void)? = nil) {
114116

115-
self.selectionValue = ASSelectionValue(selection: selection)
117+
self.selectionValue = ASSelectionValue(selection: selection, onTapReceive: onTapReceive)
116118
self.constant = constant
117119
self.style = style
118120
self.content = content
@@ -126,11 +128,13 @@ public extension AxisSegmentedView where SelectionValue: Hashable, Content: View
126128
/// - selection: The currently selected tap value.
127129
/// - constant: A constant value for segmented view.
128130
/// - content: Content views with tab items applied.
131+
/// - onTapReceive: Method that treats the currently selected tab as imperative syntax.
129132
init(selection: Binding<SelectionValue>,
130133
constant: ASConstant = .init(),
131-
@ViewBuilder _ content: @escaping () -> Content) {
134+
@ViewBuilder _ content: @escaping () -> Content,
135+
onTapReceive: ((SelectionValue) -> Void)? = nil) {
132136

133-
self.selectionValue = ASSelectionValue(selection: selection)
137+
self.selectionValue = ASSelectionValue(selection: selection, onTapReceive: onTapReceive)
134138
self.constant = constant
135139
self.content = content
136140
}

Sources/AxisSegmentedView/Private/Modifiers/ASItemModifier.swift

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -44,23 +44,31 @@ struct ASItemModifier<SelectionValue: Hashable, S: View>: ViewModifier {
4444
var selectArea: CGFloat
4545
var select: S? = nil
4646

47+
private var selection: Binding<SelectionValue> { Binding(
48+
get: { self.selectionValue.selection },
49+
set: {
50+
self.selectionValue.onTapReceive?($0)
51+
self.selectionValue.selection = $0
52+
})
53+
}
54+
4755
var normalSize: CGSize {
4856
if positionValue.constant.axisMode == .horizontal {
49-
return CGSize(width: positionValue.getNormalArea(selectionValue.selection),
57+
return CGSize(width: positionValue.getNormalArea(self.selection.wrappedValue),
5058
height: positionValue.size.height)
5159
}else {
5260
return CGSize(width: positionValue.size.width,
53-
height: positionValue.getNormalArea(selectionValue.selection))
61+
height: positionValue.getNormalArea(self.selection.wrappedValue))
5462
}
5563
}
5664

5765
var selectSize: CGSize {
5866
if positionValue.constant.axisMode == .horizontal {
59-
return CGSize(width: positionValue.getSelectArea(selectionValue.selection),
67+
return CGSize(width: positionValue.getSelectArea(self.selection.wrappedValue),
6068
height: positionValue.size.height)
6169
}else {
6270
return CGSize(width: positionValue.size.width,
63-
height: positionValue.getSelectArea(selectionValue.selection))
71+
height: positionValue.getSelectArea(self.selection.wrappedValue))
6472
}
6573
}
6674

@@ -85,7 +93,7 @@ struct ASItemModifier<SelectionValue: Hashable, S: View>: ViewModifier {
8593
ZStack {
8694
if positionValue.isHasStyle {
8795
Button {
88-
self.selectionValue.selection = tag
96+
self.selection.wrappedValue = tag
8997
self.stateValue.isInitialRun = false
9098
if positionValue.constant.isActivatedVibration { vibration() }
9199
} label: {
@@ -100,19 +108,19 @@ struct ASItemModifier<SelectionValue: Hashable, S: View>: ViewModifier {
100108
}else {
101109
ZStack {
102110
Button {
103-
self.selectionValue.selection = tag
111+
self.selection.wrappedValue = tag
104112
self.stateValue.isInitialRun = false
105113
if positionValue.constant.isActivatedVibration { vibration() }
106114
} label: {
107115
content
108116
}
109117
.contentShape(Rectangle())
110118
.buttonStyle(.plain)
111-
.opacity(tag != selectionValue.selection ? 1 : 0)
119+
.opacity(tag != self.selection.wrappedValue ? 1 : 0)
112120

113121
select?
114122
.contentShape(Rectangle())
115-
.opacity(tag == selectionValue.selection ? 1 : 0)
123+
.opacity(tag == self.selection.wrappedValue ? 1 : 0)
116124

117125
}
118126
.frame(width: getItemSize().width, height: getItemSize().height)
@@ -136,7 +144,7 @@ struct ASItemModifier<SelectionValue: Hashable, S: View>: ViewModifier {
136144
.onAppear {
137145
self.setupStateValue()
138146
}
139-
.onChange(of: self.selectionValue.selection) { newValue in
147+
.onChange(of: self.selection.wrappedValue) { newValue in
140148
self.setupStateValue()
141149
}
142150
.onChange(of: selectArea) { newValue in
@@ -147,15 +155,15 @@ struct ASItemModifier<SelectionValue: Hashable, S: View>: ViewModifier {
147155

148156
private func getItemSize() -> CGSize {
149157
if positionValue.constant.axisMode == .horizontal {
150-
return CGSize(width: tag == selectionValue.selection ? selectSize.width : normalSize.width, height: positionValue.size.height)
158+
return CGSize(width: tag == self.selection.wrappedValue ? selectSize.width : normalSize.width, height: positionValue.size.height)
151159
}else {
152-
return CGSize(width: positionValue.size.width, height: tag == selectionValue.selection ? selectSize.height : normalSize.height)
160+
return CGSize(width: positionValue.size.width, height: tag == self.selection.wrappedValue ? selectSize.height : normalSize.height)
153161
}
154162
}
155163

156164
private func isShowDivideLine() -> Bool {
157165
let currentIndex = positionValue.indexOfTag(tag)
158-
let selectionIndex = positionValue.indexOfTag(selectionValue.selection)
166+
let selectionIndex = positionValue.indexOfTag(self.selection.wrappedValue)
159167
if positionValue.constant.divideLine.isShowSelectionLine {
160168
return currentIndex != 0
161169
}else {
@@ -165,14 +173,14 @@ struct ASItemModifier<SelectionValue: Hashable, S: View>: ViewModifier {
165173

166174
private func getItemView(_ content: Content) -> some View {
167175
ZStack {
168-
if tag == selectionValue.selection {
176+
if tag == self.selection.wrappedValue {
169177
ZStack {
170178
if let select = select {
171179
select
172180
.onAppear {
173181
DispatchQueue.main.async {
174182
stateValue.previousIndex = stateValue.selectionIndex
175-
stateValue.previousFrame = positionValue.getSelectFrame(self.selectionValue.selection, selectionIndex: stateValue.selectionIndex)
183+
stateValue.previousFrame = positionValue.getSelectFrame(self.selection.wrappedValue, selectionIndex: stateValue.selectionIndex)
176184

177185
if positionValue.constant.axisMode == .horizontal {
178186
stateValue.otherSize = CGSize(width: normalSize.width, height: positionValue.size.height)
@@ -198,11 +206,11 @@ struct ASItemModifier<SelectionValue: Hashable, S: View>: ViewModifier {
198206
}
199207

200208
private func setupStateValue() {
201-
let selectionIndex = positionValue.indexOfTag(self.selectionValue.selection)
209+
let selectionIndex = positionValue.indexOfTag(self.selection.wrappedValue)
202210
stateValue.constant = positionValue.constant
203211
stateValue.itemCount = positionValue.itemCount
204212
stateValue.selectionIndex = selectionIndex
205-
stateValue.selectionFrame = positionValue.getSelectFrame(self.selectionValue.selection, selectionIndex: selectionIndex)
213+
stateValue.selectionFrame = positionValue.getSelectFrame(self.selection.wrappedValue, selectionIndex: selectionIndex)
206214
stateValue.size = positionValue.size
207215
}
208216

Sources/AxisSegmentedView/Private/ViewModel/ASSelectionValue.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,15 @@ class ASSelectionValue<SelectionValue: Hashable>: ObservableObject {
3030

3131
/// The currently selected tap value.
3232
@Binding var selection: SelectionValue
33+
var onTapReceive: ((SelectionValue) -> Void)?
3334

3435
/// Initializes `ASSelectionValue`
3536
/// - Parameters:
3637
/// - selection: The currently selected tap value.
37-
init(selection: Binding<SelectionValue>) {
38+
/// - onTapReceive: Method that treats the currently selected tab as imperative syntax.
39+
init(selection: Binding<SelectionValue>, onTapReceive: ((SelectionValue) -> Void)? = nil) {
3840
_selection = selection
39-
41+
self.onTapReceive = onTapReceive
4042
}
4143
}
4244

0 commit comments

Comments
 (0)