The UIView has the readableContentGuide
so layout could be related to screen size and make sure content always readable. I can not find any pieces of information about those things in the SwiftUI.
What's the equivalent thing in the SwiftUI could be using? And if not, could we use the SwiftUI component to build the same effect in UIKit?
Thanks.
Like most new frameworks, however, one drawback is that it doesn’t come with all UI controls which are available in UIKit. For example, you can’t find a SwiftUI counterpart of text view. Thankfully, Apple provided a protocol called UIViewRepresentable that allows you easily wrap a UIView and make it available to your SwiftUI project.
The makeUIView allows us to set up our representable view ( UIActivityIndicatorView, in our case). It’ll be called only once during the SwiftUI view’s lifecycle. The updateUIView gets triggered whenever its enclosing SwiftUI view changes its state.
Editor’s note: If you are new to SwiftUI, you can check out our introductory tutorial. To use a UIKit view in SwiftUI, you can wrap the view with the UIViewRepresentable protocol. Basically, you just need to create a struct in SwiftUI that adopts the protocol to create and manage a UIView object.
The updateUIView gets triggered whenever its enclosing SwiftUI view changes its state. Inside this method, you can do changes to the view information. For getting data from the SwiftUI view, we leveraged a Binding property wrapper — it can read and write a value owned by a source of truth (State, in our case).
The other solutions didn't work for me because they relied on a hardcoded amount of padding or dropping down to UIKit, which isn't great for multi-platform SwiftUI apps that need to look nice on all the differently-sized iPhones, iPads, and Macs. So as there still isn't a native SwiftUI equivalent (as of iOS 15/macOS 12), I thought I'd make an alternative.
My alternative is to calculate the amount of padding based on:
struct ReadabilityPadding: ViewModifier {
let isEnabled: Bool
@ScaledMetric private var unit: CGFloat = 20
func body(content: Content) -> some View {
// Use a GeometryReader here to get view width.
GeometryReader { geometryProxy in
content
.padding(.horizontal, padding(for: geometryProxy.size.width))
}
}
private func padding(for width: CGFloat) -> CGFloat {
guard isEnabled else { return 0 }
// The internet seems to think the optimal readable width is 50-75
// characters wide; I chose 70 here. The `unit` variable is the
// approximate size of the system font and is wrapped in
// @ScaledMetric to better support dynamic type. I assume that
// the average character width is half of the size of the font.
let idealWidth = 70 * unit / 2
// If the width is already readable then don't apply any padding.
guard width >= idealWidth else {
return 0
}
// If the width is too large then calculate the padding required
// on either side until the view's width is readable.
let padding = round((width - idealWidth) / 2)
return padding
}
}
Here is how it looks on different devices (top is normal, bottom is with the ReadabilityPadding view modifier applied):
There's no direct readableContentGuide
alternative in SwiftUI. It should be directly backed into views. Theoretically, SwiftUI should apply device specific padding but it's not happening in v1.0. So, i.e., adding a padding
modifier to a TextField
should apply a bigger padding in resolutions like an iPad of 12.9".
Even so, you can write your own view modifier to apply custom paddings. Here is an example done by @mecid:
import SwiftUI
private struct ReadableGuidePadding: ViewModifier {
@Environment(\.horizontalSizeClass) var horizontal
func body(content: Content) -> some View {
content.padding(.horizontal, horizontal == .regular ? 84: 16)
}
}
extension View {
func readableGuidePadding() -> some View {
modifier(ReadableGuidePadding())
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With