Reputation: 15
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).
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
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,
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