【问题标题】:How to remove List Separator lines in SwiftUI 2.0 in iOS 14 and above如何在 iOS 14 的 SwiftUI 2.0 中删除列表分隔符行
【发布时间】:2020-10-17 05:13:42
【问题描述】:

所以问题很简单,就在标题中。我想删除 SwiftUI iOS 14 中的行分隔符。以前,我正在使用 UITableView().appearance().separatorStyle = .none 这曾经在 iOS 13 中完成这项工作。但是现在,它不起作用。有关如何使其工作的任何更新或想法。谢谢:)

【问题讨论】:

  • 好吧,下面没有UITableView...没有更多的废话了))
  • @SchmidtyApps 发布了一个我已经确认有效的解决方案!但是答案被版主删除了,我无法取消删除。见github.com/SchmidtyApps/SwiftUIListSeparator
  • @Asperi 你是什么意思下面没有更多的 UITableView - 还有一个

标签: xcode list swiftui separator ios14


【解决方案1】:

这是一个可能解决方案的演示。使用 Xcode 12b 测试。

List {
    ForEach(0..<3) { _ in
        VStack {
            Text("Hello, World!").padding(.leading)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
        .listRowInsets(EdgeInsets())
        .background(Color.white)
    }
}

【讨论】:

  • 使用Color(UIColor.systemBackground)) 代替Color.white?
  • 此外,在某些情况下,您可能希望应用负边缘插图。 .listRowInsets(EdgeInsets(.init(top: -1, leading: -1, bottom: -1, trailing: -1))).
  • 如何在不修改插图的情况下做到这一点?删除所有填充会使列表看起来很糟糕。
  • @JordanH 可以将列表样式设置为.listStyle(InsetListStyle())
  • 喜欢这个解决方案,它在模拟器(XCode 12,运行 iOS 13 和 14)上运行良好,但是,它不适用于我的实际设备(iPhone XS,iOS 14.2)。由于某种奇怪的原因,列表分隔符都出现了。其他人也面临同样的情况吗?
【解决方案2】:

我如何制作一个适用于 iOS 14 和 iOS 13 的列表,它没有显示分隔符和额外边距

struct NoButtonStyle: ButtonStyle {
    func makeBody(configuration: Self.Configuration) -> some View {
        configuration.label
    }
}

struct ListWithoutSepatorsAndMargins<Content: View>: View {
        let content: () -> Content
    
        var body: some View {
            if #available(iOS 14.0, *) {
                ScrollView {
                    LazyVStack(spacing: 0) {
                        self.content()
                    }
                    .buttonStyle(NoButtonStyle())
                }
            } else {
                List {
                    self.content()
                }
                .listStyle(PlainListStyle())
                .buttonStyle(NoButtonStyle())
            }
        }
    }

示例用法 -

ListWithoutSepatorsAndMargins {
    ForEach(0..<5) { _ in
      Text("Content")
    }
}

如果列表中有更多组件,请将它们包装在组中

                ListWithoutSepatorsAndMargins {
                    Group {
                            self.groupSearchResults()
                            self.myGroups()
                            self.exploreGroups()
                        }
                    }
                }

    

希望这对某人有所帮助,我在这些小事上浪费了很多时间,Apple 正在努力推动我们使用 LazyVStack,看来

【讨论】:

  • 此解决方案是有害的,因为 LazyVStack 以与 List 完全不同的方式处理单元格。您可以在滚动这些单元格时检查 CPU 负载。如果单元格不仅仅是文本(“hello test”),您将在滚动时看到峰值负载
  • CPU 使用率在滚动时会上升一点,但随着事情的稳定会立即回落,这在 UITableView 中也曾经发生过,我的应用程序中有相当大的单元格和非常大的列表,它从来没有导致滚动延迟或崩溃,到目前为止我们没有发现任何问题,但使用风险自负!
  • @Lonkly 为什么你认为这可能是个问题?
  • @Zapko 你怎么看,UIKit 中 StackView 和 TableView 的主要区别是什么? List 和 LazyVStack 也一样。 TableView 重用单元格,LazyVStack 没有。因此,当您有更多适合屏幕的元素,并且布局比 Text("Content") 更复杂时,您将变得极其缓慢和滞后。因此,提供名为 ListWithoutSeparators{} 的解决方案并使其内部成为 LazyVStack 是非常有害的。
  • 使用惰性 vstack 你会失去其他 List 的好处,比如编辑状态、滑动删除手势等。
【解决方案3】:

将@asperi、@akmin 和@zrfrank 答案合并为一件事。根据我的经验,ListLazyVStack 更可靠、更高效,所以我仍然使用List 来处理任何需要可靠性的复杂问题。

extension View {
    func listRow() -> some View {
        self.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
            .listRowInsets(EdgeInsets(top: -1, leading: -1, bottom: -1, trailing: -1))
            .background(Color(.systemBackground))
    }
}

List {
    Color.red
         .listRow()


    Color.green
         .listRow()
}

【讨论】:

  • LazyVStack 不适合如果你想有列表部分。
  • 这对我有用。列表 + 一些视图(不是 LazyVStack)
  • 在 iOS 14 上它就像一个魅力!没有 LazyVStack,只有 List + view。谢啦!我快疯了!
【解决方案4】:

我在 Apple 开发者论坛上找到了这个简单的解决方案。它在 14.4 对我有用:

List {
   ...
}.listStyle(SidebarListStyle())

这似乎在边缘添加了一点点填充。如果这对您来说是个问题,您可以尝试一些负填充。

