SwiftUI: Text Field getting cut off - swiftui

The textField on my SwiftUI app is getting cut off. But it doesn't happen every time. It seems to happen at random.
Here is the code I'm using:
var body: some View {
VStack {
Spacer()
// Target row
HStack {
Text("Put the bullseye as close as you can to:")
Text("\(target)")
}
Spacer()
// Slider row
HStack {
Text("1")
Slider(value: $sliderValue, in: 1...100) {_ in
print(self.sliderValue)
}
Text("100")
}
Spacer()
// Hit me button row
Button(action: {
print("Button pressed")
self.alertIsVisible = true
}) {
Text(/*#START_MENU_TOKEN#*/"Hit Me!"/*#END_MENU_TOKEN#*/)
}
.alert(isPresented: $alertIsVisible) { () -> Alert in
let roundedValue = Int(sliderValue.rounded())
let score = pointsForCurrentRound()
return Alert(title: Text("Hello there!"), message: Text("The slider's value is \(roundedValue)!\n" +
"You scored \(score) points this round"
), dismissButton: .default(Text("Awesome")))
}
Spacer()
// Score and start over button row
HStack {
Button(action: /*#START_MENU_TOKEN#*/{}/*#END_MENU_TOKEN#*/) {
Text("Start Over")
}
Spacer()
Text("Score:")
Text("999999")
Spacer()
Text("Round:")
Text("999")
Spacer()
Button(action: /*#START_MENU_TOKEN#*/{}/*#END_MENU_TOKEN#*/) {
Text("Info")
}
}
.padding(.bottom, 20)
}
}
I've tried adding padding trailing the text field and before the target. I've tried adding padding to the leading edge of the target. I've tried giving using the frame method on the text field to add a min length. None of these work. Any ideas?
Thanks

You may add fixedSize() to lock the labels.
HStack {
Text("Put the bullseye as close as you can to:").fixedSize()
Text("\(target)").fixedSize()
}

I just came across this exact situation! After a few moments of searching, trial, and errors, I finally figured it out. The text view is trying to resize and one of the parent views have animations enabled. If anyone having this same issue adds .animation(nil) to the Text, this will likely solve the issue.
VStack {
Text("\(Int(self.viewModel.ProgressPercentage * 100.0))%")
.font(.largeTitle)
.animation(nil)
}
Good luck!

Related

Trouble With Constraints for a Navigation Link

Here is my code:
import SwiftUI
struct ContentView: View {
var link: some View {
NavigationLink(destination: OtherView()) {
Text("NLTitle")
}
.foregroundColor(.blue)
}
var body: some View {
NavigationView {
List {
ZStack {
HStack {
Text("1")
Spacer()
}.padding([.leading, .trailing], 20)
HStack {
Spacer()
Text("2")
.multilineTextAlignment(.center)
.frame(
alignment: .center
)
Spacer()
}
.padding([.leading, .trailing], 20)
HStack {
Spacer()
link
}.padding([.leading, .trailing], 20)
}
}
}
}
}
I have a NavigationLink (named 'link') in a list cell. I would like for the Text within 'link' to be to the rightmost side of the view. To try to accomplish this, I inserted 'link' in an HStack and put a Spacer() before it to try and push it to the rightmost part of the view. When I run the app though, the Text ends up in between Text("1") and Text("2") and I can't figure out why. I want Text("1") to be in the leftmost part of the view, Text("2") to be in the center of the view, and 'link' to be in the rightmost part of the view. I have provided visuals (the colors aren't important, I just wanted to make the different Texts clear):
Desired layout:
What I get instead:
I found that if I take everything out of the List view I get my desired layout. Also, if I keep everything in the List view and replace the NavigationLink with a Button I get my desired layout. The goal is to get the desired layout without having to change either of these aspects.
For the sake of clarity, I didn't include the code for OtherView() as I don't think it's necessary for this question.
The "quick" fix is to add fixedSize() to the NavigationLink
var link: some View {
NavigationLink(destination: Text("OtherView()")) {
Text("NLTitle")
}
.foregroundColor(.blue)
.fixedSize()
}
That will allow the link to shrink.

