Есть ли способ определить ширину моего изображения SwiftUI относительно размера экрана с помощью Geometry Reader?

Я работаю с образцом приложения, чтобы познакомиться со Swift и SwiftUI, и хочу объединить идеи составных макетов с использованием настраиваемых представлений и GeometryReader для определения размера экрана устройства.

Страница, которую я пытаюсь создать, представляет собой прокручиваемый список друзей, где каждый элемент строки представляет собой кнопку, которую можно выбрать, чтобы развернуть список, чтобы увидеть более подробную информацию о каждом друге. Я создал кнопку и все содержащие представления какFriendView использовать внутри моего FriendListView. Я определил 2GeometryReader взгляды в FriendListView но не знаю, как определить размер каждой строки из FriendView чтобы сохранить соответствующий размер.

Необходимость в этом возникает из-за того, что не каждое изображение, которое пользователь может позже установить для своего друга, будет иметь одинаковые размеры, поэтому я хочу сохранить его согласованность. Я понимаю, что могу установить.frame() модификатор и жестко закодируйте ширину, но я бы хотел, чтобы она относилась к экрану, чтобы она была единообразной на всех экранах телефонов.

Пример: если строка не развернута, изображение должно занимать половину ширины устройства. Когда он будет расширен, я бы хотел, чтобы он занимал четверть ширины экрана устройства.

Скриншот

Просмотр приложения

Образец кода

struct FriendListView: View {
    var pets = ["Woofer", "Floofer", "Booper"]

    var body: some View {
        GeometryReader { geo1 in
            NavigationView {
                GeometryReader { geo2 in
                    List(self.pets, id: \.self) { pet in
                            FriendView(name: pet)

                    }// End of List
                }
                .navigationBarTitle(Text("Furiends"))

            }// End of NavigationView
        }// End of GeometryReader geo1
    }// End of body
}
struct FriendView: View {
    @State private var isExpanded = false
    var randomPic = Int.random(in: 1...2)

    var name =  ""
    var breed = "Dawg"
    var body: some View {

            Button(action: self.toggleExpand) {
                HStack {
                    VStack {
                    Image("dog\(self.randomPic)")
                        .resizable()
                        .renderingMode(.original)
                        .scaledToFill()
                        .clipShape(Circle())

                       if self.isExpanded == false {
                        Text(self.name)
                            .font(.title)
                            .foregroundColor(.primary)
                       }
                   }

                   if self.isExpanded == true {
                       VStack {
                        Text(self.name).font(.title)
                        Text(self.breed).font(.headline)
                       }
                       .foregroundColor(.primary)
                   }
               }
            }// End of Button
    }
    func toggleExpand() {
        isExpanded.toggle()
    }
}

1 ответ

Решение

Вы можете определить GeometryReader на верхнем уровне FriendListView и передайте ширину экрана в FriendView:

struct FriendListView: View {
    var pets = ["Woofer", "Floofer", "Booper"]

    var body: some View {
        GeometryReader { geo in
            NavigationView {
                List(self.pets, id: \.self) { pet in
                    FriendView(name: pet, screenWidth: geo.size.width)
                }
                .navigationBarTitle(Text("Furiends"))
            }
        }
    }
}

Затем используйте .frame чтобы установить максимальную ширину изображения.

struct FriendView: View {
    ...

    var screenWidth: CGFloat

    var imageWidth: CGFloat {
        isExpanded ? screenWidth / 4 : screenWidth / 2
    }

    var body: some View {
        Button(action: self.toggleExpand) {
            HStack {
                VStack {
                    Image("dog\(self.randomPic)")
                        .resizable()
                        .renderingMode(.original)
                        .scaledToFill()
                        .clipShape(Circle())
                        .frame(width: imageWidth, height: imageWidth)  // <- add frame boundaries

                    if self.isExpanded == false {
                        Text(self.name)
                            .font(.title)
                            .foregroundColor(.primary)
                    }
                }

                if self.isExpanded == true {
                    VStack {
                        Text(self.name).font(.title)
                        Text(self.breed).font(.headline)
                    }
                    .foregroundColor(.primary)
                }
            }
        }
    }

    func toggleExpand() {
        isExpanded.toggle()
    }
}

Если вы хотите, чтобы ваше изображение было центрировано, вы можете использовать Spacer:

HStack {
    Spacer()
    FriendView(name: pet, screenWidth: geo.size.width)
    Spacer()
}
Другие вопросы по тегам