Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement a custom slider with two thumbs?

How I can create a custom slider with two thumbs. One is for representing higher range and another for lower range. For example Price range. if the value is below 50 it will represent lower range and if it is above 50, it will represent the higher range.

like image 810
StezPet Avatar asked Jan 20 '14 16:01

StezPet


People also ask

How to create a slider with two thumbs in JavaFX?

The slider JavaFX provides contains only one thumb if you want to create a slider with two thumbs you need to rely on an external library named org.controlsfx.control. <dependency> <groupId>org.controlsfx</groupId> <artifactId>controlsfx</artifactId> <version>11.0.1</version> </dependency>

Can you get a two-thumb slider?

The first part of this two-part series detailed how we can get a two-thumb slider. Now we’ll look at a general multi-thumb case, but with a different and better technique for creating the fills in between the thumbs. And finally, we’ll dive into the how behind the styling a realistic 3D-looking slider and a flat one.

How to create a slider handle icon/image?

Tip: Set the height of the slider to a different value than the slider thumbs if you want unequal heights (15px vs. 25px in this example): To create a slider handle icon/image, use the background property and insert an image url:

How do the thumbs work in the slider?

Also, the thumbs still work as they do in the basic Slider control, with the middle of the thumb being the indicator for where the thumb value is.


2 Answers

That's no small question. I won't do it all, but I will get you started:

<Grid Background="Black">
    <Grid Height="100" Width="500" Background="DimGray">
        <Grid.Resources>
            <Style TargetType="Grid" x:Name="HandleStyle">
                <Setter Property="Height" Value="50" />
                <Setter Property="Width" Value="50" />
                <Setter Property="Background" Value="White" />
                <Setter Property="RenderTransformOrigin" Value="0.5,0.5" />
            </Style>
            <Style TargetType="TextBlock" x:Name="HandleTextStyle">
                <Setter Property="Foreground" Value="DimGray" />
                <Setter Property="FontSize" Value="20" />
                <Setter Property="TextAlignment" Value="Center" />
                <Setter Property="HorizontalAlignment" Value="Center" />
                <Setter Property="VerticalAlignment" Value="Center" />
                <Setter Property="IsHitTestVisible" Value="False" />
            </Style>
        </Grid.Resources>
        <Rectangle Height="10" Width="450" Fill="DarkGray" />
        <Grid x:Name="LeftHandle" Style="{StaticResource HandleStyle}"
              ManipulationMode="TranslateX" 
              ManipulationDelta="LeftHandle_ManipulationDelta">
            <Grid.RenderTransform>
                <CompositeTransform TranslateX="-200"/>
            </Grid.RenderTransform>
            <TextBlock x:Name="LeftHandleText" Text="0"
                       Style="{StaticResource HandleTextStyle}" />
        </Grid>
        <Grid x:Name="RightHandle" Style="{StaticResource HandleStyle}"
              ManipulationMode="TranslateX" 
              ManipulationDelta="RightHandle_ManipulationDelta" RenderTransformOrigin="0.5,0.5">
            <Grid.RenderTransform>
                <CompositeTransform TranslateX="-150"/>
            </Grid.RenderTransform>
            <TextBlock x:Name="RightHandleText" Text="0"
                       Style="{StaticResource HandleTextStyle}" />
        </Grid>
    </Grid>
</Grid>

Use this code-behind:

int Min = 0;
int Max = 100;
int Size = 100;
int Range = 200;

private void LeftHandle_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
    var t = (sender as Grid).RenderTransform as CompositeTransform;
    var x = (RightHandle.RenderTransform as CompositeTransform).TranslateX;
    var f = -this.Range;
    var c = x - this.Size * .5;
    t.TranslateX = Translate(t, e, f, c);
    LeftHandleText.Text = Text(t.TranslateX);
}

private void RightHandle_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
    var t = (sender as Grid).RenderTransform as CompositeTransform;
    var x = (LeftHandle.RenderTransform as CompositeTransform).TranslateX;
    var f = x + this.Size * .5;
    var c = this.Range;
    t.TranslateX = Translate(t, e, f, c);
    RightHandleText.Text = Text(t.TranslateX);
}

private double Translate(CompositeTransform s, ManipulationDeltaRoutedEventArgs e, double floor, double ceiling)
{
    var target = s.TranslateX + e.Delta.Translation.X;
    if (target < floor)
        return floor;
    if (target > ceiling)
        return ceiling;
    return target;
}

private string Text(double x)
{
    var p = (x - (-this.Range)) / ((this.Range) - (-this.Range)) * 100d;
    var v = (this.Max - this.Min) * p / 100d + this.Min;
    return ((int)v).ToString();
}

Looks good:

enter image description here

Best of luck!

like image 121
Jerry Nixon Avatar answered Oct 02 '22 04:10

Jerry Nixon


Based on @Jerry Nixon's code, I've created a range control. I do not know how to create a custom control. So have simply put the project in GitHub for all the desperate souls like me who are searching for a control :) Feel free to contribute or file issues. Will work on it as time permits.

https://github.com/alfah-plackal/CustomSlider

May the code be with you!

like image 29
alfah Avatar answered Oct 02 '22 04:10

alfah