how can I get Text to be on one side and another text on the same line to be on the other side in a List?

NavigationView{
List{
VStack{
Text("EdwardCullen")
.padding(.vertical, -20)
AsyncImage(url)) { image in
image
.center()
} placeholder: {
ProgressView()
}
}
Text("Test")
}
.navigationTitle("EdwardCullen's Profile")
.navigationBarTitleDisplayMode(.inline)
}
Picture of what I want
I included a picture of what I want kind of, so basically "Status" on the left side of the Text and "Online" on the total other side. I also would preferably want "Online" to be green, so I think I need to use two different Text views, but how exactly would I do this in a list? Is there any good way to do this?
The way I did what is in the picture is just adding many spaces to Text like this, but obviously that is not very smart and also not exactly what I want.
Text("First Second")
Use HStack{} plus Spacer(). (Code is below the image)
var body: some View {
VStack {
HStack {
Text("First")
Spacer() //this one
Text("Second")
}
.padding()
.background(.blue)
.cornerRadius(15)
}
}
Use a spacer "Spacer()". This is an adaptive view that expands as much as it can.
NavigationView{
List{
VStack{
Text("EdwardCullen")
.padding(.vertical, -20)
AsyncImage(url)) { image in
image
.center()
} placeholder: {
ProgressView()
}
}
# new code here
HStack {
Text("Status")
Spacer()
Text("Online")
.foregroundColor(.green)
}
}
.navigationTitle("EdwardCullen's Profile")
.navigationBarTitleDisplayMode(.inline)
}
Just Use a HStack and put a spacer between two text .
sample code :
HStack{
Text("Status")
Spacer()
Text("Online")
}.cornerRadius(8)
you may use this anywhere you want .
Sample Output:

XCode SwiftUI - Why is my keypad toolbar doing this?

Very novice to the app development game. I am trying to put this toolbar above the .decimalPad and I cannot get this large gap to go away.
VStack {
Rectangle()
.foregroundColor(Color(UIColor.systemBackground))
.frame(height: 35)
.overlay {
HStack {
Spacer()
Button(action: {
isTextFieldFocused = false
}) { Text("Done")}
}
.offset(y: -3)
.padding(.trailing)
}
.opacity(isTextFieldFocused ? 1 : 0)
.ignoresSafeArea(.keyboard) //This makes sure the bottom tab bar stays below the keyboard.
}
I initially thought it was something in another view causing the spacing, but I managed to parse through the views in the canvas and it does it regardless.
Here is what I'd like it to look like, for reference.
What I want
To add a Button onto your keyboard, you use a .toolbar with the locations to .keyboard like this:
TextField("Enter Text", text: $text)
.toolbar {
ToolbarItemGroup(placement: .keyboard) {
Button(action: {
isTextFieldFocused = false
}) { Text("Done")}
// If you want it leading, then use a Spacer() after
Spacer()
}
}
You were overthinking it by adding the Rectangle. This is why we look for minimal reproducible examples. We can dial in the fix for your specific code.

Why tap Gesture of Button get triggered even out side of it's frame in SwiftUI?

