I would like to centre an image on the screen but make its height half of the screen height? How is this possible?
You can use a GeometryReader
in SwiftUI to get details of a view's container geometry; Note that this approach is different to using the screen size, but this is a more flexible as you can use it inside other views.
struct RatioImage: View {
let image: Image
let heightRatio:CGFloat = 0.5
var body: some View {
GeometryReader { geo in
VStack {
Spacer()
image.resizable().aspectRatio(contentMode: .fit)
.frame(width: geo.size.width, height: geo.size.height*heightRatio,
alignment: .center)
Spacer()
}
}
}
}
struct ContentView: View {
var body: some View {
HalfHeight {
RatioImage(image: Image(systemName:"photo.fill"))
}
}
}
By using SwiftUI's ViewBuilder
capability you can create a generic container that can resize arbitrary content:
struct RatioContainer<Content: View>: View {
let heightRatio:CGFloat
let content: Content
init(heightRatio:CGFloat = 0.5,@ViewBuilder content: () -> Content) {
self.heightRatio = heightRatio
self.content = content()
}
var body: some View {
GeometryReader { geo in
VStack {
Spacer()
content.frame(width: geo.size.width, height: geo.size.height*heightRatio, alignment: .center)
Spacer()
}
}
}
}
struct ContentView: View {
var body: some View {
RatioContainer {
VStack {
Image(systemName: "photo").resizable().aspectRatio(contentMode: .fit)
Text("Some caption text").font(.caption)
}
}
}
}
You can even nest instances of the container, which won't work correctly if you use UIScreen
dimensions:
struct ContentView: View {
var body: some View {
VStack {
RatioContainer {
VStack {
Image(systemName: "photo").resizable().aspectRatio(contentMode: .fit)
Text("Some caption text").font(.caption)
RatioContainer(heightRatio:0.3) {
VStack {
Image(systemName: "photo.fill").resizable().aspectRatio(contentMode: .fit)
Text("Some other caption text").font(.caption)
}
}
}
}
}
}
}
Like this, if you have a question about code ask plz, I think it is easy to understand.
import SwiftUI
struct ContentView: View {
var body: some View {
Image(systemName: "person")
.resizable()
.frame(width: UIScreen.main.bounds.height/2, height: UIScreen.main.bounds.height/2)
.aspectRatio(contentMode: .fit)
}
}
updated: for supporting orientation change:
import SwiftUI
struct ContentView: View {
@State var sizeOfImage: CGFloat = UIScreen.main.bounds.height/2
var body: some View {
Image(systemName: "person")
.resizable()
.frame(width: sizeOfImage, height: sizeOfImage)
.aspectRatio(contentMode: .fit)
.onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
sizeOfImage = UIScreen.main.bounds.height/2 }
}
}
You can use a GeometryReader
in SwiftUI to get details of a view's container geometry; Note that this approach is different to using the screen size, but this is a more flexible as you can use it inside other views.
struct RatioImage: View {
let image: Image
let heightRatio:CGFloat = 0.5
var body: some View {
GeometryReader { geo in
VStack {
Spacer()
image.resizable().aspectRatio(contentMode: .fit)
.frame(width: geo.size.width, height: geo.size.height*heightRatio,
alignment: .center)
Spacer()
}
}
}
}
struct ContentView: View {
var body: some View {
HalfHeight {
RatioImage(image: Image(systemName:"photo.fill"))
}
}
}
By using SwiftUI's ViewBuilder
capability you can create a generic container that can resize arbitrary content:
struct RatioContainer<Content: View>: View {
let heightRatio:CGFloat
let content: Content
init(heightRatio:CGFloat = 0.5,@ViewBuilder content: () -> Content) {
self.heightRatio = heightRatio
self.content = content()
}
var body: some View {
GeometryReader { geo in
VStack {
Spacer()
content.frame(width: geo.size.width, height: geo.size.height*heightRatio, alignment: .center)
Spacer()
}
}
}
}
struct ContentView: View {
var body: some View {
RatioContainer {
VStack {
Image(systemName: "photo").resizable().aspectRatio(contentMode: .fit)
Text("Some caption text").font(.caption)
}
}
}
}
You can even nest instances of the container, which won't work correctly if you use UIScreen
dimensions:
struct ContentView: View {
var body: some View {
VStack {
RatioContainer {
VStack {
Image(systemName: "photo").resizable().aspectRatio(contentMode: .fit)
Text("Some caption text").font(.caption)
RatioContainer(heightRatio:0.3) {
VStack {
Image(systemName: "photo.fill").resizable().aspectRatio(contentMode: .fit)
Text("Some other caption text").font(.caption)
}
}
}
}
}
}
}
I had to call aspectRatio before .frame() so the image doesn't stretch
Image(imageName)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height/2)
© 2022 - 2024 — McMap. All rights reserved.