有没有办法使用 Geometry Reader 将我的 SwiftUI 图像的宽度定义为相对于屏幕尺寸?
Is there a way to define the width of my SwiftUI Image to be relative to screen size using Geometry Reader?
我正在通过一个示例应用程序来熟悉 Swift 和 SwiftUI,我想结合使用自定义视图和 GeometryReader 的复合布局的想法来确定设备的屏幕尺寸。
我要构建的页面是一个可滚动的朋友列表,其中每个行项目都是一个按钮,可以选择该按钮来展开列表以查看每个朋友的更多详细信息。我已经构建了按钮和所有包含视图的 FriendView
,以便在我的 FriendListView
中使用。我在 FriendListView
中定义了 2 GeometryReader
视图,但不知道如何从 FriendView
中定义每一行的大小以使其保持适当的大小。
之所以需要这样做,是因为并非用户以后可以为他们的朋友设置的每张图像都具有相同的尺寸,因此我想保持一致。我知道我可以设置一个 .frame()
修饰符并对宽度进行硬编码,但我希望它与屏幕相关,以便在所有 phone 屏幕上保持一致。
示例:当一行未展开时,图像应占设备宽度的一半。当它展开时,我希望它占据设备屏幕宽度的四分之一。
截图
Application View
示例代码
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()
}
}
您可以在顶层定义一个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()
}
我正在通过一个示例应用程序来熟悉 Swift 和 SwiftUI,我想结合使用自定义视图和 GeometryReader 的复合布局的想法来确定设备的屏幕尺寸。
我要构建的页面是一个可滚动的朋友列表,其中每个行项目都是一个按钮,可以选择该按钮来展开列表以查看每个朋友的更多详细信息。我已经构建了按钮和所有包含视图的 FriendView
,以便在我的 FriendListView
中使用。我在 FriendListView
中定义了 2 GeometryReader
视图,但不知道如何从 FriendView
中定义每一行的大小以使其保持适当的大小。
之所以需要这样做,是因为并非用户以后可以为他们的朋友设置的每张图像都具有相同的尺寸,因此我想保持一致。我知道我可以设置一个 .frame()
修饰符并对宽度进行硬编码,但我希望它与屏幕相关,以便在所有 phone 屏幕上保持一致。
示例:当一行未展开时,图像应占设备宽度的一半。当它展开时,我希望它占据设备屏幕宽度的四分之一。
截图
Application View
示例代码
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()
}
}
您可以在顶层定义一个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()
}