fermoya / SwiftUIPager

Native Pager in SwiftUI
MIT License
1.29k stars 172 forks source link

[FEAT] Page Indicator dots (`PageTabViewStyle.IndexDisplayMode`) at the bottom according page count #313

Closed rb090 closed 1 year ago

rb090 commented 1 year ago

Is your feature request related to a problem? Please describe.

I started using SwiftUIPager. I like it a lot. I want to use it, because I want to show a pager where the end of the previous element and the begging of the next element in the pager is visible:

Bildschirm­foto 2023-03-30 um 10 54 16

There is only one thing I am missing atm. This is a page indicator about the current page index like SwiftUI has for the TabView element. When I use TabView I am setting tabViewStyle to page and there I can specify the PageTabViewStyle.IndexDisplayMode:

TabView {
    ....
}
.tabViewStyle(.page(indexDisplayMode: .always))

This results in:

Bildschirm­foto 2023-03-30 um 10 07 54

Describe the solution you'd like

It would be nice to please have a ViewModifier for the Pager element to enable displaying those index indicator dots at the bottom.

But maybe there is already sth like this provided by this library and I did not find it yet? 😬

Describe alternatives you've considered

I considered to implement an own Indicator dots element similar to this:

HStack(spacing: 10){
    ForEach((0...items.count-1), id: \.self) { index in
            Circle()
                .fill(Color.black.opacity(currentPage.index == index ? 1 : 0.1))
        .frame(width: 8, height: 8)
        .animation(.spring(), value: currentPage.index == index)
    }
}
.frame(width: Const.Screen.width - 40)
.padding(.bottom, 20)

But with this I do not achieve this nice effect of dots getting "fade out" on many elements, which fe. standard on SwiftUI when using indexDisplayMode:

Bildschirm­foto 2023-03-30 um 11 02 06

Plus on many elements I end up in weird behaviors, like the ForEach overgrow the HStack container:

Bildschirm­foto 2023-03-30 um 10 50 30

When I add .clipping() after the .frame(...) on the HStack the ForEach is in the bounds of HStack, but the 1st element of the ForEach is not visible and so on. So I run in one problem after the other.

And with this I have not this "fading and shrinking" out of the page indicator view like with TabView

Additional context

/

rb090 commented 1 year ago

I solved this problem I had by building a PageControl element like @esikmalazman did it in SwiftUI-UIPageControl

And this element I put now below the Pager { ... }, so my code looks in the end like this:

VStack {
    // 'currentPage' is a '@StateObject' defined outside the `var body: some View { }` -> `@StateObject var currentPage = Page.withIndex(0)`
    Pager(page: currentPage, data: items, id: \.self) { item in
            MyView(item: item)
    }
    .sensitivity(.high)
    .preferredItemSize(CGSize(width: CONST_FOR_WIDTH, height: CONST_FOR_HEIGHT))
    .itemSpacing(12)

    // Pager element to have the page indicator
    PageControl(currentPageIndex: currentPage.index, numberOfPages: items.count).padding(.bottom, 20)
}

My colleague @sebbu gave me this tip, by moving my thoughts to UIPageControl. This UIKit element is used for UIKit pager elements and can be easily rebuild into SwiftUI.

But is there a way to please integrate the PageControl to this library and be able to enable it by a ViewModifier

fermoya commented 1 year ago

I think a PageControl is out of the scope of the library. I leave this to the user to implement if desired