【问题标题】:SwiftUI Remove List padding fand Row spacing?SwiftUI 删除列表填充和行间距?
【发布时间】:2021-03-10 12:17:01
【问题描述】:

我正在尝试删除列表行的间距和填充,在花费数小时尝试多种解决方案后它无法正常工作。

列表视图:

import SwiftUI

struct Item {
    let uuid = UUID()
    let value: String
}

struct w_tasks: View {
    
    @State private var items = [Item]()
      
   
      var body: some View {
          ZStack(alignment: .leading){
                    List(self.items, id: \.uuid) {item in
                        cl_task().listRowInsets(EdgeInsets())
                    }
                    .listStyle(SidebarListStyle())
                    .frame(width: UIScreen.main.bounds.width )
                    .onAppear {
                      
                        DispatchQueue.main.async {
                            self.items.append(Item(value: "Item"))
                            self.items.append(Item(value: "Item"))
                            self.items.append(Item(value: "Item"))
                            self.items.append(Item(value: "Item"))
                            self.items.append(Item(value: "Item"))
                            self.items.append(Item(value: "Item"))
                            self.items.append(Item(value: "Item"))
                            self.items.append(Item(value: "Item"))
                            self.items.append(Item(value: "Item"))
                            self.items.append(Item(value: "Item"))
                            self.items.append(Item(value: "Item"))
                            self.items.append(Item(value: "Item"))
                        }
               
                    }
              VStack {
                  Spacer()

                  HStack {
                      Spacer()

                      Button(action: {
                          self.items.append(Item(value: "Item"))
                      }, label: {
                          Text("+")
                          .font(.system(size: 30))
                          .frame(width: 50, height: 50)
                          .foregroundColor(Color.white)
                          .padding(.bottom, 5)
                      })
                      .background(Color(hex : "#216D94"))
                      .frame(width: 50, height: 50)
                      .cornerRadius(25)
                      .padding()
                      .shadow(color: Color.black.opacity(0.3),
                              radius: 3,
                              x: 3,
                              y: 3)
                  }
              }
          }.background(Color.black)
      }
}

struct w_tasks_Previews: PreviewProvider {

    static var previews: some View {
        w_tasks()
    }
}

行咬:

import SwiftUI

struct cl_task: View {
    @State private var offset: CGSize = .zero
  
    var body: some View {
        //Swipe to custom options ,by "Jack" this option not yet available in SwiftUI
        let drag = DragGesture(minimumDistance: 25, coordinateSpace: .local)
       
                   .onChanged {
                    
                    if (self.offset.width > 0 ){  return }
                    self.offset.width = $0.translation.width
                
                   }.onEnded {
                   if $0.translation.width < -100 {
                       self.offset = .init(width: -100, height: 0)
                   } else {
                      self.offset = .zero
                   }
               }
        ZStack{
            Rectangle().foregroundColor(.blue).offset(x: offset.width, y: offset.height)
                .gesture(drag)
                .animation(.easeIn, value: offset)
            Text("test").foregroundColor(.white)
        }.frame(minWidth: 0,
                maxWidth: .infinity,
                minHeight: 120,
                maxHeight: .infinity,
                alignment: .topLeading
        )
    }
}

struct cl_task_Previews: PreviewProvider {
    static var previews: some View {
        cl_task().previewLayout(.sizeThatFits)
    }
}

当我在NavigationView 中添加List 时,分隔线再次显示,我无法删除它,不知道为什么!

