Skip to content

Commit

Permalink
Added methods to handle currently selected tab state with imperative …
Browse files Browse the repository at this point in the history
…syntax.
  • Loading branch information
jasudev committed Mar 31, 2022
1 parent 9de0fd2 commit 4a9a9c6
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 25 deletions.
10 changes: 10 additions & 0 deletions AxisSegmentedViewExample/Shared/CustomStyleView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ struct CustomStyleView: View {
}
} style: {
CustomStyle(color: .blue)
} onTapReceive: { selectionTap in
/// Imperative syntax
print("---------------------")
print("Selection : ", selectionTap)
print("Already selected : ", self.selection == selectionTap)
}
.frame(width: 44)

Expand All @@ -56,6 +61,11 @@ struct CustomStyleView: View {
}
} style: {
CustomStyle(color: .red)
} onTapReceive: { selectionTap in
/// Imperative syntax
print("---------------------")
print("Selection : ", selectionTap)
print("Already selected : ", self.selection == selectionTap)
}
.frame(height: 44)
}
Expand Down
11 changes: 8 additions & 3 deletions AxisSegmentedViewExample/Shared/SegmentedViewWithControl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,16 @@ struct SegmentedViewWithControl<Tabs: View, Style: View> : View {
}

private var segmentedView: some View {
AxisSegmentedView(selection: $selection, constant: constant, {
AxisSegmentedView(selection: $selection, constant: constant) {
tabs()
}, style: {
} style: {
style()
})
} onTapReceive: { selectionTap in
/// Imperative syntax
print("---------------------")
print("Selection : ", selectionTap)
print("Already selected : ", self.selection == selectionTap)
}
.font(.system(size: 20))
}

