Is there a way to hide the arrow to the right of the navigation link view that is automatically added?
I want to show an image grid using NavigationView -> List -> HStack -> NavigationLink_1 - NavigationLink_2
Is there a way to hide the arrow to the right of the navigation link view that is automatically added?
I want to show an image grid using NavigationView -> List -> HStack -> NavigationLink_1 - NavigationLink_2
The way it worked for me:
List {
ForEach(elements) { element in
ZStack {
CustomView(element: element)
NavigationLink(destination: DestinationView()) {
EmptyView()
}.buttonStyle(PlainButtonStyle())
}
}
}
Rectangle().opacity(0.0)
instead of EmptyView()
for List, it worked. –
Shebashebang The easiest way I've found is to place the navigation in the .background
modifier with the opacity
of zero:
List {
Text("The cell")
.background(
NavigationLink("", destination: Text("The detail view"))
.opacity(0)
)
}
And with this solution you don't loose the dynamic height functionality of the cells.
Bonus: Using .overlay
modifier works too!
The way it worked for me:
List {
ForEach(elements) { element in
ZStack {
CustomView(element: element)
NavigationLink(destination: DestinationView()) {
EmptyView()
}.buttonStyle(PlainButtonStyle())
}
}
}
Rectangle().opacity(0.0)
instead of EmptyView()
for List, it worked. –
Shebashebang I got it done with this
NavigationLink(destination: DestinationView()) {
EmptyView()
}
.frame(width: 0, height: 0)
.hidden()
The only thing that helped me is to add .opacity(0)
to NavigationLink like so:
List {
ForEach(elements) { element in
ZStack {
CustomView(element: element)
NavigationLink(destination: DestinationView()),
label: {}).opacity(0)
}
}
}
List {
ForEach(elements) { element in
ZStack {
CustomView(element: element)
NavigationLink(destination: DestinationView()) {
EmptyView()
}.opacity(0.0)
}
}
}
Finally found out a way how to avoid the the chevron without doing some tricky ZStacks
and other solutions. The only downside is that this is only tested on iOS 16 with the new NavigationPath
+ NavigationStack
.
Instead of using a regular NavigationLink
where you apply the hashable
object, you'll just use a regular Button
and append the object to the NavigationPath
.
@State private var path = NavigationPath()
var body: some View {
List {
ForEach(viewModel.customers) { customer in
Button {
path.append(customer)
} label: {
CustomerCell(customer: customer)
}
}
}
.navigationDestination(for: Customer.self) { customer in
CustomerView(customer: customer)
}
}
For projects using the NavigationBackport (for preparing the new navigation), it might work as well. As you can use NBNavigationPath
and append the object to the path with a Button
just like the example above.
I've also struggled with this recently and I think I've found a solution by using a custom view for the navigation link (it works for me):
struct CustomNavigationLink<D: View, L: View>: View {
@ViewBuilder var destination: () -> D
@ViewBuilder var label: () -> L
@State private var isActive = false
var body: some View {
Button {
withAnimation {
isActive = true
}
} label: {
label()
}
.onAppear {
isActive = false
}
.overlay {
NavigationLink(isActive: $isActive) {
destination()
} label: {
EmptyView()
}
.opacity(0)
}
}
}
And you use like this:
CustomNavigationLink {
SomeViewHere()
} label: {
Text("hello world")
}
@State var selection: Int? = nil
var body: some View {
let navigation = NavigationLink(destination: Text("View"), tag: 1, selection: $selection) { EmptyView() }
return
VStack {
navigation
Text("Tap").onTapGesture { self.selection = 1 }
}
}
Form
: ` var body: some View { Form { NavigationLink(destination: Text("View"), tag: 1, selection: $selection) { EmptyView() } Text("Tap").onTapGesture { self.selection = 1 } } } ` NOTE: the VStack
in the above example isn't needed. –
Segmentation This is what worked for me, just adding an empty NavigationLink
in a ZStack
List(viewModel.items, id: \.id) { item in
ZStack {
NavigationLink(destination: Destination()) {}
CustomView(item: item)
}
}
Setting .opacity(0)
on the NavigationLink
seems to be the most reliable solution for me because I noticed that it might show the indicators again when messing with the .listStyle
property. You will also not lose the highlighted effect.
var body: some View {
NavigationView {
List {
ForEach(items) { item in
ZStack(alignment: .leading) {
NavigationLink(destination: EmptyView()) {
EmptyView()
}
.opacity(0)
Text(item.value)
}
}
}
}
}
2023 Update
This simple solution works for me:
ZStack {
CustomCell()
NavigationLink(destination: DetailView()) {
EmptyView()
}
.opacity(0)
}
Only this worked for me, when I tried to implement button tap inside row in List:
ZStack {
NavigationLink(destination: FlightBoardInformation(flight: flight), tag: FlightBoardNavigation.toFlightDetailed, selection: $navigation) {
EmptyView()
}
.frame(width: 0, height: 0)
.hidden()
.disabled(true)
Button(action: {
self.navigation = .toFlightDetailed
}) {
Text("\(self.flight.airline) \(self.flight.number)")
}.buttonStyle(PlainButtonStyle())
}
Although .background(...).opacity(0)
works, in a more complex view it expands itself through all the view and conflicts with other elements like buttons.
If you need it inside a List
, what worked for me is also marking the NavigationLink
as .disabled(true)
:
Text(...)
.background( NavigationLink(...).opacity(0).disabled(true) )
Use .background
modifier.
ForEach(elements) { e in
AnyViewYouWantToShow(e)
.background(
NavigationLink("", destination: DestinationView()))
.opacity(0)
)
}
Works for me on iOS 16/17
NavigationLink(destination: YourView) {
Color.clear // or EmptyView, etc.
}
.foregroundStyle(Color.clear)
.opacity(0)
also works but in my case I needed .foregroundStyle(Color.clear)
For some reason with .opacity(0)
the NavigationLink
is not working if I put it outside of the ListView
.
The best workaround for me is using background
:
NavigationLink(...) {}
.opacity(0)
.background(
HStack {
Text("Your custom view without arrow")
}
)
Or if you need dynamic height as @turingtested posted use NavigationLink as background
Text("Your custom view without arrow")
.background(NavigationLink( ... ) {}.opacity(0))
NavigationLink
in the background of your HStack
), per the explanation by @turingtested, is better. –
Francophobe though there is lots of solution. I'm posting my one.
var body: some View {
VStack{
List{
ForEach (items){item in
switch item.onClick {
//For SettingsOverviewView
case .Settings:
ZStack{
NavigationLink (destination: SettingsMenuView(item: item)){
EmptyView()
}
.opacity(0.0)
.buttonStyle(PlainButtonStyle())
//some views that you will show as your listItem
HStack {
Text(item.name)
.font(.body)
Spacer()
}
}
}
}
.listStyle(GroupedListStyle())
}
}
}
A lot of examples playing around with ZStack
and .opacity
but for my opinion SwiftUI can offer more elegant solution using NavigationLink
with isActive
parameter that works perfect with .listRowSeparator
or .listStyle
modificators:
struct HidingNavArrowInList: View {
let planets = ["Mars", "Sun", "Mercury", "Venus", "Jupiter", "Uranus", "Saturn", "Earth"]
@State var selectedPlanet: String?
@State var showDetailView = false
var body: some View {
NavigationView {
List {
ForEach(planets, id: \.self) { planet in
Text(planet)
.onTapGesture {
segue(planet: planet)
}
}
}
.background(
NavigationLink(isActive: $showDetailView, destination: {
if let unwrappedPlanet = selectedPlanet {
VStack {
Text("This is detail view of \(unwrappedPlanet)")
}
}
}, label: {
EmptyView()
})
)
}
}
private func segue(planet: String) {
selectedPlanet = planet
showDetailView.toggle()
}
}
'init(isActive:destination:label:)' was deprecated in iOS 16.0: use NavigationLink(value:label:) inside a NavigationStack or NavigationSplitView
Deprecated for iOS 16 –
Imputation In my case, foregroundColor modifier works for me.
NavigationLink(EmptyView(), label: {
//place your custom view
Text("your Label")
}).buttonStyle(PlainButtonStyle()).foregroundColor(Color.clear)
To hide the navigation link forward arrow icon we have to do the following steps.
Here is the code -
List($store.models, id: \.id) { model in
CustomListItem(model: model.wrappedValue)
.overlay {
NavigationLink {
DetailView()
} label: {
EmptyView()
}
.opacity(0) //this will hide the arrow icon.
}
.listRowSeparator(.hidden)
}
.listStyle(.plain)
You can also do like: This worked for me,
@State var boolValue: Bool = false
HStack {
Text("Your text")
Toggle(isOn: $boolValue){
Text("")
}
if boolValue {
NavigationLink(destination: DestinationView()) {
EmptyView()
}.frame(width: 0)
}
}
It also works with any View (not only Text)
ZStack {
Text("Some text")
NavigationLink(destination: Text("Hello")) {
EmptyView()
}.frame(width: 0)
}
I set the opacity
of the navigationLink
to zero and it work like a charm
NavigationLink(
destination: Text("Destination"),
label: {}
).opacity(0)
© 2022 - 2024 — McMap. All rights reserved.