Navigationlink Inside Lazyvgrid Cycles All Entries on Back, Swiftui

NavigationLink inside LazyVGrid cycles all entries on back, SwiftUI

It is Form/List feature to auto-detect links in rows, but you have several in row, so the effect. The solution would be to separate cell view and hide link from auto-detection.

Tested with Xcode 12.0 / iOS 14

struct ContentView: View {
@State var images:[String] = ["plus", "minus"]
var body: some View {
NavigationView {
Form {
Section {
LazyVGrid(columns: [GridItem(.adaptive(minimum:100))]){
ForEach(images){
ImageCellView(image: $0)
}
}
}
}
}
}
}

struct ImageCellView: View {
var image: String
@State private var isActive = false
var body: some View {
Image(uiImage: UIImage(systemName: image)!)
.resizable()
.scaledToFit()
.onTapGesture {
self.isActive = true
}
.background(
NavigationLink (
destination: ImageDetail(image: image), isActive: $isActive,
label: {
EmptyView()
}
))
}
}

SwiftUI NavigationLink in LazyVGrid picking random index

You activate all links at once (because all of them depends on one state). Instead we need to use different NavigationLink constructor for such cases.

Here is fixed variant. Tested with Xcode 12.1 / iOS 14.1

struct TestView: View {
let columns = [
GridItem(.flexible())
]
@State var selectedItem: Int?

var body: some View {
ScrollView {
LazyVGrid(columns: columns, spacing: 20) {
ForEach(1...10, id: \.self) { index in
Text("\(index)")
.background(NavigationLink(destination: TestDetail(index: index), tag: index, selection: $selectedItem) {
EmptyView()
}).onTapGesture {
selectedItem = index
}
}
}
}
}
}

Assigning NavigationLink to Images within Array in Swift UI

For occasions like this I would prefer an enum that holds all related information. You also could do this with a struct the reasoning behind this stays the same.

enum ImageEnum: String, CaseIterable{ //Please find a better name ;)
case image1, image2

var imageName: String{ // get the assetname of the image
switch self{
case .image1:
return "test"
case .image2:
return "test2"
}
}

@ViewBuilder
var detailView: some View{ // create the view here, if you need to add
switch self{ // paramaters use a function or associated
case .image1: // values for your enum cases
TestView1()
case .image2:
TestView2()
}
}
}


struct TestView1: View{
var body: some View{
Text("test1")
}
}

struct TestView2: View{
var body: some View{
Text("test2")
}
}

And your Grid View:

struct Grid: View {

var columnGrid: [GridItem] = [GridItem(.flexible(), spacing: 25), GridItem(.flexible(), spacing: 25)]

var body: some View {
NavigationView{ // Add the NavigationView
LazyVGrid(columns: columnGrid, spacing: 50) {
ForEach(ImageEnum.allCases, id:\.self) { imageEnum in // Itterate over all enum cases
NavigationLink(destination: imageEnum.detailView){ // get detailview here
Image(imageEnum.imageName) // get image assset name here
.resizable()
.scaledToFill()
.clipped()
.cornerRadius(25)
}
}
}
}
}
}

Result:

Result

The Back button messes up the view

Your issue is that you have duplicate NavigationViews. There are two ways to solve this:

  1. When you call the next view in your NavigationLink, set .navigationBarBackButtonHidden(true). This will disappear the extra back button.

  2. A simpler way; just delete the NavigationView in your second view (the linked one). That will prevent duplicate back buttons.

SwiftUI: NavigationLink unintentionally tappable and activated inside Form

The solution is to hide link into background of some view, like below

Form {
Section {
VStack {
Text("Hello")
.background(
NavigationLink(destination: Text("Detail View"), isActive: $showNext)
{ EmptyView() }.disabled(!showNext)
)
}
}
}

SwiftUI NavigationLink Hide Arrow

The way it worked for me:

List { 
ForEach(elements) { element in
ZStack {
CustomView(element: element)
NavigationLink(destination: DestinationView()) {
EmptyView()
}.buttonStyle(PlainButtonStyle())
}
}
}

SwiftUI - Setting maxHeight does nothing for Text() inside LazyVGrid()

You just need to set the idealHeight to 80 as well.

Text(buttons[index])
.font(.system(size: 30))
.foregroundColor(Color.white)
.frame(maxWidth: 80, idealHeight: 80, maxHeight: 80) // <- Here
.background(RoundedRectangle(cornerRadius: 8).fill(getButtonColour(char: buttons[index]).opacity(Double(index) / Double(buttons.count) + 0.1)))

Result (colors may look different because I don't have all the functions):

Result


Additionally, in the screenshot you can see not all the characters are shown. You should change the range in the ForEach to 0 ..< buttons.count to fix this.



Related Topics



Leave a reply



Submit