I was testing accuracy of recognizing tap Gesture of a simple Button in SwiftUI, which I noticed it get activated even outside of its frame! I wanted be sure that I am not messing with label or other thing of Button, there for I build 2 different Buttons to find any improvement, but both of them get triggered in outside of given frame. I made a gif for showing issue.
gif:
code:
struct ContentView: View {
var body: some View {
Spacer()
Button("tap me!") {
print("you just tapped Button1!")
}.font(Font.largeTitle.bold()).background(Color.red)
Spacer()
Button(action: {
print("you just tapped Button2!")
}, label: {
Text("tap me!").font(Font.largeTitle.bold()).background(Color.red)
})
Spacer()
}
}
update:
some one said:
Do you see circle on click? - It is a size of active tap spot (kind of finger), and as you see, from your own demo, it overlaps red square - so gesture detected. That's it
I made another gif to show it is completely wrong to thinking like that, in this gif, even with overlaps tap get not registered!
I don't have an answer why this happens other than maybe there is some built-in functionality that increases the tappable area where possible for a better user experience? Anyway, if you put another tappable button behind it or next to it, you'll notice that this no longer happens and the tappable area is exactly where you'd expect it. Therefore, I wouldn't worry about it. But if you need to clip the tap area to the exact frame, you could add a clear background to the button and add a tap event that doesn't doesn't do anything, but takes priority on that location.
var body: some View {
VStack {
// Button behind button will take priority tap.
ZStack {
Button(action: {
print("tap 2")
}, label: {
Text("tap me!")
.padding()
.font(Font.largeTitle.bold())
.background(Color.green)
})
Button(action: {
print("tap 1")
}, label: {
Text("tap me!")
.font(Font.largeTitle.bold())
.background(Color.red)
})
}
// Clear background with "fake" tap event
Button(action: {
print("tap 3")
}, label: {
Text("tap me!")
.font(Font.largeTitle.bold())
.background(Color.red)
})
.padding()
.background(Color.black.opacity(0.001).onTapGesture {
//print("tap 4")
})
}
}
I think it's a built-in functionality to expand the tappable area:
Color.red
.frame(width: 30.0, height: 30.0)
.gesture(DragGesture(minimumDistance: 0).onEnded({ (value) in
// Tap with Apple Pencil: location is exactly the frame
// Tap with finger or an capacitance pen: the hit location is inaccurate
print(value.startLocation)
}))
Solution (Bug: If the view is inside a ScrollView, this will block scroll gesture):
let size = CGSize(width: 200.0, height: 200.0)
Color.red
.frame(width: size.width, height: size.height)
.gesture(DragGesture(minimumDistance: 0).onEnded({ (value) in
print(value.startLocation)
if value.startLocation.x >= 0 && value.startLocation.y >= 0 && value.startLocation.x <= size.width && value.startLocation.y <= size.height {
print("inside frame")
// action ...
} else {
print("outside frame")
}
}))

Dismiss button (X) on an image - top right alignment HOW?

What is an effective & effecient way to get the Dismiss button (X) into the top right corner?
I'm struggling with container alignment... can't say I GROK it.
Needless to say ... this ain't it!
var body: some View {
ZStack {
Image("Biz-card_2020")
.resizable()
.edgesIgnoringSafeArea(.all)
HStack(alignment: .top) {
VStack() {
Spacer(minLength: 5) // vertical space
HStack() {
Spacer()
// close Welcome page (X) button
Button(action: {
//print(" - Button to dismiss page \(self.isPresented)")
self.isPresented = false // dismiss the Welcome view
//print(" - after action Button to dismiss Welcome page \(self.isPresented)")
}, label: {
Image(systemName: "xmark.circle" )
.scaledFont(name: "Georgia", size: Const.titleText)
.minimumScaleFactor(0.3)
.accentColor(.white)
.padding(10)
})
}
Spacer()
}
}
}
}
You need to remove Spacer(minLength: 5) and replace it with padding for HStack.
Spacer(minLength: 5) doesn't mean its length will be exactly 5 (only that the minimum length will be 5).
You may also want to extract close button to another function for clarity.
Try the following:
struct ContentView: View {
...
var body: some View {
ZStack {
Image("Biz-card_2020")
.resizable()
.edgesIgnoringSafeArea(.all)
closeButton
}
}
var closeButton: some View {
VStack {
HStack {
Spacer()
Button(action: {
...
}) {
Image(systemName: "xmark.circle")
.padding(10)
}
}
.padding(.top, 5)
Spacer()
}
}
}
ZStack can be configured using .topTrailing etc. You should use those alignments to configure your view. Using something like Spacer() is going to cause the rest of your views to get pushed down.
ZStack(alignment: .topTrailing) {
// your code here
}
If you need to move your code a bit more, use either padding, or offset modifiers.