Nested Tab Views Scrolling SwiftUI

92 Views Asked by At

I am facing an issue with nested TabViews for an iOS project with SwiftUI. In the code below, you can see that I have 2 TabVies vertically stacked and each TabView has an inner TabView with three images. This works how I want it, meaning I always scroll element wise - nothing in between.

But when I scroll horizontally, and get to the first/last image and scroll again, nothing happens. Normally, in apps like Instagram or BeReal, when you scroll further, the last image is scrolled a bit to the side, but not more, because there is no next image. I am talking about the 'animation' that signals the user, that there is no further image, but his scrolling was recognised. In my current solution, it feels like the scrolling was not recognised.

I don't know what the issue could be. For the outer TabView, it works and if I just have the inner Tab View for one image, it works too.

Hope somebody can help :)

import SwiftUI

struct ScrollablePieceView: View {
    
    let pieces: [(name: String, amount: Int)] = [
        ("julz", 3),
        ("klara", 3)
    ]
    
    var body: some View {
        GeometryReader { geometry in
            TabView {
                ForEach(pieces.indices, id: \.self) { pieceIndex in
                    let piece = pieces[pieceIndex]
                    let imageCount = piece.amount
                    let imageNamePrefix = piece.name
                    
                    TabView {
                        ForEach(1...imageCount, id: \.self) { imageIndex in
                            ImageItemView(imageName: "\(imageNamePrefix)_\(imageIndex)")
                        }
                    }
                    .frame(
                        width: geometry.size.width,
                        height: geometry.size.height * 0.65
                    )
                    .rotationEffect(.degrees(-90))
                    .tabViewStyle(PageTabViewStyle())
                }
            }
            .frame(
                width: geometry.size.height,
                height: geometry.size.width
            )
            .rotationEffect(.degrees(90), anchor: .topLeading)
            .offset(x: geometry.size.width)
            .tabViewStyle(
                PageTabViewStyle(indexDisplayMode: .never)
            )
        }
    }
}
1

There are 1 best solutions below

1
Anshul On

it seems like the inner TabView isn't providing the bounce effect when reaching the end of the content. This might be due to the specific setup of your nested TabViews, especially with the use of rotationEffect for creating a vertical paging effect.

SwiftUI doesn't expose direct control over the bounce behavior of a TabView, as it's generally handled automatically. The lack of a bounce effect in your inner TabView could be an unintended consequence of this automatic handling, particularly when nested inside another TabView and transformed with rotations

struct ContentView: View {
    // Define a simple list of images
    let images = ["photo", "photo.fill", "bookmark", "bookmark.fill", "paperplane", "paperplane.fill"]

    var body: some View {
        TabView {
            ForEach(images.indices, id: \.self) { index in
                GeometryReader { geometry in
                    VStack {
                        Text("Image \(index + 1)")
                            .font(.headline)
                            .padding()
                        Image(systemName: images[index])
                            .resizable()
                            .scaledToFit()
                            .frame(maxWidth: .infinity)
                            .padding()
                            .background(Color.secondary.opacity(0.1))
                            .cornerRadius(10)
                            .padding()
                            // Here we add a simple visual cue to indicate the image is at the start or end
                            .border(index == 0 || index == images.count - 1 ? Color.red : Color.clear, width: 4)
                            .onTapGesture {
                                // Example of adding a tap gesture to each image
                                print("Tapped on Image \(index + 1)")
                            }
                    }
                    .frame(width: geometry.size.width, height: geometry.size.height)
                }
            }
        }
        .tabViewStyle(PageTabViewStyle())
        .indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .always))
    }
}

enter image description here