Changing Slider thumb in SwiftUI
Asked Answered
E

3

5

is it possible to change the thumb of a Slider in SwiftUI like you can with a UISlider in UIKit? With a UISlider all you have to do is: self.setThumbImage(UIImage(named: "Play_black"), for: .normal)

Eugenioeugenius answered 27/8, 2021 at 15:14 Comment(1)
Does this answer your question? How customise Slider blue line in SwiftUI?Aetna
U
11

You can do this with SwiftUI-Introspect.

You are basically just accessing the underlying UISlider from SwiftUI's Slider, and then setting it there. This is much easier than creating a custom slider or making a representable.

Code:

struct ContentView: View {
    @State private var value: Double = 0

    var body: some View {
        Slider(value: $value)
            .introspectSlider { slider in
                slider.setThumbImage(UIImage(named: "Play_black"), for: .normal)
            }
    }
}

Result (temporary image):

Unknowing answered 27/8, 2021 at 15:44 Comment(0)
T
6

You can do this using UIKit's appearance in SwiftUI.

Example:

struct CustomSlider : View {
    @State private var value : Double = 0
    init() {
        let thumbImage = UIImage(systemName: "circle.fill")
        UISlider.appearance().setThumbImage(thumbImage, for: .normal)
    }
    
    var body: some View {
        Slider(value: $value)
    }
}
Topsyturvydom answered 18/7, 2022 at 2:46 Comment(3)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Sunshine
This is awesome! A great solution that avoids using a third-party framework or building a custom slider from scratch. Thank you!Reckon
Does this actually work? I see the onAppear solution works, but not this one.Platform
P
2

Ran into the same thing in iOS 16. The simplest way to customize it is with the .onAppear modifier:

Slider(value: $value)
    .onAppear {
        let thumbImage = UIImage(systemName: "circle.fill")
        UISlider.appearance().setThumbImage(thumbImage, for: .normal)
    }

Inspired by: https://developer.apple.com/forums/thread/719658

Update based on soundflix's comment

WARNING: this changes all sliders in the same view!!!

To be more clear, if you have a SampleView that contains this .onAppear code, the SampleView will pollute any view that contains SampleView (and any upstream and downstream views as well!), so be very careful with this solution if you want multiple slider styles in your app!

If you still want to use this code after understanding its limitations, you might want to move the .onAppear to the outer-most view to reflect what it does more accurately, like so:

var body: some View {
    VStack {
        Text("\(value1)")
        Slider(value: $value1)
        Text("\(value2)")
        Slider(value: $value2)
     }
    .onAppear {
        let thumbImage = UIImage(systemName: "circle.fill")
        UISlider.appearance().setThumbImage(thumbImage, for: .normal)
    }
}
Penneypenni answered 24/9, 2023 at 5:3 Comment(4)
It should be noted that this solution changes all Slider views in your app.Platform
I just did a test; you are partially correct. This code, unfortunately, changes all controls appearing in the same view, meaning if you have multiple sliders with different styles and put them in a view, whoever appears first will be the style of the slider in that view. Each view can have its own style, though.Penneypenni
In my testing there's always exactly one thumpImage for all sliders, no matter where and how many onAppear I declare in child/parent/grandparent views.Platform
Thanks soundflix; I have now modified my answer with more clarity. This .onAppear will pollute an entire view hierarchy for sure (as you said child/parent/grandparent, etc.); however, if you have a view hierarchy that is not polluted by this .onAppear already, you can start a different pollution within it by creating a different slider style. I do hope to find a native solution to not having this polluting behaviour, though...Penneypenni

© 2022 - 2024 — McMap. All rights reserved.