简体   繁体   English

SwiftUI zIndex inside List

[英]SwiftUI zIndex inside List

The zIndex property on a view inside a ForEach inside List does not seem to work whereas if you have zIndex inside a ForEach inside a ScrollView , it does. ListForEach内的视图上的zIndex属性似乎不起作用,而如果您在ScrollView内的 ForEach 内有zIndex ,它就可以了。

Does not work for me:对我不起作用:

List {
    ForEach { index
       View()
          .zIndex(index == 1 ? 1 : 0)
    }
}

Works:作品:

VStack {
    ScrollView {
        ForEach { index
           View()
              .zIndex(index == 1 ? 1 : 0)
        }
    }
}

Does anyone have an idea why?有谁知道为什么?

It seems zIndex is not working inside List in SwiftUI (even SwiftUI 2).似乎 zIndex 在SwiftUI (甚至 SwiftUI 2)中的List内不起作用。 One workaround could be to introspect the UITableViewCell and change its zPosition of the layer, Like the following;一种解决方法可能是自省UITableViewCell并更改其层的zPosition ,如下所示;

 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;然后创建 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第二行在第一行之后,因为第一行现在具有更高的 zIndex

Answer is inspired from this answer答案的灵感来自这个答案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM