SwiftUI - размещение двух сборщиков бок о бок в HStack не изменяет размер сборщиков.

Моя цель состоит в том, чтобы два сборщика располагались бок о бок по горизонтали, причем каждый сборщик занимал половину ширины экрана. Представьте себе 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

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


person graycampbell    schedule 09.07.2019    source источник


Ответы (1)


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

введите описание изображения здесь

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)
            }
        }
    }
}
person kontiki    schedule 10.07.2019
comment
Огромное спасибо! Не могу поверить, что это было так просто, как добавить clipped(). Вы правы, ширина была такой же. Меня сбило с толку тот факт, что сборщик справа так сильно перекрывал сборщик слева. Между прочим, у вас отличные уроки. Я использовал их на днях и многому научился, так что спасибо за это! - person graycampbell; 10.07.2019