1
votes

I am trying to create an app, where I have a horizontal scrollview inside list. And tapping on that horizontal scrollview, each item should navigate to another screen and there is a button on each item, which shows the context menu. But, both of these functionalities don't work together. If navigatiionlink works, menu doesnt pop up on tapping(it does pop on long press though).

Here's the code:

    
    var categoryName: String
    
    var items: [Post]
    
    var body: some View {
        
        VStack(alignment: .leading) {
            
            Text(categoryName)
                
                .font(.headline)
                
                .padding(.leading, 15)
            
            ScrollView(.horizontal, showsIndicators: false) {
                
                HStack(alignment: .top, spacing: 0) {
                    
                    ForEach(items) { post in
                        
                        VStack {
                            
                            NavigationLink(
                                destination: PostView(post: post)) {
                                EmptyView()
                            }
                        
//                            NavigationLink(
//                                destination: PostView(post: post)) {
                                
                                CategoryItem(categoryName: "Featured", post: post)
                                    
                                    .frame(width: (UIScreen.main.bounds.width - 90), height: 155)
                                    
                                    .padding(.leading, 10)
                                    
                                    .onAppear {
                                        if (self.items.last?.id == post.id) {
                                            print("Last Featured")
                                        }
                                    }
//                            }
                        }
                        
                    }
                    
                }
                
            }
            
            .frame(height: 185)
            
            .padding(.top, 0)
            
        }
        
    }
    
}

And here is the category item:

VStack(alignment: .trailing, spacing: nil, content: {
                
                Menu {
                    
                    VStack {
                        
                        Button(action: {
                            print("Hello")
                            if (!checkIfAlreadySaved(post: post, viewContext: viewContext)) {
                                self.bookmarkPost(post: post, viewContext: viewContext) {
//                                    self.isBookmarked = true
                                }
                            } else {
                                self.unBookmarkPost(post: post, viewContext: viewContext) {
//                                    self.isBookmarked = false
                                }
                            }
                        }) {
                            Text(!checkIfAlreadySaved(post: post, viewContext: viewContext) ? "Add to Favourites" : "Remove from Favourites")
                        }
                        Button(action: {
                            print("Hello")
                            self.actionSheet(urlString: post.link)
                        }) {
                            Text("Share")
                        }
                        
                    }

                }  label: {
                    Image(systemName: "ellipsis")
                        
                        .font(.subheadline)
                        
                        .foregroundColor(.white)
                        
//                        .rotationEffect(.degrees(-90))
                        
                        //                        .position(CGPoint(x: 0.0, y: 20.0))
                        
//                        .frame(width: 30, height: 30, alignment: .trailing)
                        
                        .padding(8)
                    
//                        .zIndex(2.0)
                        
                }
            })

There is more code in CategoryItem too, but, there are just other views and all of this is inside ZStack.

With the above code, menu pops up, but navigation link doesn't work. As you can see, I have also tried putting CategoryItem inside NavigationLink(commented out code), this results in navigationlink being working, but menu only pops on long press.

Can anyone please help with this? Thanks

P.S. The whole view is navigated from another view, which is embedded inside a List, which is further embedded in a NavigationView. Also, the issue is in a scrollview, it works with list, but i need a horizontal scroll view, so, can't use that.

1

1 Answers

1
votes

It could be how you are organizing your Views maybe the ZStack you aren't showing is what is conflicting.

In your code the NavigationLink likely doesn't pop up because you have made it an EmptyView

If you make clear distinctions for the tappable areas you should not have an issue.

The first example makes the tappable area for the ellipsis a small square

import SwiftUI

struct NavLinkMenuView: View {
    var body: some View {
        GeometryReader{geo in
            NavigationView{
                List{
                    ForEach(0..<3){ count in
                        VStack{
                            Text("category \(count)")
                            NavLinkRowView(geo: geo)
                        }
                    }
                }.listStyle(PlainListStyle())
            }
        }
    }
}
struct NavLinkRowView: View {
    let geo: GeometryProxy
    var body: some View {
        ScrollView(.horizontal){
            HStack{
                ForEach(0..<15){ count in
                    ZStack{
                        //The the user to the next page
                        NavigationLink(destination: Text(count.description), label: {
                            Text(count.description)
                            //Make the NavigationLink take all the available space
                                .frame(maxWidth: .infinity, maxHeight: .infinity)
                            //Just to make a visible marke of the view
                                .border(Color.green, width: 2)
                        })
                        HStack{
                            Spacer()
                            //CategoryItem
                            VStack(alignment: .trailing, spacing: nil){
                                Menu(content: {
                                    Text("context menu")
                                }, label: {
                                    
                                    Image(systemName: "ellipsis")
                                    //stretch the tappable area to the ellipsis column
                                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                                    
                                        .font(.subheadline)
                                        .foregroundColor(.gray)
                                        .padding(8)
                                }
                                )
                            }
                            .aspectRatio(1, contentMode: .fit)
                            //Limit the size of the ellipsis column
                            .frame(maxWidth: geo.size.width * 0.08)
                            
                            //Just to make a visible marke of the view
                            .border(Color.red)
                        }
                    }
                    //Just to make a visible marke of the view
                    .border(Color.orange)
                    //Size of the overall view
                    .frame(width: (geo.size.width - 90), height: 155)
                    //Just to make a visible marke of the view
                    .border(Color.blue)
                    .padding(.leading, 10)
                }
            }
        }
    }
}

The second example creates a tappable column for the ellipsis

import SwiftUI

struct NavLinkMenuView: View {
    var body: some View {
        GeometryReader{geo in
            NavigationView{
                List{
                    ForEach(0..<3){ count in
                        VStack{
                            Text("category \(count)")
                            NavLinkRowView(geo: geo)
                        }
                    }
                }.listStyle(PlainListStyle())
            }
        }
    }
}
struct NavLinkRowView: View {
    let geo: GeometryProxy
    var body: some View {
        ScrollView(.horizontal){
            HStack{
                ForEach(0..<15){ count in
                    HStack(spacing: 0){
                        //The the user to the next page
                        NavigationLink(destination: Text(count.description), label: {
                            Text(count.description)
                            //Make the NavigationLink take all the available space
                                .frame(maxWidth: .infinity, maxHeight: .infinity)
                            //Just to make a visible marke of the view
                                .border(Color.green, width: 2)
                        })
                        
                        //CategoryItem
                        VStack(alignment: .trailing, spacing: nil){
                            Menu(content: {
                                Text("context menu")
                            }, label: {
                                
                                Image(systemName: "ellipsis")
                                //stretch the tappable area to the ellipsis column
                                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                                
                                    .font(.subheadline)
                                    .foregroundColor(.gray)
                                    .padding(8)
                            }
                            )
                        }
                        //Limit the size of the ellipsis column
                        .frame(maxWidth: geo.size.width * 0.08, maxHeight: .infinity)
                        
                        //Just to make a visible marke of the view
                        .border(Color.red)
                        
                    }
                    //Just to make a visible marke of the view
                    .border(Color.orange)
                    //Size of the overall view
                    .frame(width: (geo.size.width - 90), height: 155)
                    //Just to make a visible marke of the view
                    .border(Color.blue)
                    .padding(.leading, 10)
                }
            }
        }
    }
}