Skip to content

Commit

Permalink
Merge pull request #17 from twodayslate/initial_offset
Browse files Browse the repository at this point in the history
By @twodayslate :
Improvements to initial offset
Switch to offset based approach to cell status based approach
Replaces AnyView with ViewBuilder
  • Loading branch information
fatbobman authored Oct 23, 2022
2 parents 7d42b5f + 0d7569d commit 7c51a6c
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 152 deletions.
8 changes: 7 additions & 1 deletion Demo/Demo/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,13 @@ struct ContentView: View {
Button(action: { print("button") }) {
demo2()
}
.swipeCell(cellPosition: .both, leftSlot: slot1, rightSlot: slot1, initalOffset: 74 * 2, initialOffsetResetDelay: 2.0)
.swipeCell(
cellPosition: .both,
leftSlot: slot1,
rightSlot: slot1,
initalStatus: .showLeftSlot,
initialStatusResetDelay: 2.0
)

demo3()
.onTapGesture {
Expand Down
228 changes: 114 additions & 114 deletions Sources/SwipeCell/SwipeCellViewModifier1.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ struct SwipeCellModifier: ViewModifier {
let rightSlot: SwipeCellSlot?
let swipeCellStyle: SwipeCellStyle
let clip: Bool
/// If the offset should be reset to 0 onAppaer
@State var resetOffsetOnAppear = true
/// The amount of time it should take to reset the offset to 0.0 on appear
let initialOffsetResetDelay: TimeInterval
/// If the status should be reset
@State var shouldResetStatusOnAppear = true
/// The amount of time it should take to reset the status on appear
let initialStatusResetDelay: TimeInterval

@State var status: CellStatus = .showCell
@State var showDalayButtonWith: CGFloat = 0

@State var offset: CGFloat
@State var offset: CGFloat = 0.0

@State var frameWidth: CGFloat = 99999
@State var leftOffset: CGFloat = -10000
Expand Down Expand Up @@ -65,53 +65,55 @@ struct SwipeCellModifier: ViewModifier {
rightSlot: SwipeCellSlot?,
swipeCellStyle: SwipeCellStyle,
clip: Bool,
initialOffset: CGFloat = 0.0,
initialOffsetResetDelay: TimeInterval = 0.0
initialStatusResetDelay: TimeInterval = 0.0,
initialStatus: CellStatus = .showCell
) {
switch initialStatus {
case .showLeftSlot:
precondition(cellPosition != .right, "Initial status not supported with a right cell position")
case .showRightSlot:
precondition(cellPosition != .left, "Initial status not support with a left cell position")
default:
break
}
_cellPosition = State(wrappedValue: cellPosition)
self.clip = clip
self.leftSlot = leftSlot
self.rightSlot = rightSlot
self.swipeCellStyle = swipeCellStyle
self._offset = State(initialValue: initialOffset)
self.initialOffsetResetDelay = initialOffsetResetDelay
self._status = State(initialValue: initialStatus)
self.initialStatusResetDelay = initialStatusResetDelay
}

func emptyView(_ button: SwipeCellButton) -> some View {
Text("nil").foregroundColor(button.titleColor)
}

func buttonView(_ slot: SwipeCellSlot, _ i: Int) -> some View {
@ViewBuilder func buttonView(_ slot: SwipeCellSlot, _ i: Int) -> some View {
let button = slot.slots[i]
let viewStyle = button.buttonStyle

func emptyView() -> AnyView {
AnyView(
Text("nil").foregroundColor(button.titleColor)
)
}
let emptyView = emptyView(button)

switch viewStyle {
case .image:
guard let image = button.systemImage else {
return emptyView()
}
return AnyView(
if let image = button.systemImage {
Image(systemName: image)
.font(.system(size: 23))
.foregroundColor(button.imageColor)
)
case .title:
guard let title = button.title else {
return emptyView()
} else {
emptyView
}
return AnyView(
case .title:
if let title = button.title {
Text(title)
.font(.callout)
.bold()
.foregroundColor(button.titleColor)
)
case .titleAndImage:
guard let title = button.title, let image = button.systemImage else {
return emptyView()
} else {
emptyView
}
return AnyView(
case .titleAndImage:
if let title = button.title, let image = button.systemImage {
VStack(spacing: 5) {
Image(systemName: image)
.font(.system(size: 23))
Expand All @@ -121,13 +123,15 @@ struct SwipeCellModifier: ViewModifier {
.bold()
.foregroundColor(button.titleColor)
}
)

} else {
emptyView
}
case .view:
guard let view = button.view else {
return emptyView()
if let view = button.view {
view()
} else {
emptyView
}
return view()
}
}

Expand Down Expand Up @@ -227,13 +231,13 @@ struct SwipeCellModifier: ViewModifier {
}
}

func loadButtons(_ slot: SwipeCellSlot, position: SwipeCellSlotPosition, frame: CGRect)
-> some View
@ViewBuilder func loadButtons(_ slot: SwipeCellSlot, position: SwipeCellSlotPosition, frame: CGRect)
-> some View
{
let buttons = slot.slots

if slot.slotStyle == .destructive && leftOffset == -10000 && position == .left {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
let _ = DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
leftOffset = cellOffset(
i: buttons.count - 1,
count: buttons.count,
Expand All @@ -245,7 +249,7 @@ struct SwipeCellModifier: ViewModifier {
}

if slot.slotStyle == .destructive && rightOffset == 10000 && position == .right {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
let _ = DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
rightOffset = cellOffset(
i: buttons.count - 1,
count: buttons.count,
Expand All @@ -257,99 +261,96 @@ struct SwipeCellModifier: ViewModifier {
}

if slot.slotStyle == .destructive {
//单button的销毁按钮
if buttons.count == 1 {
return AnyView(
slotView(slot: slot, i: 0, position: position)
destructiveButtons(slot, position: position, frame: frame)
}
else {
ZStack {
ForEach(0..<buttons.count, id: \.self) { i in
if slot.slotStyle == .destructiveDelay && i == buttons.count - 1 {
slotView(slot: slot, i: i, position: position)
.offset(
x: showDalayButtonWith != 0
? showDalayButtonWith
: cellOffset(
i: i,
count: buttons.count,
position: position,
width: frame.width,
slot: slot
)
)
.zIndex(Double(i))
}
else {
slotView(slot: slot, i: i, position: position)
.offset(
x: cellOffset(
i: i,
count: buttons.count,
position: position,
width: frame.width,
slot: slot
)
)
.zIndex(Double(i))
}
}
}
}
}

@ViewBuilder private func destructiveButtons(_ slot: SwipeCellSlot, position: SwipeCellSlotPosition, frame: CGRect) -> some View {
let buttons = slot.slots
//单button的销毁按钮
if buttons.count == 1 {
slotView(slot: slot, i: 0, position: position)
.offset(
x: cellOffset(
i: 0,
count: buttons.count,
position: position,
width: frame.width,
slot: slot
)
)
}
else {
ZStack {
ForEach(0..<buttons.count - 1, id: \.self) { i in
slotView(slot: slot, i: i, position: position)
.offset(
x: cellOffset(
i: 0,
i: i,
count: buttons.count,
position: position,
width: frame.width,
slot: slot
)
)
)
}
else {
return AnyView(
ZStack {
ForEach(0..<buttons.count - 1, id: \.self) { i in
slotView(slot: slot, i: i, position: position)
.offset(
x: cellOffset(
i: i,
count: buttons.count,
position: position,
width: frame.width,
slot: slot
)
)
.zIndex(Double(i))
}
//销毁按钮
if slot.slotStyle == .destructive && position == .left {
slotView(slot: slot, i: buttons.count - 1, position: .left)
.zIndex(10)
.offset(x: leftOffset)

}
.zIndex(Double(i))
}
//销毁按钮
if slot.slotStyle == .destructive && position == .left {
slotView(slot: slot, i: buttons.count - 1, position: .left)
.zIndex(10)
.offset(x: leftOffset)

if slot.slotStyle == .destructive && position == .right {
slotView(slot: slot, i: buttons.count - 1, position: .right)
.offset(x: rightOffset)
.zIndex(10)
}

}
}
)
}
}
else {
if slot.slotStyle == .destructive && position == .right {
slotView(slot: slot, i: buttons.count - 1, position: .right)
.offset(x: rightOffset)
.zIndex(10)

return AnyView(
ZStack {
ForEach(0..<buttons.count, id: \.self) { i in
if slot.slotStyle == .destructiveDelay && i == buttons.count - 1 {
slotView(slot: slot, i: i, position: position)
.offset(
x: showDalayButtonWith != 0
? showDalayButtonWith
: cellOffset(
i: i,
count: buttons.count,
position: position,
width: frame.width,
slot: slot
)
)
.zIndex(Double(i))
}
else {
slotView(slot: slot, i: i, position: position)
.offset(
x: cellOffset(
i: i,
count: buttons.count,
position: position,
width: frame.width,
slot: slot
)
)
.zIndex(Double(i))
}
}
}
)
}
}
}

func offsetForSingleDestructiveButton(slot: SwipeCellSlot, position: SwipeCellSlotPosition) {
if slot.slotStyle == .destructive && slot.slots.count == 1 {
switch position {
case .left:
print("left")
DispatchQueue.main.async {
spaceWidth = 0
}
Expand Down Expand Up @@ -501,5 +502,4 @@ struct SwipeCellModifier: ViewModifier {
}
}
}

}
18 changes: 15 additions & 3 deletions Sources/SwipeCell/SwipeCellViewModifier2.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,18 @@ extension SwipeCellModifier {
.contentShape(Rectangle())
.gesture(getGesture())
.onAppear {
withAnimation(Animation.default.delay(initialOffsetResetDelay)) {
if resetOffsetOnAppear {
offset = 0
self.setStatus(status)
switch status {
case .showLeftSlot:
offset = leftSlotWidth
case .showRightSlot:
offset = rightSlotWidth
default:
break
}
DispatchQueue.main.asyncAfter(deadline: .now() + initialStatusResetDelay) {
if shouldResetStatusOnAppear {
resetStatus()
}
}
}
Expand Down Expand Up @@ -140,6 +149,7 @@ extension SwipeCellModifier {
timer.connect().store(in: &cancellables)
}

/// Set the status and associated values to ``CellStatus.showCell``
func resetStatus() {
status = .showCell
withAnimation(.easeInOut) {
Expand All @@ -152,6 +162,8 @@ extension SwipeCellModifier {
feedStatus = .none
cancellables.removeAll()
currentCellID = nil
// since we reset, we won't have to do it again
shouldResetStatusOnAppear = false

}

Expand Down
2 changes: 1 addition & 1 deletion Sources/SwipeCell/SwipeCellViewModifier3.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ extension SwipeCellModifier {
cancellables.removeAll() //只要移动,定时清零

// A gesture happened so don't reset
self.resetOffsetOnAppear = false
self.shouldResetStatusOnAppear = false

if currentCellID != cellID {
currentCellID = cellID
Expand Down
Loading

0 comments on commit 7c51a6c

Please sign in to comment.