1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-15 00:53:10 +08:00

Merge pull request #22743 from Joehuu/scroll-back-to-previous

Add ability to scroll back to previous position after scrolling to top via button on overlays
This commit is contained in:
Dean Herbert 2023-03-01 22:55:47 +09:00 committed by GitHub
commit bd11d5d29a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 73 additions and 15 deletions

View File

@ -61,6 +61,18 @@ namespace osu.Game.Tests.Visual.UserInterface
AddStep("scroll to 500", () => scroll.ScrollTo(500)); AddStep("scroll to 500", () => scroll.ScrollTo(500));
AddUntilStep("scrolled to 500", () => Precision.AlmostEquals(scroll.Current, 500, 0.1f)); AddUntilStep("scrolled to 500", () => Precision.AlmostEquals(scroll.Current, 500, 0.1f));
AddAssert("button is visible", () => scroll.Button.State == Visibility.Visible); AddAssert("button is visible", () => scroll.Button.State == Visibility.Visible);
AddStep("click button", () =>
{
InputManager.MoveMouseTo(scroll.Button);
InputManager.Click(MouseButton.Left);
});
AddAssert("button is visible", () => scroll.Button.State == Visibility.Visible);
AddStep("user scroll down by 1", () => InputManager.ScrollVerticalBy(-1));
AddAssert("button is hidden", () => scroll.Button.State == Visibility.Hidden);
} }
[Test] [Test]
@ -71,6 +83,10 @@ namespace osu.Game.Tests.Visual.UserInterface
AddStep("invoke action", () => scroll.Button.Action.Invoke()); AddStep("invoke action", () => scroll.Button.Action.Invoke());
AddUntilStep("scrolled back to start", () => Precision.AlmostEquals(scroll.Current, 0, 0.1f)); AddUntilStep("scrolled back to start", () => Precision.AlmostEquals(scroll.Current, 0, 0.1f));
AddStep("invoke action", () => scroll.Button.Action.Invoke());
AddAssert("scrolled to end", () => scroll.IsScrolledToEnd());
} }
[Test] [Test]
@ -85,6 +101,14 @@ namespace osu.Game.Tests.Visual.UserInterface
}); });
AddUntilStep("scrolled back to start", () => Precision.AlmostEquals(scroll.Current, 0, 0.1f)); AddUntilStep("scrolled back to start", () => Precision.AlmostEquals(scroll.Current, 0, 0.1f));
AddStep("click button", () =>
{
InputManager.MoveMouseTo(scroll.Button);
InputManager.Click(MouseButton.Left);
});
AddAssert("scrolled to end", () => scroll.IsScrolledToEnd());
} }
[Test] [Test]
@ -97,12 +121,12 @@ namespace osu.Game.Tests.Visual.UserInterface
AddStep("hover button", () => InputManager.MoveMouseTo(scroll.Button)); AddStep("hover button", () => InputManager.MoveMouseTo(scroll.Button));
AddRepeatStep("click button", () => InputManager.Click(MouseButton.Left), 3); AddRepeatStep("click button", () => InputManager.Click(MouseButton.Left), 3);
AddAssert("invocation count is 1", () => invocationCount == 1); AddAssert("invocation count is 3", () => invocationCount == 3);
} }
private partial class TestScrollContainer : OverlayScrollContainer private partial class TestScrollContainer : OverlayScrollContainer
{ {
public new ScrollToTopButton Button => base.Button; public new ScrollBackButton Button => base.Button;
} }
} }
} }

View File