Expand Down
10 changes: 10 additions & 0 deletions AxisSegmentedViewExample/Shared/WithoutStyleView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,20 @@ struct WithoutStyleView: View {
VStack {
AxisSegmentedView(selection: $selection1, constant: constant1) {
TabViews()
} onTapReceive: { selectionTap in
/// Imperative syntax
print("---------------------")
print("Selection : ", selectionTap)
print("Already selected : ", self.selection1 == selectionTap)
}
.clipped()
AxisSegmentedView(selection: $selection2, constant: constant2) {
TabViews()
} onTapReceive: { selectionTap in
/// Imperative syntax
print("---------------------")
print("Selection : ", selectionTap)
print("Already selected : ", self.selection2 == selectionTap)
}
.clipped()
}
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ AxisSegmentedView(selection: $selection, constant: .init()) {
}
} style: {
ASBasicStyle()
} onTapReceive: { selectionTap in
/// Imperative syntax
print("---------------------")
print("Selection : ", selectionTap)
print("Already selected : ", self.selection == selectionTap)
}
.frame(height: 44)
```
Expand Down
12 changes: 8 additions & 4 deletions Sources/AxisSegmentedView/AxisSegmentedView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,14 @@ public extension AxisSegmentedView where SelectionValue: Hashable, Content: View
/// - constant: A constant value for segmented view.
/// - content: Content views with tab items applied.
/// - style: The style of the segmented view.
/// - onTapReceive: Method that treats the currently selected tab as imperative syntax.
init(selection: Binding<SelectionValue>,
constant: ASConstant = .init(),
@ViewBuilder _ content: @escaping () -> Content,
@ViewBuilder style: @escaping () -> Style) {
@ViewBuilder style: @escaping () -> Style,
onTapReceive: ((SelectionValue) -> Void)? = nil) {

self.selectionValue = ASSelectionValue(selection: selection)
self.selectionValue = ASSelectionValue(selection: selection, onTapReceive: onTapReceive)
self.constant = constant
self.style = style
self.content = content
Expand All @@ -126,11 +128,13 @@ public extension AxisSegmentedView where SelectionValue: Hashable, Content: View
/// - selection: The currently selected tap value.
/// - constant: A constant value for segmented view.
/// - content: Content views with tab items applied.
/// - onTapReceive: Method that treats the currently selected tab as imperative syntax.
init(selection: Binding<SelectionValue>,
constant: ASConstant = .init(),
@ViewBuilder _ content: @escaping () -> Content) {
@ViewBuilder _ content: @escaping () -> Content,
onTapReceive: ((SelectionValue) -> Void)? = nil) {

self.selectionValue = ASSelectionValue(selection: selection)
self.selectionValue = ASSelectionValue(selection: selection, onTapReceive: onTapReceive)
self.constant = constant
self.content = content
}
Expand Down
40 changes: 24 additions & 16 deletions Sources/AxisSegmentedView/Private/Modifiers/ASItemModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,23 +44,31 @@ struct ASItemModifier<SelectionValue: Hashable, S: View>: ViewModifier {
var selectArea: CGFloat
var select: S? = nil

private var selection: Binding<SelectionValue> { Binding(
get: { self.selectionValue.selection },
set: {
self.selectionValue.onTapReceive?($0)
self.selectionValue.selection = $0
})
}

var normalSize: CGSize {
if positionValue.constant.axisMode == .horizontal {
return CGSize(width: positionValue.getNormalArea(selectionValue.selection),
return CGSize(width: positionValue.getNormalArea(self.selection.wrappedValue),
height: positionValue.size.height)
}else {
return CGSize(width: positionValue.size.width,
height: positionValue.getNormalArea(selectionValue.selection))
height: positionValue.getNormalArea(self.selection.wrappedValue))
}
}

var selectSize: CGSize {
if positionValue.constant.axisMode == .horizontal {
return CGSize(width: positionValue.getSelectArea(selectionValue.selection),
return CGSize(width: positionValue.getSelectArea(self.selection.wrappedValue),
height: positionValue.size.height)
}else {
return CGSize(width: positionValue.size.width,
height: positionValue.getSelectArea(selectionValue.selection))
height: positionValue.getSelectArea(self.selection.wrappedValue))
}
}

Expand All @@ -85,7 +93,7 @@ struct ASItemModifier<SelectionValue: Hashable, S: View>: ViewModifier {
ZStack {
if positionValue.isHasStyle {
Button {
self.selectionValue.selection = tag
self.selection.wrappedValue = tag
self.stateValue.isInitialRun = false
if positionValue.constant.isActivatedVibration { vibration() }
} label: {
Expand All @@ -100,19 +108,19 @@ struct ASItemModifier<SelectionValue: Hashable, S: View>: ViewModifier {
}else {
ZStack {
Button {
self.selectionValue.selection = tag
self.selection.wrappedValue = tag
self.stateValue.isInitialRun = false
if positionValue.constant.isActivatedVibration { vibration() }
} label: {
content
}
.contentShape(Rectangle())
.buttonStyle(.plain)
.opacity(tag != selectionValue.selection ? 1 : 0)
.opacity(tag != self.selection.wrappedValue ? 1 : 0)

select?
.contentShape(Rectangle())
.opacity(tag == selectionValue.selection ? 1 : 0)
.opacity(tag == self.selection.wrappedValue ? 1 : 0)

}
.frame(width: getItemSize().width, height: getItemSize().height)
Expand All @@ -136,7 +144,7 @@ struct ASItemModifier<SelectionValue: Hashable, S: View>: ViewModifier {
.onAppear {
self.setupStateValue()
}
.onChange(of: self.selectionValue.selection) { newValue in
.onChange(of: self.selection.wrappedValue) { newValue in
self.setupStateValue()
}
.onChange(of: selectArea) { newValue in
Expand All @@ -147,15 +155,15 @@ struct ASItemModifier<SelectionValue: Hashable, S: View>: ViewModifier {

private func getItemSize() -> CGSize {
if positionValue.constant.axisMode == .horizontal {
return CGSize(width: tag == selectionValue.selection ? selectSize.width : normalSize.width, height: positionValue.size.height)
return CGSize(width: tag == self.selection.wrappedValue ? selectSize.width : normalSize.width, height: positionValue.size.height)
}else {
return CGSize(width: positionValue.size.width, height: tag == selectionValue.selection ? selectSize.height : normalSize.height)
return CGSize(width: positionValue.size.width, height: tag == self.selection.wrappedValue ? selectSize.height : normalSize.height)
}
}

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

private func getItemView(_ content: Content) -> some View {
ZStack {
if tag == selectionValue.selection {
if tag == self.selection.wrappedValue {
ZStack {
if let select = select {
select
.onAppear {
DispatchQueue.main.async {
stateValue.previousIndex = stateValue.selectionIndex
stateValue.previousFrame = positionValue.getSelectFrame(self.selectionValue.selection, selectionIndex: stateValue.selectionIndex)
stateValue.previousFrame = positionValue.getSelectFrame(self.selection.wrappedValue, selectionIndex: stateValue.selectionIndex)

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

private func setupStateValue() {
let selectionIndex = positionValue.indexOfTag(self.selectionValue.selection)
let selectionIndex = positionValue.indexOfTag(self.selection.wrappedValue)
stateValue.constant = positionValue.constant
stateValue.itemCount = positionValue.itemCount
stateValue.selectionIndex = selectionIndex
stateValue.selectionFrame = positionValue.getSelectFrame(self.selectionValue.selection, selectionIndex: selectionIndex)
stateValue.selectionFrame = positionValue.getSelectFrame(self.selection.wrappedValue, selectionIndex: selectionIndex)
stateValue.size = positionValue.size
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@ class ASSelectionValue<SelectionValue: Hashable>: ObservableObject {

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

/// Initializes `ASSelectionValue`
/// - Parameters:
/// - selection: The currently selected tap value.
init(selection: Binding<SelectionValue>) {
/// - onTapReceive: Method that treats the currently selected tab as imperative syntax.
init(selection: Binding<SelectionValue>, onTapReceive: ((SelectionValue) -> Void)? = nil) {
_selection = selection

self.onTapReceive = onTapReceive
}
}

0 comments on commit 4a9a9c6

Please sign in to comment.