在SwiftUI中,从列表中移除顶部填充

32
我在Stack Overflow上看到过类似的问题,但是没有一个能够回答我的问题。
我创建了一个List,但是我想要移除List中内容上方带有空白边距(用红色箭头标记)的部分。当使用GroupedListStyle时,如何移除它?

Screenshot

这是一个在NavigationView中通过fullscreenCover显示的VStack中的List

var body: some View {
  NavigationView {
    VStack {
      taskEventPicker
      myList
    }
    .navigationBarTitle("Add Task", displayMode: .inline)
  }
}

这里的taskEventPicker是一个分段式Picker(用绿色方框标注):

var taskEventPicker: some View {
  Picker("Mode", selection: $selection) { /* ... */ }
  .pickerStyle(SegmentedPickerStyle())
  .padding()
}

\{\{myList\}\}是需要讨论的表格(用黄色框起来):

var myList: some View {
  List { /* ... */ }
  .listStyle(GroupedListStyle())
}

我尝试过的方法

注意:我正在寻找适用于GroupedListStyle的答案。我知道这个问题在PlainListStyle中不会出现。这个填充问题也会出现在默认的listStyle中。

感谢您的帮助!

Xcode 版本:12.5

8个回答

33

首先,我想说 GroupedListStyle 已经正常工作。

在iOS上,分组列表样式相比纯样式显示更大的标题和页脚,视觉上将不同部分的成员隔离开来。

你说你已经尝试过了,但是对我来说可以正常工作(Xcode 12.5.1):

    List { ... }    
    .onAppear(perform: {
        UITableView.appearance().contentInset.top = -35
    })

你也可以使用ZStack,将列表放在堆栈底部,并将Picker放在其上方来隐藏列表头。Picker确实具有透明度,因此您还需要添加不透明视图作为Picker的背景。

var body: some View {
    NavigationView {
        ZStack(alignment: .top) {
            List { ... }
            .listStyle(.grouped)
            .padding(.top, 30)
            
            Color.white
                .frame(height: 65)
            
            Picker { ... }
            .pickerStyle(.segmented)
            .padding()
        }
        .navigationBarTitle("Add Task", displayMode: .inline)
    }
}

enter image description here

就我所看到的,这似乎与PlainListStyle没有什么区别,但我猜你想使用GroupedListStyle一定有特殊原因。

1
一个很棒的解决方案!谢谢@rbaldwin!我甚至没有想到使用带有picker的ZStack - Ben Myers
5
如果有人跟发帖者不一样,并且在代码中没有指定任何样式,那么添加显式的.listStyle(PlainListStyle())可以有效地解决他们列表顶部不需要的空间问题。但请注意,这种方法不能解决发帖者的问题,因为他需要保留GroupedListStyle样式。 - ConfusionTowers
这在Xcode 13和iOS 15.5上对我不起作用。 - Gavin Morrow
这对我有效:List {...}.padding(.top, -20) 没有 ZStack 等等... - PAULMAX
在当前的iOS版本中,你必须使用UICollectionView.appearance().contentInset.top = -35,因为List现在是一个UICollectionView的底层实现。 - Radu Ursache

5

我有一个类似的设置,其中在 VStack 中放置了一些视图和一个列表,并且在我的列表顶部出现了不必要的空白。在我的情况下,我需要将 VStack 的间距设置为 0,这解决了问题,因为它实际上只是来自 VStack 的间距。

VStack(spacing: 0) { ... }

我以为我已经检查了所有的Stacks,但显然我在UI结构中找到了一个LazyVStack(似乎与我的问题无关)。当我将我的LazyVStack设置为0间距时,问题消失了。谢谢! - jason d

4

接受答案的contentInsent部分在大多数情况下都能正常工作,但是在我这种情况下,当你想在一个包含设置为.inlinenavigationBarTitleDisplayModeList的详细视图中使用它时,在导航栈的末尾,当返回到使用另一个设置为.largeList的视图时,List内容和NavigationBar会非常混乱。无论navigationBarTitleDisplayMode设置成什么,它们可能也会这样做。

在我的情况下,切换到listStyle(.plain)不是可行的选择,因为在详细视图中,我会失去内置过渡到和从List的EditMode的美丽动画效果,这似乎只存在于分组的listStyle品种中。

最后,在经过几天的挫败后,我发现tableHeaderView是解决我的问题的最佳方法 - 当然,它同样适用于解决原始问题。所有的解决方案都在这里...

XCode文档

... 以及以下这句话:

"当将视图分配给该属性[即tableHeaderView]时,请将该视图的高度设置为非零值"

所以我会像这样做:

List {
  // bla bla bla
}
.listStyle(.grouped)
.onAppear {
  let tableHeaderView = UIView(frame: .zero)
  tableHeaderView.frame.size.height = 1
  UITableView.appearance().tableHeaderView = tableHeaderView
}

就是这么简单。希望它也能对你有所帮助!


@Niels,自从List不再基于UITableView实现后,它在iOS 16上已经无法工作了,你有什么解决方法吗? - Claudiu
你好Claudiu,非常抱歉回复晚了。我必须承认我太愚蠢了,没有预料到会有任何问题。我保证以后会更加注意。确实,它不再起作用了,但是在iOS 16中,我发现自己非常喜欢普通列表样式的动画效果,从editMode到普通模式的切换。这就是为什么我没有寻找其他解决方法,而是决定将我的列表配置为普通列表样式。 - Niels

4

为列表中的第一个部分添加标题:Section(header: Spacer(minLength: 0))

免责声明:虽然这并不能完全消除顶部间距,但确实可以得到与原生“设置”应用程序相同的结果。

注意:此方法已在 iOS 14.5 上测试成功。

VStack {
    List {
        Section(header: Spacer(minLength: 0)) {
            Text(verbatim: "First Section")
        }

        Section {
            Text(verbatim: "Second Section")
        }
    }
    .listStyle(GroupedListStyle())
}

Without Section Header With Section Header Native Settings App


最佳答案,不要使用UITableView进行黑客攻击。 - timbre timbre
iOS16这个已经不再起作用了。 - Peter Lapisu

3

另一个选项是添加

List { ... }.offset(x: 0, y: -30).edgesIgnoringSafeArea(.bottom)

到列表中。由于使用此选项时无法将其滚动到顶部,因此在列表底部添加 Spacer(minLength: 30)


1
为列表和间隔添加顶部填充,并为第一个分区标题设置最小长度为0。
NavigationView {
    List { 
       Section {
         Text("My Header")
       } header: {
            Spacer(minLength: 0)
    }
    .listStyle(.grouped)
    .padding(.top, -20)
}
.navigationBarTitleDisplayMode(.inline)

}


-1
extension View {
    /// Clear tableview and cell color
    func tableClearColor() {
        let tableHeaderView = UIView(frame: .zero)
        tableHeaderView.frame.size.height = 0.5
        UITableView.appearance().tableHeaderView = tableHeaderView
    }
}

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接