I would like to overlay text on top of an image, and allow that text to properly scale with the parent image as it decreases or increases in size. However, I do not want to force the text to fit inside the view. Below, is a simple code I have been using to test this:
struct BooksView: View {
let gridItems = [GridItem(.adaptive(minimum: 200, maximum: 300))]
let books = [
BookView(bookTitle: "Illustrated Manual of Abdominal Massage", bookAuthor: "Shinsai Ota", bookRating: 4),
BookView(bookTitle: "Illustrated Manual of Abdominal Massage", bookAuthor: "Shinsai Ota", bookRating: 4),
BookView(bookTitle: "Illustrated Manual of Abdominal Massage", bookAuthor: "Shinsai Ota", bookRating: 4),
BookView(bookTitle: "Illustrated Manual of Abdominal Massage", bookAuthor: "Shinsai Ota", bookRating: 4),
BookView(bookTitle: "Illustrated Manual of Abdominal Massage", bookAuthor: "Shinsai Ota", bookRating: 4),
BookView(bookTitle: "Illustrated Manual of Abdominal Massage", bookAuthor: "Shinsai Ota", bookRating: 4),
BookView(bookTitle: "Illustrated Manual of Abdominal Massage", bookAuthor: "Shinsai Ota", bookRating: 4)
]
var body: some View {
ScrollView {
LazyVGrid(columns: gridItems, spacing: 5) {
ForEach(books.indices, id: \.self) { i in
books[i]
}
}
}
}
}
and my "BookView" looks like this:
import SwiftUI
import URLImage
struct BookView: View {
let bookTitle: String
let bookAuthor: String
let bookRating: Int
var body: some View {
ZStack {
VStack {
URLImage(URL(string: "https://upload.wikimedia.org/wikipedia/commons/e/e8/AnpukuZukaiCover.jpg")!) { // placeholder url
EmptyView()
} inProgress: { progress in
ProgressView()
} failure: { error, retry in
VStack {
Text(error.localizedDescription)
Button("Retry", action: retry)
}
} content: { image in
image
.scaleFit(radius: 2)
.shadow(radius: 5)
}
}
VStack(alignment: .leading) {
Spacer()
Text(bookTitle)
.font(.title)
.fontWeight(.bold)
.lineLimit(3)
.foregroundColor(.primary)
Text("by \(bookAuthor)")
.font(.subheadline)
.foregroundColor(.secondary)
}
.scaledToFit()
}
.frame(minWidth: 200, minHeight: 300)
}
}
as well, I made a "scaleFit" function for my image. It looks like this:
func scaleFit(radius: CGFloat) -> some View {
self
.resizable()
.scaledToFit()
.mask(
self
.resizable()
.scaledToFit()
.clipped()
)
.clipShape(RoundedRectangle(cornerRadius: radius))
.contentShape(Rectangle())
}
This BooksView is inside the detail of a NavigationSplitView, and I was hoping of figuring out a way that allows the text to scale with the image as the column changes size.
I have tried using:
.minimumScaleFactor(0.01)
and .font(.system(size: 300))
to try and scale my text, but I am not sure if this is what I want, as it has only been useful for fitting rather than dynamic scaling. I have looked at using .scaleEffect
, but I am not too sure if that is what I want either. I was thinking of somehow turning the text into a bitmap, so it behaves differently and I could possible scale it better, but I feel there must be a better solution to this.
I also have looked at this page but everything seemed to refer to fitting rather than scaling with the parent.