SwiftUI:如何查找图像的高度并使用它来设置框架的大小 [英] SwiftUI: How to find the height of an image and use it to set the size of a frame
问题描述
所以我一直试图弄清楚如何在SwiftUI中找到图像的高度已经有一段时间了,但没有成功.本质上,我有纵向/横向图像,要在600 pt高处显示纵向图像,而横向图像则要显示,以便使用图像的宽度,因此高度不限.话虽如此,我想在GeometryReader中使用它,因为我正在使用的偏移量会使用它,因此当您向下滚动时,图像不会滚动,但是如果向上滚动,它会滚动.我不相信我可以共享图像,但是无论如何,这应该足以使它成功运行!
So I've been trying to figure out how to find the height of an image in SwiftUI for a while now with no success. Essentially I have portrait/landscape images, which the portrait ones I want to display at about 600 pt tall, whereas the landscape images I want to display so the width of the image is used, so the height is whatever. That being said, I'm wanting it inside of a GeometryReader, as the offset I am using uses it so that when you scroll down, the image doesn't scroll, but if you scroll up, it does. I don't believe I can share images, but in any case, this should be enough code to run it successfully!
struct ContentView: View {
@Environment(\.presentationMode) var mode: Binding<PresentationMode>
var backButton: some View {
Button(action: {
withAnimation {
self.mode.wrappedValue.dismiss()
}
}) {
Image(systemName: "chevron.left.circle.fill")
.opacity(0.8)
.font(.system(size: 30))
.foregroundColor(.black)
.background(Color.gray.mask(Image(systemName: "chevron.left").offset(x: 9.4, y: 7.6)))
}
}
var body: some View {
ScrollView(showsIndicators: false) {
GeometryReader { geometry in
Image("image1")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(maxWidth: UIScreen.main.bounds.width, minHeight: 350, maxHeight: 600, alignment: .top)
.clipped()
.overlay(
Rectangle()
.foregroundColor(.clear)
.background(LinearGradient(gradient: Gradient(colors: [.clear, .white]), startPoint: .center, endPoint: .bottom))
)
.offset(y: geometry.frame(in: .global).minY > 0 ? -geometry.frame(in: .global).minY : 0)
}
.frame(minWidth: UIScreen.main.bounds.width, maxWidth: UIScreen.main.bounds.width, minHeight: 350, idealHeight: 600, maxHeight: 600)
//Message
VStack(alignment: .leading) {
Text("\(07/22/20) - Day \(1)")
.font(.body)
.fontWeight(.light)
.foregroundColor(Color.gray)
.padding(.leading)
Text("what I Love)
.font(.title)
.fontWeight(.bold)
.padding([.leading, .bottom])
Text("paragraph")
.padding([.leading, .bottom, .trailing])
}
}
.edgesIgnoringSafeArea(.all)
.navigationBarBackButtonHidden(true)
.navigationBarItems(leading: backButton)
}
}
任何帮助将不胜感激!
这是两张供参考的图片-抱歉,我没意识到您能够做到,尽管我早该想到了!
Here are two images for reference- Sorry I didn't realize you were able to, though I should've figured that!
推荐答案
如果我正确理解,您想要图像的大小,以便可以在其自己的框架中使用它的尺寸吗?您可以创建一个接受图像名称并返回所需图像的函数,同时还为您设置的 width
和 height
设置 @State
vars可以在框架中使用.
If I understood correctly, you want the size of the image so you can use it's dimensions in it's own frame? You could make a function that takes in an image name and returns your desired image while also setting @State
vars for the width
and height
which you can use in the frame.
@State var width: CGFloat = 0
@State var height: CGFloat = 0
func image(_ name: String) -> UIImage {
let image = UIImage(named: name)!
let width = image.size.width
let height = image.size.height
DispatchQueue.main.async {
if width > height {
// Landscape image
// Use screen width if < than image width
self.width = width > UIScreen.main.bounds.width ? UIScreen.main.bounds.width : width
// Scale height
self.height = self.width/width * height
} else {
// Portrait
// Use 600 if image height > 600
self.height = height > 600 ? 600 : height
// Scale width
self.width = self.height/height * width
}
}
return image
}
用法:
GeometryReader { geometry in
Image(uiImage: image("image1"))
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: width, height: height)
.overlay(
Rectangle()
.foregroundColor(.clear)
.background(LinearGradient(gradient: Gradient(colors: [.clear, .white]), startPoint: .center, endPoint: .bottom))
)
.offset(y: geometry.frame(in: .global).minY > 0 ? -geometry.frame(in: .global).minY : 0)
添加了 DispatchQueue.main.async
块作为在视图更新期间修改状态"警告的快速修复.可行,但可能不是绝对的最佳方法.最好将图像放入其自己的 @State
中,并在视图的 onAppear
方法中进行设置.
edit: Added the DispatchQueue.main.async
block as a quick fix for 'Modifying state during view update' warning. Works but probably not the absolute best way to go about it. Might be better to put the image into it's own @State
and set it in the view's onAppear
method.
edit 2:将图像移动到它自己的 @State
var中,我认为这是一个更好的解决方案,因为它可以使视图更具可重用性,因为您可以传递图像而不是对名称的硬编码.视图中的图像.
edit 2: Moved the image into it's own @State
var which I believe is a better solution as it will make the view more reusable as you can pass an image instead of hard coding the name of the image in the view.
@State var image: UIImage {
didSet {
let width = image.size.width
let height = image.size.height
DispatchQueue.main.async {
if width > height {
// Landscape image
self.width = width > UIScreen.main.bounds.width ? UIScreen.main.bounds.width : width
self.height = self.width/width * height
} else {
self.height = height > 600 ? 600 : height
self.width = self.height/height * width
}
}
}
}
用法:
GeometryReader { geometry in
Image(uiImage: image)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: width, height: height)
.overlay(
Rectangle()
.foregroundColor(.clear)
.background(LinearGradient(gradient: Gradient(colors: [.clear, .white]), startPoint: .center, endPoint: .bottom))
)
.offset(y: geometry.frame(in: .global).minY > 0 ? -geometry.frame(in: .global).minY : 0)
将不得不通过传入UIImage来更新ContentView的声明方式:
Will have to update how the ContentView is declared by passing in a UIImage:
ContentView(image: UIImage(named: "image0")!)
这篇关于SwiftUI:如何查找图像的高度并使用它来设置框架的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!