Если я правильно понял, вам нужен размер изображения, чтобы вы могли использовать его размеры в собственном фрейме? Вы можете создать функцию, которая принимает имя изображения и возвращает желаемое изображение, одновременно задавая @State
переменные для width
и height
, которые вы можете использовать во фрейме.
@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)
edit: Добавлен блок DispatchQueue.main.async
как быстрое исправление для предупреждения «Изменение состояния во время обновления представления». Работает, но, вероятно, не лучший способ go об этом. Может быть, лучше поместить изображение в его собственный @State
и установить его в методе представления onAppear
.
edit 2: переместил изображение в свое собственное @State
var, которое, как я считаю, является лучшим решением так как это сделает представление более пригодным для повторного использования, поскольку вы можете передать изображение вместо жесткого кодирования имени изображения в представлении.
@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)
Придется обновите способ объявления ContentView, передав UIImage:
ContentView(image: UIImage(named: "image0")!)