Unicode char has odd gap when rendered in view - swiftui

I am using the following code to show a playing card. Not sure why there is a large gap at the top.
This is on iOS 15.4
var body: some View {
Text(String(Character(unicodeScalarLiteral: "\u{1F0A1}")))
.font(.system(size: size))
.foregroundColor(.red)
}
Compare to how this smiley is displayed:

This is how this symbol layout within glyph box (pay attention on its position relative to base line):
and here is for comparison of Latin A:
and really if both in one Text
Probably you just need different symbol/image, or try to use some manual workaround like
Text("\u{1F0A1}")
.baselineOffset(20)

Related

What is the recommended way to convert between pixels and points in SwiftUI?

I want to display a QR code in SwiftUI. The code is generated as a CGImage via CIImage. I don't want to scale it to the full size available because if the scaling factor isn't an integer there may be fuzzy boundaries between the QR modules. So I need a way to convert between iOS display points which I can get with GeometryReader and physical points. I've found a few search "hits" about reading the screen scale from a UIView, but not how I can get this scale in SwiftUI.
There a few more hits which just say the scale is 3 on all modern iPhones, and as I'm targeting iOS 15+ I think I can safely assume it's always 3 for now, but what if Apple bring out even higher pixel densities in future?
You can get displayScale using the Environment property wrapper.
struct ContentView: View {
#Environment(\.displayScale) var displayScale
var body: some View {
Text("display scale: \(displayScale)")
}
}
Consult EnvironmentValues to what else SwiftUI provides in the “environment”.

VStack is increasing the width based on String

Example
I have tried playing with the padding but no success. Since the string is vertical when you use a larger string the vstack gets wider
var body: some View {
VStack(spacing: 0) {
Spacer()
Text(title.uppercased())
.font(.footnote)
.foregroundColor(.white)
.rotationEffect(Angle(degrees: rotateClockwise ? 90 : -90))
Spacer()
}//: VSTACK
.background(Color.gray.cornerRadius(12))
.frame(width: 85)
}
It's a little tricky to answer with certainty, as there is clearly a more complex layout around this element. So this answer may work or I may need to edit it as you give me a bit more info.
But my suggestion is this: because rotation is not part of SwiftUI's layout calculation, I would suggest using an HStack to wrap just the Text() elements and then rotating that entire stack. This of course then will require you to be more hands-on with the way you use the HStack in your overall layout, but will allow you to get regular stack layout dynamics for your Text elements. To get more control you could consider using the new layout protocol. These are two good tutorials.

How to add character spacing in SwiftUI after applying fonts and color style?

I want to add character spacing in the text of SwiftUI in iOS version iOS 14 and plus.
When I use a new modifier called as kerning and Tracking after applying fonts styling then it won't work. So any pointer will be appreciated.
kerning and tracking are available in earlier versions of iOS, but only if they're applied directly to Text views.
What's new in iOS 16 is the ability to apply the modifier to any view, and have it apply to any of its Text child views.
Note the iOS availability flags:
Text.tracking(_:) - iOS 13.0+
View.tracking(_:) - iOS 16.0+
So that means that this should work for you in iOS 14:
Text("My Sample Text")
.tracking(-0.1)
but this would not:
VStack {
Text("My Sample View")
Text("With two lines of text")
}
.tracking(-0.1)

ScrollViewReader scrollTo with .center anchor bug?

So I'm try to use ScrollViewReader to programmatically scroll a horizontal scroll view. I thought it would work like scrollToItem with .centeredHorizontally in UIKit, and for the most part it does, but the last few elements in the scroll view are being forcefully scrolled to the center of the screen, despite the fact that the scroll view isn't normally able to scroll that far over (without snapping back after releasing the drag, at least). This ends up creating white space across the trailing half of the screen.
I've seen some other questions about this and it seems like the general opinion is that it's not a bug? On the one hand I suppose we're telling the scroll view to center the item, and it's doing just that -- so, not a bug? On the other hand, that's not how similar functionality worked in UIKit. Also, this behavior is only happening on the trailing end of the scroll view! If it was the intended behavior I would expect that scrolling to the first element in the scroll view using .center anchor would force it into the center of the screen and leave leading white space, but this doesn't happen.
Is there an elegant solution to this? Or do we have to calculate the width of our elements + spacing and figure out based on the screen width whether we should anchor .center or just scroll to the last element with anchor .trailing in order to replicate the UIKit behavior?
I found a package (Amzd/ScrollViewProxy) that was made before ScrollViewReader was released that functions much the same as ScrollViewReader, but also seems to not have the bug (if it is a bug) detailed in the question.
Usage examples can be seen on the repository page, but here's a quick minimal example.
ScrollView(.horizontal) { scrollProxy in
ForEach(sections) { section in
Text(section.text)
.scrollId(section.id)
}
.onChange(of: index) {
scrollProxy.scrollTo(
sections[index].id,
alignment: .center
)
}
}
The package adds a convenience init to ScrollView to give access to the scrollProxy.
I can confirm this behavior and think it should be considered a bug. Especially since the scroll view will "jump" into position on the first touch event.
As of iOS 15.4 Beta 1 this is fixed for me. Maybe give it another try.

SwiftUI scaleEffect and layout bounds

I want to create a Text view with slighter larger than normal font. I tried,
Text("Foo").scaleEffect(1.3)
The text is larger as desired, but the layout uses the original borders, so the "Foo" is going off the bottom of the screen. Is there a way make it use the new larger bounds for layout?
I know there are named fonts, so I could do:
Text("Foo").font(.title)
but I wanted to say "1.3 times bigger than .body".
Here is possible approach
Text("Hello")
.font(Font.system(size: UIFont.systemFontSize * 1.3))