Сетка SwiftUI со столбцом, подходящим для содержимого?

Возможен ли такой макет с SwiftUI?

Я хочу, чтобы в первом столбце был заключен размер меток, поэтому в этом случае он будет достаточно большим, чтобы отобразить "Bigger Label:". Затем оставшееся место отдайте второму столбцу.

Этот макет довольно прост с автоматическим макетом.

SwiftUI 2020 имеет LazyVGridно единственные способы, которые я вижу для установки размеров столбцов, используют жестко заданные числа. Разве они не понимают, в чем проблема с несколькими языками и настраиваемыми пользователем размерами шрифтов?

1 ответ

Это не так сложно, если сравнить количество строк кода, чтобы сделать это программно в обоих мирах...

Во всяком случае, конечно, это возможно. Вот решение, основанное на некотором модификаторе справки с использованием функции предпочтений просмотра. Нетрудно. Нет сетки.

Демо подготовлено и протестировано с Xcode 12 / iOS 14.

       struct DemoView: View {
    @State private var width = CGFloat.zero

    var body: some View {
        VStack {
            HStack {
                Text("Label1")
                    .alignedView(width: $width)
                TextField("", text: .constant("")).border(Color.black)
            }
            HStack {
                Text("Bigger Label")
                    .alignedView(width: $width)
                TextField("", text: .constant("")).border(Color.black)
            }
        }
    }
}

и помощники

       extension View {
    func alignedView(width: Binding<CGFloat>) -> some View {
        self.modifier(AlignedWidthView(width: width))
    }
}

struct AlignedWidthView: ViewModifier {
    @Binding var width: CGFloat

    func body(content: Content) -> some View {
        content
            .background(GeometryReader {
                Color.clear
                    .preference(key: ViewWidthKey.self, value: $0.frame(in: .local).size.width)
            })
            .onPreferenceChange(ViewWidthKey.self) {
                if $0 > self.width {
                    self.width = $0
                }
            }
            .frame(minWidth: width, alignment: .trailing)
    }
}
Другие вопросы по тегам