SwiftUI уменьшает интервал между строками в списке до нуля - PullRequest
1 голос
/ 01 марта 2020

Я хочу уменьшить расстояние между строками в списке до нуля.

Мои попытки уменьшить отступы не сработали. Установка «.environment (.defaultMinListRowHeight, 0)» очень помогла.

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 }
    }
  }
}

Изменение «separatorStyle» на «.none» только удалило строку, но оставило пробел.
Есть ли дополнительные «Скрытый» вид строки Lists или разделителя между строками? Как это можно контролировать?

Будет ли использовать ScrollView вместо List хорошего решения?

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

Это также работает для большого набора данных?

Ответы [ 2 ]

2 голосов
/ 01 марта 2020

Ну, на самом деле нет ничего удивительного - .separatorStyle = .none работает правильно. Полагаю, вы перепутали фон текста с фоном ячейки - они меняются разными модификаторами. Пожалуйста, найдите ниже проверенный и работающий код (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 }
    }
  }
}

Обновление:

невозможно избежать синего пробела между желтыми текстами?

Технически да, это возможно, однако для демо-версии используются жестко закодированные значения, и некоторые из них не сложно подгонять при вычислении это динамически может быть сложным ... в любом случае, здесь это

demo2

, для этого требуется комбинация стека для сжатия, заполнения контента для сопротивления и среды для ограничения:

  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
1 голос
/ 01 марта 2020

Сократить межстрочный интервал действительно сложно, попробуйте

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

    var body: some View {
        VStack {
            ScrollView {
                ForEach(data, id: \.self) { item in
                    VStack(alignment: .leading, spacing: 0) {
                        Color.red.frame(height: 1)
                        Text("\(item)").font(.largeTitle)
                            .background(Color.yellow)
                    }.background(Color.green)
                    .padding(.leading, 10)
                    .padding(.bottom, -25)
                    .frame(maxWidth: .infinity)
                }
            }
        }
    }
} 

Он использует ScrollView вместо List и отрицательного заполнения.

enter image description here

Я не нашел решения, основанного на List, мы должны попросить Apple опубликовать sh xxxxStyle протоколов и базовых структур.

UPDATE

Как насчет этого отрицательного значения заполнения? Конечно, это зависит от высоты содержимого строки и, к сожалению, от стратегии компоновки SwiftUI. Давайте попробуем еще немного динамического c контента! (мы используем нулевое заполнение для демонстрации решаемой задачи)

struct ContentView: View {
    @State var data : [CGFloat] = [20, 30, 40, 25, 15]

    var body: some View {
        VStack {
            ScrollView {
                ForEach(data, id: \.self) { item in
                    VStack(alignment: .leading, spacing: 0) {
                        Color.red.frame(height: 1)
                        Text("\(item)").font(.system(size: item))
                            .background(Color.yellow)
                    }.background(Color.green)
                    .padding(.leading, 10)
                    //.padding(.bottom, -25)
                    .frame(maxWidth: .infinity)
                }
            }
        }
    }
}

enter image description here

Очевидно, что расстояние между строками не является фиксированным значением! Мы должны рассчитать его для каждой строки отдельно.

Следующий фрагмент кода демонстрирует основную идею c. Я использовал глобальный словарь (для хранения высоты и положения каждой строки) и старался избегать каких-либо функций высокого порядка и / или некоторой продвинутой техники SwiftUI c, поэтому стратегию легко увидеть. Необходимые отступы рассчитываются только один раз, при закрытии .onAppear

import SwiftUI

var _p:[Int:(CGFloat, CGFloat)] = [:]

struct ContentView: View {
    @State var data : [CGFloat] = [20, 30, 40, 25, 15]
    @State var space: [CGFloat] = []

    func spc(item: CGFloat)->CGFloat {
        if let d = data.firstIndex(of: item) {
            return d < space.count ? space[d] : 0
        } else {
            return 0
        }
    }

    var body: some View {
        VStack {
            ScrollView {
                ForEach(data, id: \.self) { item in
                    VStack(alignment: .leading, spacing: 0) {
                        Color.red.frame(height: 1)
                        Text("\(item)")
                            .font(.system(size: item))
                            .background(Color.yellow)
                    }
                    .background(
                        GeometryReader { proxy->Color in
                            if let i = self.data.firstIndex(of: item) {
                                _p[i] = (proxy.size.height, proxy.frame(in: .global).minY)
                            }
                            return Color.green
                        }
                    )
                    .padding(.leading, 5)
                    .padding(.bottom, -self.spc(item: item))

                    .frame(maxWidth: .infinity)
                }.onAppear {
                    var arr:[CGFloat] = []
                    _p.keys.sorted(by: <).forEach { (i) in
                        let diff = (_p[i + 1]?.1 ?? 0) - (_p[i]?.1 ?? 0) - (_p[i]?.0 ?? 0)
                        if diff < 0 {
                            arr.append(0)
                        } else {
                            arr.append(diff)
                        }
                    }
                    self.space = arr
                }
            }
        }
    }
}

Выполнение кода, который я получил

enter image description here

...