Search code examples
swiftswiftui

Why is a component being selected even when not being tapped swift/swiftui


I have a component called CourseCard2 with the following design:

  VStack(spacing: 0) {
                imageSection
                detailsSection
            }

        .buttonStyle(PlainButtonStyle())
        .background(
            RoundedRectangle(cornerRadius: 16)
                .fill(Color(.systemBackground))
                .shadow(
                    color: Color.black.opacity(0.08),
                    radius: 12,
                    x: 0,
                    y: 4
                )
        )
        .padding(.horizontal)
        .onTapGesture {
            showSheet = true
        }
        .sheet(isPresented: $showSheet) {
            CourseDescription(
                courseName: name,
                courseDescription: description,
                courseImage: image,
                instructor: instructors,
                youtubeVideos: youtubeLinks,
                labels: labels,
                isFree: isFree,
                ispro: ispro
            )
        }
    }
    

    private var imageSection: some View {
        image
            .resizable()
            .aspectRatio(contentMode: .fill)
            .frame(height: 180)
            .clipped()
            .cornerRadius(16, corners: [.topLeft, .topRight])
    }
    
    private var detailsSection: some View {
        VStack(alignment: .leading, spacing: 8) {
            Text(name)
                .font(.title3)
                .fontWeight(.bold)
                .lineLimit(2)
            
            labelsView
            
            instructorView
        }
        .padding()
        .frame(maxWidth: .infinity, alignment: .leading)
    }
    
    private var labelsView: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack(spacing: 8) {
                ForEach(labels, id: \.self) { label in
                    Text(label)
                        .font(.caption)
                        .padding(.horizontal, 8)
                        .padding(.vertical, 4)
                        .background(Color.blue.opacity(0.1))
                        .foregroundColor(.blue)
                        .cornerRadius(8)
                }
            }
        }
    }
    
    private var instructorView: some View {
       
        HStack(spacing: 4) {
            Image(systemName: "person.circle.fill")
                .foregroundColor(.gray)
            Text(instructors.joined(separator: ", "))
                .font(.caption)
                .foregroundColor(.gray)
        }
    }
}


extension View {
    func cornerRadius(_ radius: CGFloat, corners: UIRectCorner) -> some View {
        clipShape(RoundedCorner(radius: radius, corners: corners))
    }
}

struct RoundedCorner: Shape {
    var radius: CGFloat = .infinity
    var corners: UIRectCorner = .allCorners
    
    func path(in rect: CGRect) -> Path {
        let path = UIBezierPath(
            roundedRect: rect,
            byRoundingCorners: corners,
            cornerRadii: CGSize(width: radius, height: radius)
        )
        return Path(path.cgPath)

This component is used later in another page:

   NavigationStack{
            ScrollView {
                ScrollView(.horizontal){
                    Button(action: {
                        showSheet = true
                    }) {
                        HStack {
                            Text("Instructors")
                                .fontWeight(.bold) 
                            Image(systemName: "arrow.down") 
                        }
                        .foregroundColor(.orange) 
                        .padding(.horizontal, 16) 
                        .padding(.vertical, 8)
                   
                        .background(
                            Capsule() // Gives it a rounded, oval-like shape
                                .fill(Color.blue.opacity(0.2)) 
                        )
                    }
                    .zIndex(1000)
                   
                }
                .frame(maxHeight: 50)
                .padding(.bottom, 15)
                .padding(.leading, 15)
                    VStack{
                        ForEach(filterText){ course in
                            let image = images[course.image_ref] ?? Image("noImage")
                            CoursesCard2(name: course.Name, image: image, youtubeLinks: course.youtube_videos, description: course.Description, instructors: course.instructors, labels: course.labels, isFree: course.isfree, ispro: ispro)
                            
                                .task {
                                    await loadImage(for: course.image_ref)
                                }
                        }
                    }
            }
            .searchable(text: $searchText, prompt: "Search for courses")
                .navigationTitle("Browse Courses")
            .sheet(isPresented: $showSheet){
                AuthorCategorySelection()
                    .presentationDetents([.medium])
            }
        }

What happens though is that it becomes impossible to tap the Instructors button. It just always selects the first CourseCard2.

I tried adding a .background(Color.black) to the CourseCard2 in the ForEach loop. As seen Here, it does not take more than the card, but it is for some reason pressed every time I try to press the Instructors button.


Solution

  • Adding .contentShape(Rectangle()) to CourseCard2 answered the problem.