With the continuous improvement of SwiftUI 2.0, I feel it’s time to make a major upgrade to my app. I’ve always wanted to implement an elegant side menu effect in my app similar to the iOS mail app, and I searched online for a solution. However, most of the implementations are for UIKit and there are not many project libraries that are well adapted to SwiftUI. I ended up implementing one myself in Xcode 12.
SwipeCell is a SwiftUI library developed with Swift 5.3. Its goal is to achieve the left and right swipe menu functionality similar to the iOS Mail app. SwipeCell requires XCode 12 and iOS 14.
Configuring Buttons
let button1 = SwipeCellButton(buttonStyle: .titleAndImage,
title: "Mark",
systemImage: "bookmark",
titleColor: .white,
imageColor: .white,
view: nil,
backgroundColor: .green,
action: {bookmark.toggle()},
feedback:true
)
// You can set buttons to any view to achieve more complex designs and dynamic effects
let button3 = SwipeCellButton(buttonStyle: .view, title:"",systemImage: "", view: {
AnyView(
Group{
if unread {
Image(systemName: "envelope.badge")
.foregroundColor(.white)
.font(.title)
}
else {
Image(systemName: "envelope.open")
.foregroundColor(.white)
.font(.title)
}
}
)
}, backgroundColor: .orange, action: {unread.toggle()}, feedback: false)
Configuring Slots
let slot1 = SwipeCellSlot(slots: [button2,button1])
let slot2 = SwipeCellSlot(slots: [button4], slotStyle: .destructive, buttonWidth: 60)
let slot3 = SwipeCellSlot(slots: [button2,button1],slotStyle: .destructiveDelay)
Assembly
cellView()
.swipeCell(cellPosition: .left, leftSlot: slot4, rightSlot: nil)
More configuration options
cellView()
.swipeCell(cellPosition: .both,
leftSlot: slot1,
rightSlot: slot1 ,
swipeCellStyle: SwipeCellStyle(
alignment: .leading,
dismissWidth: 20,
appearWidth: 20,
destructiveWidth: 240,
vibrationForButton: .error,
vibrationForDestructive: .heavy,
autoResetTime: 3)
)
Automatically dismiss when scrolling
For List
List{
...
}
.dismissSwipeCell()
For single cell in ScrollView
ScrollView{
VStack{
Text("Mail Title")
.dismissSwipeCellForScrollView()
Text("Mail Content")
....
}
.frame(maxWidth:.infinity,maxHeight: .infinity)
}
.swipeCell(cellPosition: .both, leftSlot: leftSlot, rightSlot: rightSlot,clip: false)
For LazyVStack in ScrollView
ScrollView{
LazyVStack{
ForEach(lists,id:\.self){ item in
Text("Swipe in scrollView:\(item)")
.frame(height:80)
.swipeCell(cellPosition: .both, leftSlot:slot, rightSlot: slot)
.dismissSwipeCellForScrollViewForLazyVStack()
}
}
dismissSwipeCell
supports selection in editmodedismissSwipeCellForScrollView
is used for ScrollView, typically for scenarios with only one cell, such as displaying email content in Mail. Refer to the demo for a demonstrationdismissSwipeCellForScrollViewForLazyVStack
is used for ScrollView with LazyVStack. Sometimes it may interrupt the swipe menu animation. Personally, it is better to use List instead of LazyVStack unless there is a special need.
Due to SwiftUI’s lack of a good solution to get the scrolling status, the above functions are implemented using Introspect.
For the destructiveDelay
form of button, you need to add dismissDestructiveDelayButton()
in the action to ensure the cell resets after the action is executed.
Current Issues
- Animation details are still lacking
- Limitations in EditMode
Welcome Your Valuable Feedback
SwipeCell is available under the MIT license.