Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
import SwiftUI
/// Reads the width of the selection box next to a List row when editing mode is .active
///
/// Note: On iOS 15 the listRowInsets do not respond to updates so if you want to offset
/// the cell you should use negative leading padding.
public struct ListSelectionBoxWidthReader<Content: View>: View {
@State private var boxWidth: CGFloat = 0
private var content: (CGFloat) -> Content
public init(@ViewBuilder content: @escaping (CGFloat) -> Content) {
self.content = content
}
public var body: some View {
content(boxWidth).background(
GeometryReader { listGeometry in
List {
ForEach([0], id: \.self) { _ in
GeometryReader { cellGeometry in
HStack {
let listX = listGeometry.frame(in: .global).origin.x
let cellX = cellGeometry.frame(in: .global).origin.x
Rectangle().onAppear {
self.boxWidth = cellX - listX
}.onChange(of: cellX - listX) { newWidth in
self.boxWidth = newWidth
}
Spacer()
}
}
}
.onMove(perform: { _, _ in })
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
}
.opacity(0)
.disabled(true)
.frame(height: 1) // iOS 15 fix: 0 height does not work so we hide and disable
}
)
}
}
/// View with editMode active and the selection box hidden
struct ExampleView: View {
var items = ["a", "b", "c"]
var body: some View {
ListSelectionBoxWidthReader { selectionBoxWidth in
List {
ForEach(items, id: \.self) { item in
Text(item)
.padding(.leading, -selectionBoxWidth)
}
.onMove(perform: { _, _ in })
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
}
}
.environment(\.editMode, .constant(.active))
.listStyle(PlainListStyle())
}
}
@Amzd
Copy link
Author

Amzd commented May 25, 2022

Make sure to change the editMode on the ListSelectionBoxWidthReader and not just on the inner List.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment