SwiftUI - Размещение двух сборщиков рядом в HStack не изменяет размер сборщиков - PullRequest
1 голос
/ 10 июля 2019

Моя цель состоит в том, чтобы два сборщика располагались рядом друг с другом, причем каждый сборщик занимал половину ширины экрана. Представьте себе UIPickerView, который соответствует ширине экрана и имеет два компонента одинаковой ширины - это то, что я пытаюсь воссоздать в SwiftUI.

Поскольку средства выбора в SwiftUI в настоящее время не допускают использование нескольких компонентов, для меня очевидной альтернативой было просто поместить два средства выбора в HStack.

Вот пример кода из тестового проекта:

struct ContentView: View {
    @State var selection1: Int = 0
    @State var selection2: Int = 0

    @State var integers: [Int] = [0, 1, 2, 3, 4, 5]

    var body: some View {
        HStack {
            Picker(selection: self.$selection1, label: Text("Numbers")) {
                ForEach(self.integers) { integer in
                    Text("\(integer)")
                }
            }
            Picker(selection: self.$selection2, label: Text("Numbers")) {
                ForEach(self.integers) { integer in
                    Text("\(integer)")
                }
            }
        }
    }
}

А вот и холст:

SwiftUI - Сборщики в HStack

Подборщики не меняют свой размер до половины ширины экрана, как я и ожидал. Они сохраняют свой размер и вместо этого растягивают ширину представления содержимого, искажая ширину других элементов пользовательского интерфейса в процессе (как я узнал, когда пытался сделать это в моем другом проекте).

Я знаю, что могу использовать UIViewRepresentable, чтобы получить желаемый эффект, но SwiftUI будет гораздо проще использовать, учитывая сложность того, для чего я пытаюсь это использовать.

Является ли ошибкой то, что размещение двух сборщиков внутри HStack неправильно изменяет их размер или сборщики в SwiftUI просто имеют фиксированную ширину, которую нельзя изменить?


Обновление

Используя GeometryReader, мне удалось приблизиться к изменению размеров сборщиков, как я хочу, но не полностью.

Примечание: вы можете также добиться такого же несовершенного результата, не используя GeometryReader, просто установив рамку на каждом сборщике на .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity).

Вот пример кода:

struct ContentView: View {
    @State var selection1: Int = 0
    @State var selection2: Int = 0

    @State var integers: [Int] = [0, 1, 2, 3, 4, 5]

    var body: some View {
        GeometryReader { geometry in
            HStack(spacing: 0) {
                Picker(selection: self.$selection1, label: Text("Numbers")) {
                    ForEach(self.integers) { integer in
                        Text("\(integer)")
                    }
                }
                .frame(maxWidth: geometry.size.width / 2)
                Picker(selection: self.$selection2, label: Text("Numbers")) {
                    ForEach(self.integers) { integer in
                        Text("\(integer)")
                    }
                }
                .frame(maxWidth: geometry.size.width / 2)
            }
        }
    }
}

А вот и холст:

Сборщики в HStack с GeometryReader

Теперь сборщики ближе к желаемой внешности, но размеры все еще немного смещены, и теперь они накладываются друг на друга посередине.

1 Ответ

1 голос
/ 10 июля 2019

Перекрытие в середине вы можете исправить, добавив модификатор clipped (). Что касается ширины, я вижу их обоих одинаково:

enter image description here

struct ContentView: View {
    @State var selection1: Int = 0
    @State var selection2: Int = 0

    @State var integers: [Int] = [0, 1, 2, 3, 4, 5]

    var body: some View {
        GeometryReader { geometry in
            HStack(spacing: 0) {
                Picker(selection: self.$selection1, label: Text("Numbers")) {
                    ForEach(self.integers) { integer in
                        Text("\(integer)")
                    }
                }
                .frame(maxWidth: geometry.size.width / 2)
                .clipped()
                .border(Color.red)

                Picker(selection: self.$selection2, label: Text("Numbers")) {
                    ForEach(self.integers) { integer in
                        Text("\(integer)")
                    }
                }
                .frame(maxWidth: geometry.size.width / 2)
                .clipped()
                .border(Color.blue)
            }
        }
    }
}
...