I have this View
NavigationView {
GeometryReader { geometry in
List {
ForEach(self.viewModel.items) { item in
HStack(spacing: 0, content: {
ZStack {
RowItemView(data: item.FirstItem)
NavigationLink(destination: CustomView(data: item.FirstItem))
{
EmptyView()
}
}
.frame(width: geometry.size.width / 2, alignment: .center)
if (item.SecondItem != nil) {
ZStack {
RowItemView(data: item.SecondItem!)
NavigationLink(destination: CustomView(data: item.SecondItem!))
{
EmptyView()
}
}
})
}.listRowInsets(EdgeInsets())
}
}
I want to hide the disclouse arrow of the NavigationView.
I try to add .buttonStyle(PlainButtonStyle()) or add a negative trailing to the navigationLink, but it doesn't change.
I have already read this question and this one but they do not work in my case, probably because I'm creating a grid and not a plain list.
In this scenario the possible approach is to use zero frame, as following
NavigationLink(destination: CustomView(data: item.FirstItem)) {
EmptyView()
}.frame(width: 0)
Thanks to #Asperi I figured out what is the problem.
With a zero EdgeInsets in listRowInsets the arrow still show.
So I create this trick (Works in Xcode 13.3.1)
List {
ForEach(self.viewModel.items) { item in
//code for creating the row
}.listRowInsets(EdgeInsets.init(top: 8, leading: 0, bottom: 8, trailing: 0))
Put a value for both top and bottom.
I do not know if it is the correct way to get rid of that annoying arrow, but for my app it works :-)
Related
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.
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.
I would like to get the separator in SwiftUI, but I didn't find the way. This was screenshot from mail.app.
If your view elements are in a HStack (like your mail.app suggest) using Divider() will give you a vertical "separator".
Elsewhere Divider() will give you a horizontal "separator".
You can adjust its size, like this: Divider().frame(width: 123)
You can of course do more things with Dividers, such as set its thickness or height with different color:
HStack {
Divider().frame(width: 5, height: 50).background(Color.blue)
Image(systemName: "line.3.horizontal.decrease.circle")
Divider().frame(width: 10, height: 100).background(Color.pink)
Image(systemName: "envelope")
Divider().frame(width: 15, height: 150).background(Color.green)
}
Here is the right way of doing such thing, do not use Divider, because it has lots of issues. With Divider you cannot control the thickness, also it has issue with updating color, wired Xcode complain in console in some cases, also space issue, it takes more space than it needs. In general it does not worth to use it.
struct ContentView: View {
var body: some View {
HStack {
Group {
Image(systemName: "mail")
Capsule().fill(Color.secondary).frame(width: 2.0)
Image(systemName: "trash")
}
.frame(width: 25, height: 25)
}
}
}
One alternative solution that may be more useful in some cases (e.g if you want a customisable toolbar the accepted solution won't work):
ToolbarItem (placement: .primaryAction) {
HStack {
Divider()
}
}
I'm trying to use NavigationLink inside List. For a specific reason, it is in .background with EmptyView().
var body: some View {
List {
Section {
HStack {
Image(systemName: "checkmark")
.frame(width: 30, height: 30, alignment: .center)
.opacity(selected ? 1 : 0)
Text("TEST")
Spacer()
}
.onTapGesture {
selected.toggle()
}
.background(
NavigationLink(destination: WifiView()) { EmptyView() }
.disabled(isPad)
)
}
}
}
The problem is the touch area for the NavigationLink is not as expected.
.background's area is as above.
but NavigationLink and EmptyView's area is as above. I tried to force the frame with .frame but it won't change.
What am I missing?
try something like this, works well for me:
var body: some View {
List {
Section {
HStack {
Image(systemName: "checkmark")
.frame(width: 30, height: 30, alignment: .center)
.opacity(selected ? 1 : 0)
Text("TEST")
Spacer()
}
.contentShape(Rectangle()) // <--- here
.onTapGesture {
selected.toggle()
}
.background(
NavigationLink(destination: WifiView()) { EmptyView() }
.disabled(isPad)
)
}
}
}
To distill the accepted answer: all you need to do is to add .contentShape(Rectangle()) to the same element which has .onTapGesture. This solution works for any container, not just List.
E.g. if you have:
VStack {
// ...
}
.onTapGesture {
// ...
}
Add contentShape to the same element:
VStack {
// ...
}
.contentShape(Rectangle())
.onTapGesture {
// ...
}
Rationale:
If you add a tap gesture to a container SwiftUI view, such as VStack or HStack, then SwiftUI only adds the gesture to the parts of the container that have something inside – large parts of the stack are likely to be untappable.
If this is what you want then the default behavior is fine. However, if you want to change the shape of hit tests – the area that responds to taps – then you should use the contentShape() modifier with the shape you want.
(source)
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.