【问题讨论】:

  • 你为什么使用 DispatchQueue.main.async { ?因为您可以只使用 items.append(Item(value: "Item")) 来增加价值。为什么是 DispatchQueue?
  • 我确实尝试过查看行之间的分隔符是否从主线程返回,但它返回是因为我添加了 NavigationView
  • 您可以通过不使用 List 来解决问题,如果没问题我可以提供帮助
  • @swiftPunk ,如果数组有超过 400 个元素会影响性能怎么办?
  • 我发布我的答案是为了解决我在您的代码中发现的所有问题

标签: list swiftui


【解决方案1】:

为了测试显示海量数据没有问题,我预加载了10_000行。够了吗?

您的问题:

1.你应该让你的项目类型可识别,然后你可以从你的列表或 ForEach 中取出 uuid。

2.你不应该给你的行指定帧大小,它们会自动占用最大空间。

3.你可以把你的按钮放在你的视图上,像我一样节省更多的编码。

4. 你不应该使用 CGSize 作为偏移量,因为你只是在处理一个维度,CGFloat 就足够了。

5.如果你的数据量很大,你应该也必须使用 LazyVStack,正如你所说的 400 对很多,那么肯定使用 LazyVStack。


struct Item: Identifiable {

  let id: UUID = UUID()
  let value: String

}

struct ContentView: View {
    
    @State private var items: [Item] = [Item]()
    
    var body: some View {
        
        ZStack {
            
            Color.black.ignoresSafeArea()
            
            ScrollView {
                LazyVStack(spacing: 0) {
                    
                    ForEach(items) {item in
                        
                        RowView(stringOfText: item.value)
                            .frame(height: 120)
                    }
                    
                }
                
            }
            .background(Color.black)
            .onAppear() { for _ in 0...10_000 { addNewData() } }
            
            
            
        }
        .overlay(addButton, alignment: .bottomTrailing)
        .animation(.easeInOut)
        
    }
    
    var addButton: some View {
        
        Button(action: { addNewData() }, label: {
            Image(systemName: "plus.circle").foregroundColor(Color.white).font(Font.largeTitle.weight(Font.Weight.bold)).padding()
        })
        
        
    }
    
    func addNewData() { items.append(Item(value: "item " + items.count.description)) }
}

struct RowView: View {
    
    let stringOfText: String
    
    @State private var offset: CGFloat = CGFloat()
    
    var body: some View {
        
        ZStack {
            
            Color.blue
            
            Text(stringOfText)
                .foregroundColor(Color.white)
                .padding()
        }
        .offset(x: offset)
        .gesture(dragGesture)
        
    }
    
    var dragGesture: some Gesture {
        
        DragGesture(minimumDistance: 25, coordinateSpace: .local)
            
            .onChanged {
                if (offset > 0 ){  return }
                offset = $0.translation.width
                
            }.onEnded {
                if $0.translation.width < -100 {
                    offset = -100
                } else {
                    offset = 0
                }
            }
        
    }
  
}

【讨论】:

    【解决方案2】:

    这就是我所拥有的

    您尝试的方法将起作用,但不适用于列表,将 ForEach 嵌套在列表中,然后附加该修饰符,您应该会很好。当然,当然也可以根据自己的喜好调整修饰符。

    此外,从列表行之间获取间距的方法是对它们设置高度限制。我只是设置了 50,但再次,根据您的需要进行修改。

        struct Item {
        let uuid = UUID()
        let value: String
    }
    
    struct w_tasks: View {
        
        @State private var items = [Item]()
          
       
          var body: some View {
              ZStack(alignment: .leading){
               // List(self.items, id: \.uuid)
                        List {
                            ForEach(self.items, id: \.uuid) { item in
                                cl_task().listRowInsets(EdgeInsets(.init(top: 20, leading: -20, bottom: 20, trailing: -20)))
                                
                                .frame(height: 50)
                            }
                                
                        }
                        .listStyle(InsetListStyle())
                        
                        
                        .frame(width: UIScreen.main.bounds.width )
                        .onAppear {
                          
                            DispatchQueue.main.async {
                                self.items.append(Item(value: "Item"))
                                self.items.append(Item(value: "Item"))
                                self.items.append(Item(value: "Item"))
                                self.items.append(Item(value: "Item"))
                                self.items.append(Item(value: "Item"))
                                self.items.append(Item(value: "Item"))
                                self.items.append(Item(value: "Item"))
                                self.items.append(Item(value: "Item"))
                                self.items.append(Item(value: "Item"))
                                self.items.append(Item(value: "Item"))
                                self.items.append(Item(value: "Item"))
                                self.items.append(Item(value: "Item"))
                            }
                   
                        }
                  VStack {
                      Spacer()
    
                      HStack {
                          Spacer()
    
                          Button(action: {
                              self.items.append(Item(value: "Item"))
                          }, label: {
                              Text("+")
                              .font(.system(size: 30))
                              .frame(width: 50, height: 50)
                              .foregroundColor(Color.white)
                              .padding(.bottom, 5)
                          })
                          .background(Color("#216D94"))
                          .frame(width: 50, height: 50)
                          .cornerRadius(25)
                          .padding()
                          .shadow(color: Color.black.opacity(0.3),
                                  radius: 3,
                                  x: 3,
                                  y: 3)
                      }
                  }
              }.background(Color.black)
          }
    }
    
    struct w_tasks_Previews: PreviewProvider {
    
        static var previews: some View {
            w_tasks()
        }
    }
    
    
    
    struct cl_task: View {
        @State private var offset: CGSize = .zero
      
        var body: some View {
            //Swipe to custom options ,by "Jack" this option not yet available in SwiftUI
            let drag = DragGesture(minimumDistance: 25, coordinateSpace: .local)
           
                       .onChanged {
                        
                        if (self.offset.width > 0 ){  return }
                        self.offset.width = $0.translation.width
                    
                       }.onEnded {
                       if $0.translation.width < -100 {
                           self.offset = .init(width: -100, height: 0)
                       } else {
                          self.offset = .zero
                       }
                   }
            ZStack{
                Rectangle().foregroundColor(.blue).offset(x: offset.width, y: offset.height)
                    .gesture(drag)
                    .animation(.easeIn, value: offset)
                Text("test").foregroundColor(.white)
            }.frame(minWidth: 0,
                    maxWidth: .infinity,
                    minHeight: 120,
                    maxHeight: .infinity,
                    alignment: .topLeading
            )
        }
    }
    
    struct cl_task_Previews: PreviewProvider {
        static var previews: some View {
            cl_task().previewLayout(.sizeThatFits)
        }
    }
    

    【讨论】: