Search code examples
swiftuiswiftui-list

SwiftUI reduce spacing of rows in a list to null


I want to reduce the linespacing in a list to null.

My tries with reducing the padding did not work. Setting ´.environment(.defaultMinListRowHeight, 0)´ helped a lot.

struct ContentView: View {
  @State var data : [String] = ["first","second","3rd","4th","5th","6th"]

  var body: some View {
    VStack {
      List {
        ForEach(data, id: \.self)
        { item in
          Text("\(item)")
          .padding(0)
          //.frame(height: 60)
          .background(Color.yellow)
        }
        //.frame(height: 60)
        .padding(0)
        .background(Color.blue)
      }
      .environment(\.defaultMinListRowHeight, 0)
      .onAppear { UITableView.appearance().separatorStyle = .none }
      .onDisappear { UITableView.appearance().separatorStyle = .singleLine }
    }
  }
}

Changing the ´separatorStyle´ to ´.none´ only removed the Line but left the space.
Is there an extra ´hidden´ view for the Lists row or for the Separator between the rows? How can this be controlled?

Would be using ScrollView instead of a List a good solution?

ScrollView(.horizontal, showsIndicators: true)
        {
      //List {
        ForEach(data, id: \.self)
        { item in
          HStack{
          Text("\(item)")
            Spacer()
          }

Does it also work for a large dataset?


Solution

  • Well, actually no surprise - .separatorStyle = .none works correctly. I suppose you confused text background with cell background - they are changed by different modifiers. Please find below tested & worked code (Xcode 11.2 / iOS 13.2)

    demo

    struct ContentView: View {
      @State var data : [String] = ["first","second","3rd","4th","5th","6th"]
    
      var body: some View {
        VStack {
          List {
            ForEach(data, id: \.self)
            { item in
              Text("\(item)")
                .background(Color.yellow) // text background
                .listRowBackground(Color.blue) // cell background
            }
          }
          .onAppear { UITableView.appearance().separatorStyle = .none }
          .onDisappear { UITableView.appearance().separatorStyle = .singleLine }
        }
      }
    }
    

    Update:

    it's not possible to avoid the blue space between the yellow Texts?

    Technically yes, it is possible, however for demo it is used hardcoded values and it is not difficult to fit some, while to calculate this dynamically might be challenging... anyway, here it is

    demo2

    it needs combination of stack for compression, content padding for resistance, and environment for limit:

      List {
        ForEach(data, id: \.self)
        { item in
            HStack {                                 // << A
              Text("\(item)")
                .padding(.vertical, 2)               // << B
            }
            .listRowBackground(Color.blue)
            .background(Color.yellow)
            .frame(height: 12)                       // << C
        }
      }
      .environment(\.defaultMinListRowHeight, 12)    // << D