Swiftui: How to Find the Height of an Image and Use It to Set the Size of a Frame

SwiftUI: How to find the height of an image and use it to set the size of a frame

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
}

Usage:

    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)

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: 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
}
}
}
}

Usage:

    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)

Will have to update how the ContentView is declared by passing in a UIImage:

ContentView(image: UIImage(named: "image0")!)

SwiftUI Image with high height layout

Ok, I found a way

Color.clear
.background(Image("image")
.resizable()
.scaledToFill())
.clipped()

Embedding the image as background of a clear Color, the image is limited to the parent size!

Result: https://imgur.com/a/ceZRqSw

Swiftui getting an image's displaying dimensions

I would use GeometryReader on background so it reads exactly size of image, as below

@State var imageSize: CGSize = .zero // << or initial from NSImage
...
Image(nsImage: self.img!)
.resizable()
.scaledToFit()
.background(rectReader())

// ... somewhere below
private func rectReader() -> some View {
return GeometryReader { (geometry) -> Color in
let imageSize = geometry.size
DispatchQueue.main.async {
print(">> \(imageSize)") // use image actual size in your calculations
self.imageSize = imageSize
}
return .clear
}
}

How to set the height of the PageTabView

Use .frame(height: yourDesiredHeight). However this will keep your image scaled as if you're using .scaleToFit() which will try to fit all of the image in the frame.

Try using .aspectRatio(contentMode: .fill) to fill the whole frame.

How Do I get uniform view size when using Image and SFSymbols in SwiftUI?

If you want to normalize the sizes, you could use a PreferenceKey to measure the largest size and make sure that all of the other sizes expand to that:

struct ContentView: View {
let symbols = [ "camera", "comb", "diamond", "checkmark.square"]
@State private var itemSize = CGSize.zero

var body: some View {
HStack(spacing: 0) {
ForEach(Array(symbols), id: \.self) { item in
VStack {
Image(systemName: item).font(.largeTitle)
}
.padding()
.background(GeometryReader {
Color.clear.preference(key: ItemSize.self,
value: $0.frame(in: .local).size)
})
.frame(width: itemSize.width, height: itemSize.height)
.border(.red)
}.onPreferenceChange(ItemSize.self) {
itemSize = $0
}
}
.border(Color.black)
}
}

struct ItemSize: PreferenceKey {
static var defaultValue: CGSize { .zero }
static func reduce(value: inout Value, nextValue: () -> Value) {
let next = nextValue()
value = CGSize(width: max(value.width,next.width),
height: max(value.height,next.height))
}
}

Sample Image

Adjust Image Size of Image to Parent View Size

If I understood correctly the intention was to fill proportionally, so

  ZStack{
Image(backgoundImage!)
.resizable() // for resizing
.scaledToFill() // << here !! // for filling image on ImageView

but in that case it can spread out of bounds, so it needs to be clipped in place of .frame applied, so either

ImageCard("image")
.frame(decide the size of the image)
.clipped() // << here !!

or, better, as already described inject dimension inside card and apply it there, like

    Image(backgoundImage!)
.resizable() // for resizing
.scaledToFill() // << here !!
.frame(decide the size of the image)
.clipped() // << here !!
.cornerRadius(5)
.shadow(color: .gray, radius: 6, x: 0, y: 3)
}

How to set width and height of an image in SwiftUI?

Try this

Image("testImg")
.resizable()
.frame(width: 50.0, height: 50.0)

How to resize Image with SwiftUI?

You should use .resizable() before applying any size modifications on an Image.

Image(room.thumbnailImage)
.resizable()
.frame(width: 32.0, height: 32.0)


Related Topics



Leave a reply



Submit