【讨论】:

  • 我认为这是目前最好的解决方案,非常优雅!
【解决方案5】:

基于average Joe's answer 我最终得到了以下修饰符:

struct ListSeparatorNone: ViewModifier {

    var backgroundColor: Color = Color(.systemBackground)
    
    func body(content: Content) -> some View {
        content
            .listRowInsets(EdgeInsets(top: -1, leading: 0, bottom: 0, trailing: 0))
            .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
            .background(backgroundColor)
    }
}

视图扩展:

extension View {
    func listSeparatorNone(backgroundColor: Color = Color(.systemBackground)) -> some View {
        self.modifier(ListSeparatorNone(backgroundColor: backgroundColor))
    }
}

使用示例:

List {
    ForEach(viewModel.countries, id: \.self) { country in
        Text(country)
            .padding(.leading, 10)
    }
    .listSeparatorNone()
}

【讨论】:

    【解决方案6】:

    iOS 15:

    今年 Apple 推出了一个新的修饰符 .listRowSeparator,可用于设置分隔符的样式。你可以通过.hidden来隐藏它:

    List(items, id:\.self) {
        Text("Row \($0)")
            .listRowSeparator(.hidden)
    }
    

    ? 您还可以通过设置listRowSeparatorTintColor 将每个分隔符设置为任何颜色,正如我提到的here in this answer

    【讨论】:

      【解决方案7】:

      如果您没有很多单元格,因此不需要依赖 LazyVStack 来获得性能,您可以回退到 ScrollView + VStack:

      ScrollView {
        VStack {
          Row1()
          Row2()
          Row3()
        }
      }
      

      【讨论】:

        【解决方案8】:

        您也可以在 VStack 的末尾(即 List 内部)调用此函数。

        这将是 iOS 14 上列表分隔符的叠加层 :)

        private func hideDefaultListSeperator() -> some View {
            Rectangle()
                .fill(colorScheme == .light ? Color.white : Color.black)
                .frame(maxHeight: 1)
        }
        

        【讨论】:

          【解决方案9】:

          更新:

          我想出了一个适用于 iOS 13 和 iOS 14 的解决方案,并提供了一个简单的列表并在两个 iOS 上都使用 List。

          struct ListWithoutSepatorsAndMargins<Content>: View where Content: View {
              let content: () -> Content
          
              init(@ViewBuilder content: @escaping () -> Content) {
                  self.content = content
              }
          
              var body: some View {
                  List {
                      self.content()
                          .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
                          .listRowInsets(EdgeInsets())
                          .background(Color.white)
                  }
                  .listStyle(PlainListStyle())
                  .buttonStyle(NoButtonStyle())
              }
          }
          
          struct NoButtonStyle: ButtonStyle {
              func makeBody(configuration: Self.Configuration) -> some View {
                  configuration.label
              }
          

          并在 SceneDelegate.swift 中执行以下操作以删除单元格的默认灰色选择

          func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
              UITableView.appearance().separatorStyle = .none
              UITableView.appearance().allowsSelection = false
             .......
          

          我们可以通过以下方式使用它

          ListWithoutSepatorsAndMargins {
              ForEach(0..<5) { _ in
                Text("Content")
              }
          }
          
          ListWithoutSepatorsAndMargins {
               Group {
                  self.groupSearchResults()
                  self.myGroups()
                  self.exploreGroups()
               }
            }
          }
          

          【讨论】:

          • 我们应该在哪里找到SceneDelegate
          • 在您的应用启动时添加它,即执行的第一段代码
          • 在更高版本的 ios 中,我得到了单元格之间的默认间距,可以通过执行以下操作将其删除
          • List { self.content() .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) .listRowInsets(EdgeInsets()) .background(Color.white) } .listStyle(PlainListStyle()) .buttonStyle(NoButtonStyle()) .environment(\.defaultMinListRowHeight, 1)
          • 上一个解决方案中的额外.environment(\.defaultMinListRowHeight, 1)
          【解决方案10】:

          这是我的 iOS 14 解决方案:

          struct MyRowView: View {
            var body: some View {
              ZStack(alignment: .leading) {
                // Background color of the Row. It will spread under the entire row.
                Color(.systemBackground)
                NavigationLink(destination: Text("Details")) {
                  EmptyView()
                }
                .opacity(0) // Hide the Disclosure Indicator
          
                Text("Go to Details").padding(.leading)
              }
              // These 2 lines hide the row separators
              .padding(.horizontal, -16) // Removes default horizontal padding
              .padding(.vertical, -6)    // Removes default vertical padding
            }
          }
          

          封闭的列表应该有这个修饰符

          .listStyle(PlainListStyle())

          与使用 LazyVStack 相比,此解决方案的优势在于您仍然可以使用 List 的编辑功能。

          不幸的是,此解决方案依赖于硬编码值来删除每行上的系统默认填充。希望 SwiftUI 3.0 将提供简单的 .separatorStyle(.none) 和 .accessoryType(.none) 修饰符。

          去除Disclosure Indicators的代码来自:https://www.appcoda.com/hide-disclosure-indicator-swiftui-list/

          【讨论】:

            【解决方案11】:

            上面的答案对我有用,你只需要在这两个函数下面设置:

            .listRowInsets(EdgeInsets())

            .background(Color.white)

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2019-10-23
              • 1970-01-01
              • 1970-01-01
              • 2019-10-26
              • 2016-01-21
              • 2023-04-09
              • 2019-10-23
              相关资源
              最近更新 更多