Reputation: 23
I'm having a problem with custom Font in SwiftUI, I'm use Google Fonts Allura,Courgette,Mr Dafoe, Shoadows Into Light Two, and Source Sans Pro. I provided image below of example you can its cutting the character either from the back or the front and only doing them to characters with height, like D,H,J,I and etc.
I've tried giving it a frame with .infinity and adjusting the height. I've also tried adding padding and padding(trailing). Furthermore, I've attempted using .fixedSize(horizontal: true, vertical: false) and .scaledToFit(), but none of these methods have worked. I suspected there might be an issue with my view, so I created an entirely new project in SwiftUI, gave Text("Hello World!") a custom font, and encountered the same issue.
Then, while searching, I found a custom UIKit label, which worked when I tried it. It seems that when the custom font is applied as a UIFont, it works perfectly, but when it's used as a SwiftUI.Font, it does not.
I've even tried integrating the custom UIKit label into my code, but the problem persists. I need the label to resize and change the font size dynamically as the number of characters increases, to fit on one line and within the view's width. Below is the SwiftUI code as the Minimum Deployment is iOS 15 just for aheads up.
HStack(spacing: 8) {
Spacer()
Text(signText)
.lineLimit(1)
.allowsTightening(true)
.minimumScaleFactor(0.5 / 2)
.font(font)
.frame(maxWidth: .infinity,idealHeight: 150, alignment: .center)
Spacer()
if !signText.isEmpty {
Button(action: {
isSignSheetPresented = true
}, label: {
Image("edit")
.renderingMode(.template)
.frame(idealWidth: 44)
.foregroundColor(Color(CanopyColor.primary.color))
})
}
}
.padding(16)
.frame(maxWidth: .infinity, idealHeight: 150, alignment: .center )
.background(Color(red: 0.98, green: 0.98, blue: 0.98)) // Color Change
.cornerRadius(4)
.overlay(
RoundedRectangle(cornerRadius: 4)
.inset(by: 0.5)
.stroke(Color(red: 0.87, green: 0.87, blue: 0.87), lineWidth: 1)
)
This is the UILabel that I used
struct UILabelView: UIViewRepresentable {
var text: String
var font: UIFont
func makeUIView(context: Context) -> UILabel {
let label = UILabel()
label.font = font
label.text = text
label.numberOfLines = 1
label.textAlignment = .center
label.backgroundColor = .clear
label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor = 0.25
label.allowsDefaultTighteningForTruncation = true
label.translatesAutoresizingMaskIntoConstraints = false
label.widthAnchor.constraint(equalToConstant: 100).isActive = true
return label
}
func updateUIView(_ uiView: UILabel, context: Context) {
uiView.text = text
uiView.font = font
uiView.textAlignment = .center
}
}
If there anymore question or information that I've missed please Comment so I can add them.
Also all the font I mentioned above are from Google Fonts here are the name of them in code so it easier to find.
Allura-Regular Courgette-Regular MrDafoe-Regular ShadowsIntoLightTwo-Regular SourceSansPro-Regular
Upvotes: 2
Views: 772
Reputation: 1271
I believe this to be a bug in iOS font rendering and have accepted it as such in my own app. The only workaround I found is adding padding spaces to your string. You can adjust the font of the padding whitespace, so that the padding has a fixed width (independent of the font used for the rest of the string). You can then compensate for the padding if needed.
struct ContentView: View {
let font = Font.custom("Allura-Regular", size: 32)
// create an attributed string with fixed width padding
var attributedString: AttributedString {
var padding = AttributedString(" ")
padding.font = .monospacedSystemFont(ofSize: 32, weight: .regular)
var text = AttributedString("Assasin's Creed")
text.font = font
var result = padding
result.append(text)
result.append(padding)
return result
}
var body: some View {
// create a container with leading alignment to demonstrate compensating
// for the padding
ZStack(alignment: .leading) {
Color.clear
Text(attributedString)
.lineLimit(1)
.fixedSize()
.offset(x: -20) // measured fixed width of the padding space
// (measured with GeometryReader)
}
}
}
Alternatively you can also concatenate Text instead of using an attributed string.
let paddingFont = Font.system(size: 32).monospaced()
var body: some View {
// create a container with leading alignment to demonstrate compensating
// for the padding
ZStack(alignment: .leading) {
Color.clear
Group {
Text(" ")
.font(paddingFont)
+
Text("Assasin's Creed")
.font(font)
+
Text(" ")
.font(paddingFont)
} .offset(x: -20)
}
}
Note that this problem also occurs with the Zapfino font (which is an iOS system font).
Upvotes: 0