Roman V
Roman V

Reputation: 15

MAUI slider with a tooltip implementation

I'm trying to implement a slider with a tooltip showing current value. The idea is to make something like a HTML + JS with a value bubble (https://css-tricks.com/value-bubbles-for-range-inputs/). Both ideas I've come with so far are not ideal.

XAML

<Slider
        x:Name="slider1"
        Value="0"
        Maximum="100"
        Minimum="0"
        ValueChanged ="slider1_ValueChanged"                
        />

<Label
        x:Name="labelPositionBubble"
        BindingContext="{x:Reference slider1}"
        Text="{Binding Value}"
        IsVisible="false"
        />

C# code

private async void slider1_ValueChanged(object sender, ValueChangedEventArgs e)
{
    var slider = sender as Slider;

        // Idea 1
        labelPositionBubble.TranslationX += (e.NewValue - e.OldValue) * (slider.Width / slider.Maximum);
 
        // Idea 2
        labelPositionBubble.TranslateTo(slider.Value * (slider.Width / slider.Maximum), labelPositionBubble.Y + 20, 10);
}

I've tried calculating the translation (see 'Idea 1') and using TranslateTo() method (see 'Idea 2').

https://www.youtube.com/shorts/E0hEDXv1JUE

First works relatively smooth but is imprecise. Label isn't perfectly aligned with a slider's thumb and moves ahead / lags behind slightly. (Is there a mistake in my formula?)

https://www.youtube.com/shorts/Zcx4PCpn0K8

Second method works better in terms of precision, but UX is way worse: label tends to move with a noticeable jerk (since TranslateTo() is a method for animation, I guess).

Solution

labelPositionBubble.TranslationX = 16 + slider.Value * ((slider.Width - 32) / slider.Maximum) - labelPositionBubble.Width / 2;

labelPositionBubble.TranslationY = -20;

labelPositionBubble.Width / 2 centers the label.

TranslationY = -20; positions the label above the slider, use positive values to position below.

Upvotes: 0

Views: 396

Answers (1)

Liqun Shen-MSFT
Liqun Shen-MSFT

Reputation: 8220

slider.Width is the whole width of the Slider control. But there is still a small Padding for the left and right edge. So, the count is not precise, I think. See the picture below,

enter image description here

I will make a little change to the formula to make it become more precise,

labelPositionBubble.TranslationX = 16 + e.NewValue * ((slider.Width - 32) / slider.Maximum);

First, we should get the Padding value from the left or the right. We could use Handler here.

    double offset = 0;
#if ANDROID
    var seekbar = slider.Handler.PlatformView as AbsSeekBar;
    var padding = seekbar.PaddingLeft;
    offset = padding / DeviceDisplay.Current.MainDisplayInfo.Density;
#endif

The padding value we get is physical pixel. And we have to turn it to device-independent units by using padding / DeviceDisplay.Current.MainDisplayInfo.Density. For PIXEL5, that value is 16. I havn't tested on other emulators.


For windows, I recommend you set,

Microsoft.Maui.Handlers.SliderHandler.Mapper.AppendToMapping("MyCustomization", (handler, view) =>
{
#if WINDOWS
    handler.PlatformView.IsThumbToolTipEnabled = true;
#endif
});

Then it will show a built-in tooltip.

Hope it helps!

Upvotes: 1

Related Questions