Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change selected segment color in SwiftUI Segmented Picker

Tags:

ios

swift

swiftui

I want to set the selected segment color in a SwiftUI segmented picker and change the text color to white.

I have tried both using the modifiers for the picker view and modifying the tint color from the appearance proxy. None of them seem to work, unfortunately.


import SwiftUI

struct PickerView: View {

    @State var pickerSelection = 0

    init() {
        UISegmentedControl.appearance().tintColor = UIColor.blue
    }

    var body: some View {
        Picker(selection: $pickerSelection, label: Text("")) {
            Text("Active").tag(0).foregroundColor(Color.white)
            Text("Completed").tag(1)
        }.pickerStyle(SegmentedPickerStyle()).foregroundColor(Color.orange)
    }
}

Is there any way to do this in SwiftUI, or should I just use the UISegmentedControl by using UIViewControllerRepresentable?

like image 257
swifty Avatar asked Aug 31 '19 06:08

swifty


2 Answers

Native ( but limited )

SwiftUI is not currently supporting native SegmentedPicker styling (see the bottom of the answer for the working workaround). But there is a limited way to apply a color to the segmented picker using .colorMultiply() modifier:

enter image description here


Full control using UIAppearance

selectedSegmentTintColor is available since beta 3 for changing the color of the selected segment.

For changing the textColor, you should use setTitleTextAttributes for .selected state and .normal state (unselected).

So it will be like:

init() {
    UISegmentedControl.appearance().selectedSegmentTintColor = .blue
    UISegmentedControl.appearance().setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)
    UISegmentedControl.appearance().setTitleTextAttributes([.foregroundColor: UIColor.blue], for: .normal)
}

Segmented Controll

Also as mike mentioned, you can set the background color too like:

UISegmentedControl.appearance().backgroundColor = .yellow

Background demo

Also, don't forget you can set SwiftUI colors too! For example:

UISegmentedControl.appearance().selectedSegmentTintColor = UIColor(Color.accentColor)
like image 91
Mojtaba Hosseini Avatar answered Oct 24 '22 09:10

Mojtaba Hosseini


Recently I had a similar issue that I needed a custom background and foreground colors for SwiftUI SegmentedControl I've found this post that also was helpful, but I also wanted to share other solution that I've found and I'm using now. There is a very nice package called SwiftUI Introspect that allows to, well...

Introspect underlying UIKit components from SwiftUI

With this package I created the following SegmentedControl enter image description here With this code:

VStack {
    Picker("Activity view", selection: $selectedActivity) {
        ForEach(ActivityView.allCases) { activity in
            Text(activity.description)
        }
    }
    .introspectSegmentedControl { segmentedControl in
        segmentedControl.backgroundColor = .clear
        segmentedControl.tintColor = TCHColors.SegmentedControl.backgroundSelected
        segmentedControl.selectedSegmentTintColor = TCHColors.SegmentedControl.backgroundSelected
        segmentedControl.setTitleTextAttributes([
            NSAttributedString.Key.foregroundColor: TCHColors.SegmentedControl.selectedText
        ], for: .selected)
        segmentedControl.setTitleTextAttributes([
            NSAttributedString.Key.foregroundColor: TCHColors.SegmentedControl.normalText
        ], for: .normal)
    }
    .pickerStyle(.segmented)
}
.padding(.horizontal, 16)

And you can use this package to access many other underlying components from SwiftUI.

like image 2
Sangsom Avatar answered Oct 24 '22 10:10

Sangsom