4

我正在通过一个示例应用程序来熟悉 Swift 和 SwiftUI,并希望使用自定义视图和 GeometryReader 结合复合布局的想法来确定设备的屏幕大小。

我正在尝试构建的页面是一个可滚动的朋友列表,其中每个行项都是一个按钮,可以选择该按钮来展开列表以查看每个朋友的更多详细信息。我已经构建了按钮和所有包含视图,FriendView以便在我的FriendListView. 我在其中定义了 2 个GeometryReader视图,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()
    }
}
4

1 回答 1

2

GeometryReader您可以在顶层定义 aFriendListView并将屏幕宽度传递给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()
}
于 2020-06-13T15:35:58.357 回答