It seems zIndex is not working inside List in SwiftUI (even SwiftUI 2). One workaround could be to introspect the UITableViewCell and change its zPosition of the layer, Like the following;
var body: some View {
List {
Text("First Row")
.background(Color.green)
.padding()
.listRowZIndex(1)
Text("Second Row")
.background(Color.red)
.padding()
.listRowZIndex(0)
.offset(x: 0, y: -30)
}
}
Then create the ViewModifier ;
struct ListRowZIndex: ViewModifier {
@State var zIndex : CGFloat = 0.0
func body(content: Content) -> some View {
content.background(ListRowZindexHelperView(zIndex: zIndex))
}
}
extension View {
func listRowZIndex(_ index: CGFloat = 0.0) -> some View {
self.modifier(ListRowZIndex(zIndex: index))
}
}
Required implementation;
struct ListRowZindexHelperView: UIViewRepresentable {
let zIndex : CGFloat
let proxy = ListRowZindexHelperProxy(cellWrapper: UITableViewCellWrapper(cell: UITableViewCell()))
func makeUIView(context: Context) -> UIView {
return UIView()
}
func updateUIView(_ uiView: UIView, context: Context) {
proxy.catchUITableViewCell(for: uiView)
proxy.chnageZIndex(zIndex)
}
}
class ListRowZindexHelperProxy {
var uiTableViewCellWrapper: UITableViewCellWrapper
init(cellWrapper: UITableViewCellWrapper) {
uiTableViewCellWrapper = cellWrapper
}
func catchUITableViewCell(for view: UIView) {
if let cell = view.enclosingUITableViewCell() {
uiTableViewCellWrapper.uiTableViewCell = cell
}
}
func chnageZIndex(_ zIndex: CGFloat = 0.0) {
uiTableViewCellWrapper.uiTableViewCell.layer.zPosition = zIndex
}
}
class UITableViewCellWrapper {
var uiTableViewCell : UITableViewCell
init(cell: UITableViewCell) {
uiTableViewCell = cell
}
}
extension UIView {
func enclosingUITableViewCell() -> UITableViewCell? {
var next: UIView? = self
repeat {
next = next?.superview
if let asUITableViewCell = next as? UITableViewCell {
return asUITableViewCell
}
} while next != nil
return nil
}
}
Result;
Preview
The Second row goes behind the first row since first row has a higher zIndex now
Answer is inspired from this answer