I was trolling the Xamarin.Forms forum when I saw this question:
Can you limit a Slider to only allow integer values? (Hopefully snapping to the next integer)
I dug around a bit I found this solution on StackOverflow. I did a quick and dirty conversion to Xamarin.Forms, but wanted to make it a little better, more Xamarin.Formy.
So, here is the answer to this question:
ExtendedSlider Class
The first thing we need to do is create a new Slider class that has our “stop” value, which we do using the following code:
public class ExtendedSlider : Slider { public static readonly BindableProperty CurrentStepValueProperty = BindableProperty.Create<ExtendedSlider, double>(p => p.StepValue, 1.0f); public double StepValue { get { return (double)GetValue(CurrentStepValueProperty); } set { SetValue(CurrentStepValueProperty, value); } } public ExtendedSlider() { ValueChanged += OnSliderValueChanged; } private void OnSliderValueChanged(object sender, ValueChangedEventArgs e) { var newStep = Math.Round(e.NewValue / StepValue); Value = newStep * StepValue; } }
All this really does is converts the current slider value from a double, into an integer.
Demonstration Page
Here is a fully functional demonstration page:
public class SliderDemo : ContentPage { public SliderDemo() { var sliderMain = new ExtendedSlider { Minimum = 0.0f, Maximum = 5.0f, Value = 0.0f, StepValue = 1.0f, HorizontalOptions = LayoutOptions.FillAndExpand, }; var labelCurrentValue = new Label { HorizontalOptions = LayoutOptions.CenterAndExpand, BindingContext = sliderMain, }; labelCurrentValue.SetBinding(Label.TextProperty, new Binding("Value", BindingMode.OneWay, null, null, "Current Value: {0}")); var grid = new Grid { Padding = 10, RowDefinitions = { new RowDefinition {Height = GridLength.Auto}, }, ColumnDefinitions = { new ColumnDefinition {Width = new GridLength(1, GridUnitType.Star)}, new ColumnDefinition {Width = new GridLength(1, GridUnitType.Star)}, new ColumnDefinition {Width = new GridLength(1, GridUnitType.Star)}, new ColumnDefinition {Width = new GridLength(1, GridUnitType.Star)}, new ColumnDefinition {Width = new GridLength(1, GridUnitType.Star)}, }, }; for (var i = 0; i < 6; i++) { var label = new Label { Text = i.ToString(CultureInfo.InvariantCulture), }; var tapValue = i; // Prevent modified closure label.GestureRecognizers.Add(new TapGestureRecognizer { Command = new Command(() => { sliderMain.Value = tapValue; }), NumberOfTapsRequired = 1 }); grid.Children.Add(label, i, 0); } Content = new StackLayout { Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 10), Children = { grid, sliderMain, labelCurrentValue }, Orientation = StackOrientation.Vertical, HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.FillAndExpand }; } }
If anyone has a better way of doing this, then please let me know.
I’ll probably add this to the Xamarin.Forms Labs project sometime this week.