如何在SwiftUI中的列表元素之间自动添加分隔线?

时间:2020-10-27 10:30:00

标签: swiftui

我正在尝试复制List的某些行为。我特别想在所有元素之间添加分隔线。我当前的代码如下:

Customlist {
  Text("...")
  Divider()
  Text("...")
  Divider()
  Text("...")
}

我想删除分隔线,只提供文本节点,但是我不知道如何在Customlist中自动插入分隔线。所以我想要的用法是这样的:

Customlist {
  Text("...")
  Text("...")
  Text("...")
}

我认为Customlist必须看起来像这样(但我不知道如何实现body):

Customlist<Content: View>: View {
  var content: Content

  init(@ViewBuilder _ b: () -> Content) {
    self.content = b()
  }

  var body: some View {
    // Something using self.content here
  }
}

2 个答案:

答案 0 :(得分:0)

import SwiftUI
struct ParentView: View  {
    let array = [1,2,3,4,5]
    var body: some View {
        DividedList{
            VStack{
                //The next init for List would implement something like this
                ForEach(array, id: \.self) { elem in
                    VStack{
                        Text(elem.description)
                        
                        if elem.description != array.last?.description{
                            Divider()
                        }
                    }
                }
            }
        }
    }
}
struct DividedList<Content: View>: View {
    
    
    var content: Content
    //This is just the first init for the SwiftUI.List if you want the rest you have to implement them individually 
      //https://developer.apple.com/documentation/swiftui/list
      init(@ViewBuilder _ b: () -> Content) {
        self.content = b()
      }
    
    var body: some View {
        content
    }
}

struct DividedList_Previews: PreviewProvider {
    static var previews: some View {
        //DividedList({Text("test")})
        ParentView()
    }
}

答案 1 :(得分:0)

  1. Row 发送 rowID(使用 PreferenceKey)到列表。
  2. List 获取所有行的 id,并将最后一个 id 发送到行。
  3. 行检查 self'id 等于最后一行 id。
/// store all row ids.
fileprivate struct RowsPreferenceKey: PreferenceKey {
    static var defaultValue: [Namespace.ID] = []
    static func reduce(value: inout [Namespace.ID], nextValue: () -> [Namespace.ID]) {
        value.append(contentsOf: nextValue())
    }
}

extension EnvironmentValues {
    
    fileprivate struct LastRowKey: EnvironmentKey {
        static var defaultValue: Namespace.ID? = nil
    }
    
    /// identity this row id, is last item in list
    var lastRowID: Namespace.ID? {
        get { self[LastRowKey.self] }
        set { self[LastRowKey].self = newValue }
    }
}

struct Row<Content: View>: View {
    
    @Environment(\.lastRowID) var lastRowID
    @Namespace var id
    
    var content: Content
    
    init(@ViewBuilder content: () -> Content) {
        self.content = content()
    }
    
    var body: some View {
        VStack {
            content
            // check self is last row
            if lastRowID != id {
                Divider()
            }
         // send row id to list.
        }.preference(key: RowsPreferenceKey.self, value: [id])
    }
    
}


struct DividerList<Content: View>: View {
    
    var content: Content
    
    init(@ViewBuilder content: () -> Content) {
        self.content = content()
    }
    
    @State var lastRowID: Namespace.ID?
    
    var body: some View {
        VStack { content }
        .onPreferenceChange(RowsPreferenceKey.self, perform: { value in
            self.lastRowID = value.last
        })
        /// send row id to Childs
        .environment(\.lastRowID, lastRowID)
    }
    
}

struct DividerList_Previews: PreviewProvider {
    static var previews: some View {
            DividerList {
                Row {
                    Text("Hello")
                }
                
                Row {
                    Text("World")
                }
                
                Row {
                    Text("!!!")
                }
            }
    }
}


preview