This format might be familiar to some of you, as I recreated Apple’s Stepper in Daily Coding Tip 254.
I’m not sure how many more of these I’ll do, but I’ll probably at least have a go at Toggle
.
The part of a slider that you slide is called a thumb, so the most important thing I’m going to be creating is SliderThumbView
.
I have to be aware of the current colorScheme
the user has selected for their operating system, which can either be .light
or .dark
. The reason I need this is the system Slider
seems to hide its shadow in dark mode, or at least it reduces the size of it to the point it’s difficult to see.
That’s why I’m using a clear shadow colour in that case.
I’m starting by using a GeometryReader
and its GeometryProxy
argument to calculate the width available to the slider and then subtracting the height of the circular thumb (which is also its width).
Now that I know the maximum distance that the thumb can be offset from the left side, I can use the value of the slider to calculate where the thumb should be.
When the value
is divided by bounds.upperBound
, the result is a decimal where 1 is the maximum value the slider can display.
When the value
is halfway between bounds.lowerBound
and bounds.upperBound
, the offset is 0.5 multiplied by the maximum distance that the thumb can be offset.
When the location of the drag gesture is less than 1 I want to ensure that the value is set to bounds.lowerBounds
. This is because I layer my SliderThumbView
on top of a ProgressView
with .padding(.horizontal, 1)
in a ZStack
. This seems to be present in the system Slider
, and it seems to help when the Slider
itself has no padding applied.
My example ContentView
for instance does not have any horizontal padding, and you’ll notice that it’s just as easy to set the CustomSlider
to zero as it is the system Slider
.
If you don’t care about matching the system Slider
initialiser that uses in:
as a label for the bounds
parameter, you do not need this initialiser. I did that with SliderThumbView
, which just has a bounds
parameter and uses the memberwise initialiser that is automatically generated for structures.
You cannot name the bounds
property in
because this is a reserved keyword in Swift.