Pingo
Pingo

Reputation: 533

change TabView indicator color SwiftUI

enter image description here

Is there a way to change the tabView Indicator color in swiftUI ?

This is my code

struct OnBoarding: View {
    var body: some View {
        TabView {
            ForEach(0 ..< 3) { item in
                VStack {
                    Image("discover")
                        .resizable()
                        .scaledToFit()
                }
            }
        }
        .tabViewStyle(PageIndexViewStyle(backgroundDisplayMode: Color ?))   
    }
}

struct OnBoarding_Previews: PreviewProvider {
    static var previews: some View {
        OnBoarding()
    }
}

I tried tabViewStyle(PageIndexViewStyle(backgroundDisplayMode: Color ?)), but can't get around with it.

Upvotes: 33

Views: 22502

Answers (6)

Jason Armstrong
Jason Armstrong

Reputation: 1250

Needed to do this, this morning and decided to whip up a ViewModifier. The benefit of this approach is it sets it back to the previous value once the tab view disappears.

To use:

TabView {
    // ...
}
.tintedTabViewStyle()

The Modifier:

import SwiftUI

extension View {
    func tintedTabViewStyle(_ pageTabViewStyle: PageTabViewStyle = .page, color: Color = .accentColor) -> some View {
        self.modifier(TintedPageViewTabStyleModifier(pageTabViewStyle: pageTabViewStyle, color: color))
    }
}

struct TintedPageViewTabStyleModifier: ViewModifier {
    var pageTabViewStyle: PageTabViewStyle
    var color: Color

    @State private var originalCurrentPageIndicatorTintColor: UIColor?
    @State private var originalPageIndicatorTintColor: UIColor?

    func body(content: Content) -> some View {
        content
            .tabViewStyle(pageTabViewStyle)
            .onAppear {
                let appearance = UIPageControl.appearance()
                originalCurrentPageIndicatorTintColor = appearance.currentPageIndicatorTintColor
                originalPageIndicatorTintColor = appearance.pageIndicatorTintColor
            
                appearance.currentPageIndicatorTintColor = UIColor(color)
                appearance.pageIndicatorTintColor = UIColor(color.opacity(0.2))
        }
            .onDisappear {
                guard let originalCurrentPageIndicatorTintColor,
                        let originalPageIndicatorTintColor else { return }
                let appearance = UIPageControl.appearance()
                appearance.currentPageIndicatorTintColor = originalCurrentPageIndicatorTintColor
                appearance.pageIndicatorTintColor = originalPageIndicatorTintColor
            }
    }
}

Upvotes: 0

Fran
Fran

Reputation: 554

If you simply don't want to mess with UIKit on SwiftUI, or you need to give the color after init:

Create your own! and have total style control

enter image description here

@State private var tabSelection = 0

var body: some View {
 ZStack(alignment:.bottom){
    TabView(selection: $tabSelection.animation()){
                                Text("Slide 1")
                                    .frame(maxWidth: .infinity)
                                    .tag(0)
                                Text("Slide 2")
                                    .frame(maxWidth: .infinity)
                                    .tag(1)
                                Text("Slide 3")
                                    .frame(maxWidth: .infinity)
                                    .tag(2)
                            }
                            .aspectRatio(1, contentMode: .fit)
                            .frame(maxWidth: .infinity)
                            .tabViewStyle(.page(indexDisplayMode: .never))
     HStack(spacing: 6){
              ForEach(0..<3) { i in
                  Image(systemName: "circle.fill")
                      .font(.system(size: 9))
                      .foregroundStyle(tabSelection == i ? .black : .gray)
               }
     }
                            .padding(.bottom)
 }
}

Upvotes: 6

podkovyr
podkovyr

Reputation: 145

If you are using SwiftUI from UIKit there's a more delicate way to update UIPageControl appearance.

// SwiftUI with with UIPageControl
struct MyView: View { ... }
import SwiftUI
import UIKit

final class MyViewContainerController: UIHostingController<MyView> {
    init() {
        let view = MyView()
        super.init(rootView: view)
    }

    @available(*, unavailable)
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        let containerTypes = [MyViewContainerController.self]
        let appearance = UIPageControl.appearance(whenContainedInInstancesOf: containerTypes)
        appearance.currentPageIndicatorTintColor = .systemBlue
        appearance.pageIndicatorTintColor = .systemIndigo
    }
}

Upvotes: 6

Mahmudur Rahman
Mahmudur Rahman

Reputation: 639

First create a subview like:

struct SliderTabView: View {
init() {
          UIPageControl.appearance().currentPageIndicatorTintColor = .red
          UIPageControl.appearance().pageIndicatorTintColor = UIColor.red.withAlphaComponent(0.2)
       }
var body: some View {
    TabView{
        ForEach(players){ player in
            //Slider content here ...
        }
    }.tabViewStyle(PageTabViewStyle(indexDisplayMode: .always))
}

Call the subview from main view like:

    struct ContentView: View {
          var body: some View {
                                 SliderTabView()
                              }
                             }

the output look like of me: enter image description here

Upvotes: 6

Rufat Mirza
Rufat Mirza

Reputation: 1533

Basically you need to set the global variable when your view appears. One way to do it is as follows:

import SwiftUI

struct OnboardingView: View {
  
  var pages: [Page]
  
  var body: some View {
  
    TabView {
      ForEach(pages) { page in
        // Your component view
      }
    }
    .tabViewStyle(PageTabViewStyle())
    .onAppear {
      setupAppearance()
    }
  }
  
  func setupAppearance() {
    UIPageControl.appearance().currentPageIndicatorTintColor = .black
    UIPageControl.appearance().pageIndicatorTintColor = UIColor.black.withAlphaComponent(0.2)
  }
}

Upvotes: 29

Achraf
Achraf

Reputation: 1520

you need to use UIkit

 init() {
    UIPageControl.appearance().currentPageIndicatorTintColor = .red
    UIPageControl.appearance().pageIndicatorTintColor = UIColor.black.withAlphaComponent(0.2)
    }

Upvotes: 58

Related Questions