@ -5,6 +5,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
@ -21,25 +22,29 @@ using osuTK.Graphics;
namespace osu.Game.Overlays namespace osu.Game.Overlays
{ {
/// <summary> /// <summary>
/// <see cref="UserTrackingScrollContainer"/> which provides <see cref="ScrollToTopButton"/>. Mostly used in <see cref="FullscreenOverlay{T}"/>. /// <see cref="UserTrackingScrollContainer"/> which provides <see cref="ScrollBackButton"/>. Mostly used in <see cref="FullscreenOverlay{T}"/>.
/// </summary> /// </summary>
public partial class OverlayScrollContainer : UserTrackingScrollContainer public partial class OverlayScrollContainer : UserTrackingScrollContainer
{ {
/// <summary> /// <summary>
/// Scroll position at which the <see cref="ScrollToTopButton"/> will be shown. /// Scroll position at which the <see cref="ScrollBackButton"/> will be shown.
/// </summary> /// </summary>
private const int button_scroll_position = 200; private const int button_scroll_position = 200;
protected readonly ScrollToTopButton Button; protected ScrollBackButton Button;
public OverlayScrollContainer() private readonly Bindable<float?> lastScrollTarget = new Bindable<float?>();
[BackgroundDependencyLoader]
private void load()
{ {
AddInternal(Button = new ScrollToTopButton AddInternal(Button = new ScrollBackButton
{ {
Anchor = Anchor.BottomRight, Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight, Origin = Anchor.BottomRight,
Margin = new MarginPadding(20), Margin = new MarginPadding(20),
Action = scrollToTop Action = scrollBack,
LastScrollTarget = { BindTarget = lastScrollTarget }
}); });
} }
@ -53,16 +58,31 @@ namespace osu.Game.Overlays
return; return;
} }
Button.State = Target > button_scroll_position ? Visibility.Visible : Visibility.Hidden; Button.State = Target > button_scroll_position || lastScrollTarget.Value != null ? Visibility.Visible : Visibility.Hidden;
} }
private void scrollToTop() protected override void OnUserScroll(float value, bool animated = true, double? distanceDecay = default)
{ {
ScrollToStart(); base.OnUserScroll(value, animated, distanceDecay);
Button.State = Visibility.Hidden;
lastScrollTarget.Value = null;
} }
public partial class ScrollToTopButton : OsuHoverContainer private void scrollBack()
{
if (lastScrollTarget.Value == null)
{
lastScrollTarget.Value = Target;
ScrollToStart();
}
else
{
ScrollTo(lastScrollTarget.Value.Value);
lastScrollTarget.Value = null;
}
}
public partial class ScrollBackButton : OsuHoverContainer
{ {
private const int fade_duration = 500; private const int fade_duration = 500;
@ -88,8 +108,11 @@ namespace osu.Game.Overlays
private readonly Container content; private readonly Container content;
private readonly Box background; private readonly Box background;
private readonly SpriteIcon spriteIcon;
public ScrollToTopButton() public Bindable<float?> LastScrollTarget = new Bindable<float?>();
public ScrollBackButton()
: base(HoverSampleSet.ScrollToTop) : base(HoverSampleSet.ScrollToTop)
{ {
Size = new Vector2(50); Size = new Vector2(50);
@ -113,7 +136,7 @@ namespace osu.Game.Overlays
{ {
RelativeSizeAxes = Axes.Both RelativeSizeAxes = Axes.Both
}, },
new SpriteIcon spriteIcon = new SpriteIcon
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
@ -134,6 +157,17 @@ namespace osu.Game.Overlays
flashColour = colourProvider.Light1; flashColour = colourProvider.Light1;
} }
protected override void LoadComplete()
{
base.LoadComplete();
LastScrollTarget.BindValueChanged(target =>
{
spriteIcon.RotateTo(target.NewValue != null ? 180 : 0, fade_duration, Easing.OutQuint);
TooltipText = target.NewValue != null ? CommonStrings.ButtonsBackToPrevious : CommonStrings.ButtonsBackToTop;
}, true);
}
protected override bool OnClick(ClickEvent e) protected override bool OnClick(ClickEvent e)
{ {
background.FlashColour(flashColour, 800, Easing.OutQuint); background.FlashColour(flashColour, 800, Easing.OutQuint);