Skip to content

Commit f3ceac3

Browse files
authored
Merge pull request #28 from c-villain/support-rtl
add support for RTL languages
2 parents 84c9241 + 47bd4b7 commit f3ceac3

File tree

3 files changed

+98
-64
lines changed

3 files changed

+98
-64
lines changed

Example/iOS/ExampleView.swift

Lines changed: 48 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,12 @@ struct ExampleView: View {
8383
.frame(maxWidth: .infinity)
8484
.padding()
8585
.background(Color(UIColor.systemBackground))
86-
.addFullSwipeAction(menu: .slided,
87-
swipeColor: .green,
88-
swipeRole: .defaults,
89-
state: $state) {
86+
.addFullSwipeAction(
87+
menu: .slided,
88+
swipeColor: .green,
89+
swipeRole: .`default`,
90+
state: $state
91+
) {
9092
Leading {
9193
Button {
9294
} label: {
@@ -123,6 +125,7 @@ struct ExampleView: View {
123125
}
124126
}
125127
}
128+
//.environment(\.layoutDirection, .rightToLeft) //check for TRL languages
126129
.alert(isPresented: $fullSwiped) {
127130
Alert(title: Text(selectedAction),
128131
dismissButton: .default(Text("Archived!")) {
@@ -156,9 +159,11 @@ struct ExampleView: View {
156159
.contentShape(Rectangle())
157160
.padding()
158161
.background(Color(UIColor.systemBackground))
159-
.addFullSwipeAction(menu: .slided,
160-
swipeColor: .red,
161-
state: $state) {
162+
.addFullSwipeAction(
163+
menu: .slided,
164+
swipeColor: .red,
165+
state: $state
166+
) {
162167
Leading {
163168
Button {
164169
selectedAction = "cell \(cell) checked!"
@@ -237,10 +242,12 @@ struct ExampleView: View {
237242
.frame(maxWidth: .infinity)
238243
.padding()
239244
.background(Color(UIColor.systemBackground))
240-
.addFullSwipeAction(menu: .slided,
241-
swipeColor: .green,
242-
swipeRole: .defaults,
243-
state: $state) {
245+
.addFullSwipeAction(
246+
menu: .slided,
247+
swipeColor: .green,
248+
swipeRole: .default,
249+
state: $state
250+
) {
244251
Leading {
245252
Button {
246253
} label: {
@@ -272,12 +279,14 @@ struct ExampleView: View {
272279
}
273280
}
274281
.alert(isPresented: $fullSwiped) {
275-
Alert(title: Text(selectedAction),
276-
dismissButton: .default(Text("Archived!")) {
277-
withAnimation {
278-
state = .swiped(UUID())
282+
Alert(
283+
title: Text(selectedAction),
284+
dismissButton: .default(Text("Archived!")) {
285+
withAnimation {
286+
state = .swiped(UUID())
287+
}
279288
}
280-
})
289+
)
281290
}
282291
}
283292
}
@@ -310,8 +319,10 @@ struct ExampleView: View {
310319
)
311320
.contentShape(Rectangle())
312321
.listStyle(.plain)
313-
.addSwipeAction(menu: .swiped,
314-
state: $state) {
322+
.addSwipeAction(
323+
menu: .swiped,
324+
state: $state
325+
) {
315326
Leading {
316327
Button {
317328
print("check \(cell)")
@@ -440,11 +451,11 @@ struct ExampleView: View {
440451
.frame(width: UIScreen.main.bounds.size.width - 32, height: 80)
441452
.contentShape(Rectangle())
442453
.background(Color(UIColor.systemBackground))
443-
.onTapGesture {
444-
}
445-
.addSwipeAction(menu: .swiped,
446-
state: $state) {
447-
454+
.onTapGesture {}
455+
.addSwipeAction(
456+
menu: .swiped,
457+
state: $state
458+
) {
448459
Leading {
449460
Button {
450461
} label: {
@@ -465,9 +476,8 @@ struct ExampleView: View {
465476
.contentShape(Rectangle())
466477
.background(Color.green)
467478
}
468-
}
469-
.listRowInsets(EdgeInsets())
470-
.hideSeparators()
479+
}.listRowInsets(EdgeInsets())
480+
.hideSeparators()
471481
}
472482
.padding(16)
473483
.listStyle(.plain)
@@ -482,10 +492,11 @@ struct ExampleView: View {
482492
.padding(.horizontal, 16)
483493
.frame(width: UIScreen.main.bounds.size.width - 32, height: 80)
484494
.background(Color(UIColor.systemBackground))
485-
.onTapGesture {
486-
}
487-
.addSwipeAction(edge: .trailing,
488-
state: $state) {
495+
.onTapGesture {}
496+
.addSwipeAction(
497+
edge: .trailing,
498+
state: $state
499+
) {
489500
Button {
490501
print("remove")
491502
} label: {
@@ -495,9 +506,8 @@ struct ExampleView: View {
495506
.frame(width: 60, height: 80, alignment: .center)
496507
.contentShape(Rectangle())
497508
.background(Color.red)
498-
}
499-
.listRowInsets(EdgeInsets())
500-
.hideSeparators()
509+
}.listRowInsets(EdgeInsets())
510+
.hideSeparators()
501511

502512
}
503513
.padding(16)
@@ -577,9 +587,11 @@ struct ExampleView: View {
577587
.contentShape(Rectangle())
578588
.padding()
579589
.background(Color(UIColor.systemBackground))
580-
.addFullSwipeAction(menu: .slided,
581-
swipeColor: .red,
582-
state: $state) {
590+
.addFullSwipeAction(
591+
menu: .slided,
592+
swipeColor: .red,
593+
state: $state
594+
) {
583595
Leading {
584596
Button {
585597
selectedAction = "cell \(cell) checked!"

Sources/SwipeActions/SwipeActions.swift

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public enum MenuType {
1212
public enum SwipeRole {
1313
case destructive /// for removing element
1414
case cancel
15-
case defaults
15+
case `default`
1616
}
1717

1818
/// For opened cells auto-hiding during swiping anothers
@@ -27,8 +27,10 @@ private enum VisibleButton: Equatable {
2727
case right(UUID)
2828
}
2929

30-
struct SwipeAction<V1: View, V2: View>: ViewModifier {
30+
public struct SwipeAction<V1: View, V2: View>: ViewModifier {
3131

32+
@Environment(\.layoutDirection) var layoutDirection
33+
3234
@Binding private var state: SwipeState
3335
@State private var offset: CGFloat = 0
3436
@State private var oldOffset: CGFloat = 0
@@ -64,7 +66,7 @@ struct SwipeAction<V1: View, V2: View>: ViewModifier {
6466
init(
6567
menu: MenuType,
6668
allowsFullSwipe: Bool = false,
67-
fullSwipeRole: SwipeRole = .defaults,
69+
fullSwipeRole: SwipeRole = .default,
6870
swipeColor: Color? = nil,
6971
state: Binding<SwipeState>,
7072
@ViewBuilder _ content: @escaping () -> TupleView<(Leading<V1>, Trailing<V2>)>,
@@ -83,7 +85,7 @@ struct SwipeAction<V1: View, V2: View>: ViewModifier {
8385
init(
8486
menu: MenuType,
8587
allowsFullSwipe: Bool = false,
86-
fullSwipeRole: SwipeRole = .defaults,
88+
fullSwipeRole: SwipeRole = .default,
8789
swipeColor: Color? = nil,
8890
state: Binding<SwipeState>,
8991
@ViewBuilder leading: @escaping () -> V1,
@@ -102,7 +104,7 @@ struct SwipeAction<V1: View, V2: View>: ViewModifier {
102104
init(
103105
menu: MenuType,
104106
allowsFullSwipe: Bool = false,
105-
fullSwipeRole: SwipeRole = .defaults,
107+
fullSwipeRole: SwipeRole = .default,
106108
swipeColor: Color? = nil,
107109
state: Binding<SwipeState>,
108110
@ViewBuilder trailing: @escaping () -> V2,
@@ -118,13 +120,13 @@ struct SwipeAction<V1: View, V2: View>: ViewModifier {
118120
self.action = action
119121
}
120122

121-
func reset() {
123+
private func reset() {
122124
visibleButton = .none
123125
offset = 0
124126
oldOffset = 0
125127
}
126128

127-
var leadingView: some View {
129+
private var leadingView: some View {
128130
leadingSwipeView
129131
.measureSize {
130132
if !maxLeadingOffsetIsCounted {
@@ -141,7 +143,7 @@ struct SwipeAction<V1: View, V2: View>: ViewModifier {
141143
}
142144
}
143145

144-
var trailingView: some View {
146+
private var trailingView: some View {
145147
trailingSwipeView
146148
.measureSize {
147149
if !minTrailingOffsetIsCounted {
@@ -158,7 +160,7 @@ struct SwipeAction<V1: View, V2: View>: ViewModifier {
158160
}
159161
}
160162

161-
var swipedMenu: some View {
163+
private var swipedMenu: some View {
162164
HStack(spacing: 0) {
163165
leadingView
164166
Spacer()
@@ -167,7 +169,7 @@ struct SwipeAction<V1: View, V2: View>: ViewModifier {
167169
}
168170
}
169171

170-
var slidedMenu: some View {
172+
private var slidedMenu: some View {
171173
HStack(spacing: 0) {
172174
leadingView
173175
.offset(x: (-1 * maxLeadingOffset) + offset)
@@ -177,24 +179,28 @@ struct SwipeAction<V1: View, V2: View>: ViewModifier {
177179
}
178180
}
179181

180-
func gesturedContent(content: Content) -> some View {
181-
182+
private func gesturedContent(content: Content) -> some View {
182183
content
183184
.id(id)
184185
.contentShape(Rectangle()) ///otherwise swipe won't work in vacant area
185186
.offset(x: offset)
186187
.measureSize {
187188
contentWidth = $0.width
188189
}
189-
.gesture(
190-
// DragGesture(minimumDistance: 15, coordinateSpace: .local)
190+
.gesture (
191191
DragGesture(minimumDistance: 15, coordinateSpace: .global)
192192
.updating($dragGestureActive) { value, state, transaction in
193193
state = true
194194
}
195195
.onChanged { value in
196-
let totalSlide = value.translation.width + oldOffset
196+
let totalSlide: Double
197197

198+
switch layoutDirection {
199+
case .rightToLeft:
200+
totalSlide = -value.translation.width - oldOffset
201+
default:
202+
totalSlide = value.translation.width + oldOffset
203+
}
198204
if allowsFullSwipe && ...0 ~= Int(totalSlide) {
199205
withAnimation {
200206
offset = totalSlide
@@ -205,17 +211,26 @@ struct SwipeAction<V1: View, V2: View>: ViewModifier {
205211
}
206212
}
207213
}.onEnded { value in
214+
let translationWidth: Double
215+
216+
switch layoutDirection {
217+
case .rightToLeft:
218+
translationWidth = -value.translation.width
219+
default:
220+
translationWidth = value.translation.width
221+
}
222+
208223
withAnimation {
209224
if
210225
///user dismisses right buttons
211226
visibleButton == .left(id),
212-
value.translation.width < -20
227+
translationWidth < -20
213228
{
214229
reset()
215230
} else if
216231
///user dismisses right buttons
217232
visibleButton == .right(id),
218-
value.translation.width > 20
233+
translationWidth > 20
219234
{
220235
reset()
221236
} else if
@@ -239,7 +254,7 @@ struct SwipeAction<V1: View, V2: View>: ViewModifier {
239254

240255
if
241256
allowsFullSwipe,
242-
value.translation.width < -(contentWidth * 0.7)
257+
translationWidth < -(contentWidth * 0.7)
243258
{
244259
withAnimation(.linear(duration: 0.3)) {
245260
offset = -contentWidth
@@ -260,9 +275,10 @@ struct SwipeAction<V1: View, V2: View>: ViewModifier {
260275

261276
action?()
262277
}
263-
})
264-
.valueChanged(of: dragGestureActive) { dragActive in
265-
print("id: \(id) state: \(state) visibleButton: \(visibleButton) offset: \(offset)")
278+
}
279+
)
280+
.valueChanged(of: dragGestureActive) { _ in
281+
//print("id: \(id) state: \(state) visibleButton: \(visibleButton) offset: \(offset)")
266282
}
267283
.valueChanged(of: state) { value in
268284
switch value {
@@ -338,3 +354,4 @@ struct SwipeAction<V1: View, V2: View>: ViewModifier {
338354
}
339355
}
340356
}
357+

Sources/SwipeActions/ViewModifiers/SwipeHintModifier.swift

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ import SwiftUI
22

33
public extension View {
44
@ViewBuilder
5-
func swipeHint(_ isActive: Bool = false, hintOffset: CGFloat, delayIn: CGFloat = 0.5, delayOut: CGFloat = 1.5) -> some View {
5+
func swipeHint(
6+
_ isActive: Bool = false,
7+
hintOffset: CGFloat,
8+
delayIn: CGFloat = 0.5,
9+
delayOut: CGFloat = 1.5
10+
) -> some View {
611
if isActive {
712
modifier(
813
SwipeHintModifier(
@@ -27,12 +32,12 @@ public struct SwipeHintModifier: ViewModifier {
2732
content
2833
.offset(x: -offset)
2934
.onAppear {
30-
withAnimation(.easeInOut.delay(delayIn)) {
31-
offset = hintOffset
32-
}
33-
withAnimation(.easeInOut.delay(delayOut)) {
34-
offset = 0
35-
}
35+
withAnimation(.easeInOut.delay(delayIn)) {
36+
offset = hintOffset
37+
}
38+
withAnimation(.easeInOut.delay(delayOut)) {
39+
offset = 0
40+
}
3641
}
3742
}
3843
}

0 commit comments

Comments
 (0)