Skip to content

Commit a5ec556

Browse files
committed
feat(scrollviewer): Add ability to configure scrollbar's auto-hide delay, and fully disable auto-hide
1 parent 534d3ba commit a5ec556

File tree

2 files changed

+38
-6
lines changed

2 files changed

+38
-6
lines changed

src/Uno.UI/FeatureConfiguration.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,14 @@ public static class ScrollViewer
395395
/// </remarks>
396396
public static ScrollViewerUpdatesMode DefaultUpdatesMode { get; set; } = ScrollViewerUpdatesMode.AsynchronousIdle;
397397

398+
/// <summary>
399+
/// Defines the delay after which the scrollbars hide themselves when pointer is not over.<br/>
400+
/// Default is 4 sec.<br/>
401+
/// Setting this to <see cref="TimeSpan.MaxValue"/> will completely disable the auto hide feature.
402+
/// </summary>
403+
/// <remarks>This is effective only for managed scrollbars (WASM, macOS and Skia for now)</remarks>
404+
public static TimeSpan? DefaultAutoHideDelay { get; set; }
405+
398406
#if __ANDROID__
399407
/// <summary>
400408
/// This value defines an optional delay to be set for native ScrollBar thumbs to disapear. The

src/Uno.UI/UI/Xaml/Controls/ScrollViewer/ScrollViewer.cs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,7 @@ protected override void OnApplyTemplate()
907907

908908
OnBringIntoViewOnFocusChangeChangedPartial(BringIntoViewOnFocusChange);
909909

910-
ResetScrollIndicator(forced: true);
910+
PrepareScrollIndicator();
911911
}
912912

913913
partial void OnApplyTemplatePartial();
@@ -1368,16 +1368,30 @@ private bool ChangeViewCore(
13681368
return ChangeViewNative(horizontalOffset, verticalOffset, zoomFactor, disableAnimation);
13691369
}
13701370

1371-
#region Scroll indicators visual states (Managed scroll bars only)
1371+
#region Scroll indicators visual states (Managed scroll bars only)
1372+
private static readonly TimeSpan _indicatorResetDelay = FeatureConfiguration.ScrollViewer.DefaultAutoHideDelay ?? TimeSpan.FromSeconds(4);
1373+
private static readonly bool _indicatorResetDisabled = _indicatorResetDelay == TimeSpan.MaxValue;
13721374
private DispatcherQueueTimer? _indicatorResetTimer;
13731375
private string? _indicatorState;
13741376

1377+
private void PrepareScrollIndicator() // OnApplyTemplate
1378+
{
1379+
if (_indicatorResetDisabled)
1380+
{
1381+
ShowScrollIndicator(PointerDeviceType.Mouse, forced: true);
1382+
}
1383+
else
1384+
{
1385+
ResetScrollIndicator(forced: true);
1386+
}
1387+
}
1388+
13751389
private static void ShowScrollIndicator(object sender, PointerRoutedEventArgs e) // OnPointerMove
13761390
=> (sender as ScrollViewer)?.ShowScrollIndicator(e.Pointer.PointerDeviceType);
13771391

1378-
private void ShowScrollIndicator(PointerDeviceType type)
1392+
private void ShowScrollIndicator(PointerDeviceType type, bool forced = false)
13791393
{
1380-
if (!ComputedIsVerticalScrollEnabled && !ComputedIsHorizontalScrollEnabled)
1394+
if (!forced && !ComputedIsVerticalScrollEnabled && !ComputedIsHorizontalScrollEnabled)
13811395
{
13821396
return;
13831397
}
@@ -1393,13 +1407,18 @@ private void ShowScrollIndicator(PointerDeviceType type)
13931407
_indicatorState = indicatorState;
13941408
}
13951409

1410+
if (_indicatorResetDisabled)
1411+
{
1412+
return;
1413+
}
1414+
13961415
// Automatically hide the scroll indicator after a delay without any interaction
13971416
if (_indicatorResetTimer == null)
13981417
{
13991418
var weakRef = WeakReferencePool.RentSelfWeakReference(this);
14001419
_indicatorResetTimer = new DispatcherQueueTimer
14011420
{
1402-
Interval = TimeSpan.FromSeconds(4),
1421+
Interval = _indicatorResetDelay,
14031422
IsRepeating = false
14041423
};
14051424
_indicatorResetTimer.Tick += (snd, e) => (weakRef.Target as ScrollViewer)?.ResetScrollIndicator();
@@ -1412,6 +1431,11 @@ private static void ResetScrollIndicator(object sender, RoutedEventArgs _) // On
14121431

14131432
private void ResetScrollIndicator(bool forced = false)
14141433
{
1434+
if (_indicatorResetDisabled)
1435+
{
1436+
return;
1437+
}
1438+
14151439
_indicatorResetTimer?.Stop();
14161440

14171441
if (!forced && ((_horizontalScrollbar?.IsPointerOver ?? false) || (_verticalScrollbar?.IsPointerOver ?? false)))
@@ -1447,6 +1471,6 @@ private void HideScrollBarSeparator(object sender, PointerRoutedEventArgs e) //
14471471
VisualStateManager.GoToState(this, VisualStates.ScrollBarsSeparator.Collapsed, true);
14481472
}
14491473
}
1450-
#endregion
1474+
#endregion
14511475
}
14521476
}

0 commit comments

Comments
 (0)