Skip to content

Commit

Permalink
[WinUI] ScrollView Resize + Window Handler Resize (#1676)
Browse files Browse the repository at this point in the history
* WinUI-only ScrollBarHandler (#1671)

* Re-measure scrollviewer on native arrange

The scrollviewer seems to need to measure again when the handler is being native arranged.  Simply calling .arrange on the native view didn't reset the size to the requested bounds, it needs to be told to resize first, otherwise it stays >= the content size.

* Resize root panel content on window size changed

This resizes the root panel's contents when the window size changes

* Measure Page in RootPanel MeasureOverride

* Remove defunct code from demos

* Modify ScrollView to allow native measure in addition to content measure

Co-authored-by: E.Z. Hart <hartez@users.noreply.github.com>
Co-authored-by: E.Z. Hart <hartez@gmail.com>
  • Loading branch information
3 people authored Jul 20, 2021
1 parent 6fb0c7a commit e0ebddc
Show file tree
Hide file tree
Showing 20 changed files with 414 additions and 57 deletions.
33 changes: 33 additions & 0 deletions src/Controls/src/Core/HandlerImpl/ScrollView.Impl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
namespace Microsoft.Maui.Controls
{
public partial class ScrollView : IScrollView
{
IView IScrollView.Content => Content;

double IScrollView.HorizontalOffset
{
get => ScrollX;
set
{
if (ScrollX != value)
{
SetScrolledPosition(value, ScrollY);
}
}
}

double IScrollView.VerticalOffset
{
get => ScrollY;
set
{
if (ScrollY != value)
{
SetScrolledPosition(ScrollX, value);
}
}
}

void IScrollView.ScrollFinished() => SendScrollFinished();
}
}
3 changes: 3 additions & 0 deletions src/Controls/src/Core/Hosting/AppHostBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ public static partial class AppHostBuilderExtensions
{ typeof(Layout2.Layout), typeof(LayoutHandler) },
{ typeof(Picker), typeof(PickerHandler) },
{ typeof(ProgressBar), typeof(ProgressBarHandler) },
#if WINDOWS
{ typeof(ScrollView), typeof(ScrollViewHandler) },
#endif
{ typeof(SearchBar), typeof(SearchBarHandler) },
{ typeof(Slider), typeof(SliderHandler) },
{ typeof(Stepper), typeof(StepperHandler) },
Expand Down
8 changes: 5 additions & 3 deletions src/Controls/src/Core/Layout.cs
Original file line number Diff line number Diff line change
Expand Up @@ -219,12 +219,14 @@ protected virtual void OnChildMeasureInvalidated()

Size IFrameworkElement.Measure(double widthConstraint, double heightConstraint)
{
DesiredSize = OnMeasure(widthConstraint, heightConstraint).Request;
return DesiredSize;
return MeasureOverride(widthConstraint, heightConstraint);
}

protected override Size MeasureOverride(double widthConstraint, double heightConstraint)
=> (this as IFrameworkElement).Measure(widthConstraint, heightConstraint);
{
DesiredSize = OnMeasure(widthConstraint, heightConstraint).Request;
return DesiredSize;
}

protected override void OnSizeAllocated(double width, double height)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,15 @@ internal static InputScope ToInputScope(this ReturnType returnType)
return inputScope;
}

internal static UwpScrollBarVisibility ToUwpScrollBarVisibility(this Maui.Controls.ScrollBarVisibility visibility)
internal static UwpScrollBarVisibility ToUwpScrollBarVisibility(this ScrollBarVisibility visibility)
{
switch (visibility)
{
case Maui.Controls.ScrollBarVisibility.Always:
case ScrollBarVisibility.Always:
return UwpScrollBarVisibility.Visible;
case Maui.Controls.ScrollBarVisibility.Default:
case ScrollBarVisibility.Default:
return UwpScrollBarVisibility.Auto;
case Maui.Controls.ScrollBarVisibility.Never:
case ScrollBarVisibility.Never:
return UwpScrollBarVisibility.Hidden;
default:
return UwpScrollBarVisibility.Auto;
Expand Down
9 changes: 0 additions & 9 deletions src/Controls/src/Core/ScrollBarVisibility.cs

This file was deleted.

10 changes: 0 additions & 10 deletions src/Controls/src/Core/ScrollOrientation.cs

This file was deleted.

28 changes: 26 additions & 2 deletions src/Controls/src/Core/ScrollView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
namespace Microsoft.Maui.Controls
{
[ContentProperty(nameof(Content))]
public class ScrollView : Layout, IScrollViewController, IElementConfiguration<ScrollView>, IFlowDirectionController
public partial class ScrollView : Layout, IScrollViewController, IElementConfiguration<ScrollView>, IFlowDirectionController
{
#region IScrollViewController

Expand Down Expand Up @@ -274,7 +274,17 @@ protected override SizeRequest OnSizeRequest(double widthConstraint, double heig
break;
}

SizeRequest contentRequest = Content.Measure(widthConstraint, heightConstraint, MeasureFlags.IncludeMargins);
SizeRequest contentRequest;

if (Content is IFrameworkElement fe)
{
contentRequest = fe.Measure(widthConstraint, heightConstraint);
}
else
{
contentRequest = Content.Measure(widthConstraint, heightConstraint, MeasureFlags.IncludeMargins);
}

contentRequest.Minimum = new Size(Math.Min(40, contentRequest.Minimum.Width), Math.Min(40, contentRequest.Minimum.Height));

return contentRequest;
Expand Down Expand Up @@ -352,5 +362,19 @@ void OnScrollToRequested(ScrollToRequestedEventArgs e)
CheckTaskCompletionSource();
ScrollToRequested?.Invoke(this, e);
}

protected override Size MeasureOverride(double widthConstraint, double heightConstraint)
{
// We call OnSizeRequest so that the content gets measured appropriately
// and then use the standard GetDesiredSize from the handler so the ScrollView's
// backing control gets measured.

// TODO ezhart 2021-07-14 Verify that we've got the naming correct on this after we resolve the OnSizeRequest obsolete stuff
#pragma warning disable CS0618 // Type or member is obsolete
_ = OnSizeRequest(widthConstraint, heightConstraint);
#pragma warning restore CS0618 // Type or member is obsolete

return Handler.GetDesiredSize(widthConstraint, heightConstraint);
}
}
}
50 changes: 50 additions & 0 deletions src/Core/src/Core/IScrollView.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System;
using Microsoft.Maui.Graphics;

namespace Microsoft.Maui
{
public interface IScrollView : IView
{
// TODO ezhart 2021-07-08 It might make sense for IPage and IScrollView to derive from (the not yet created) IContentView

/// <summary>
/// Gets the view that contains the content of the ScrollView.
/// </summary>
public IView Content { get; }

/// <summary>
/// Gets a value indicating the visibility rules for the horizontal scroll bar.
/// </summary>
ScrollBarVisibility HorizontalScrollBarVisibility { get; }

/// <summary>
/// Gets a value indicating the visibility rules for the vertical scroll bar.
/// </summary>
ScrollBarVisibility VerticalScrollBarVisibility { get; }

/// <summary>
/// Gets a value indicating the scroll orientation of the ScrollView.
/// </summary>
ScrollOrientation Orientation { get; }

/// <summary>
/// Gets the size of the scrollable content in the ScrollView.
/// </summary>
Size ContentSize { get; }

/// <summary>
/// Gets the current scroll position of the ScrollView along the horizontal axis.
/// </summary>
double HorizontalOffset { get; set; }

/// <summary>
/// Gets the current scroll position of the ScrollView along the vertical axis.
/// </summary>
double VerticalOffset { get; set; }

/// <summary>
/// Allows the native ScrollView to inform that cross-platform code that a scroll operation has completed.
/// </summary>
void ScrollFinished();
}
}
21 changes: 21 additions & 0 deletions src/Core/src/Handlers/ScrollView/ScrollViewHandler.Android.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Text;
using AndroidX.Core.Widget;

namespace Microsoft.Maui.Handlers
{
public partial class ScrollViewHandler : ViewHandler<IScrollView, NestedScrollView>
{
protected override NestedScrollView CreateNativeView()
{
throw new NotImplementedException();
}

public static void MapContent(ScrollViewHandler handler, IScrollView scrollView) { }
public static void MapHorizontalScrollBarVisibility(ScrollViewHandler handler, IScrollView scrollView) { }
public static void MapVerticalScrollBarVisibility(ScrollViewHandler handler, IScrollView scrollView) { }
public static void MapOrientation(ScrollViewHandler handler, IScrollView scrollView) { }
public static void MapContentSize(ScrollViewHandler handler, IScrollView scrollView) { }
}
}
18 changes: 18 additions & 0 deletions src/Core/src/Handlers/ScrollView/ScrollViewHandler.Standard.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace Microsoft.Maui.Handlers
{
public partial class ScrollViewHandler : ViewHandler<IScrollView, object>
{
protected override object CreateNativeView() => throw new NotImplementedException();

public static void MapContent(IViewHandler handler, IScrollView scrollView) { }
public static void MapHorizontalScrollBarVisibility(IViewHandler handler, IScrollView scrollView) { }
public static void MapVerticalScrollBarVisibility(IViewHandler handler, IScrollView scrollView) { }
public static void MapOrientation(IViewHandler handler, IScrollView scrollView) { }
public static void MapContentSize(IViewHandler handler, IScrollView scrollView) { }
public static void MapRequestScrollTo(ScrollViewHandler handler, IScrollView scrollView, object? args) { }
}
}
66 changes: 66 additions & 0 deletions src/Core/src/Handlers/ScrollView/ScrollViewHandler.Windows.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
using Microsoft.Maui.Graphics;
using Microsoft.UI.Xaml.Controls;

namespace Microsoft.Maui.Handlers
{
public partial class ScrollViewHandler : ViewHandler<IScrollView, ScrollViewer>
{
protected override ScrollViewer CreateNativeView()
{
return new ScrollViewer();
}

protected override void ConnectHandler(ScrollViewer nativeView)
{
base.ConnectHandler(nativeView);
nativeView.ViewChanged += ViewChanged;
}

protected override void DisconnectHandler(ScrollViewer nativeView)
{
base.DisconnectHandler(nativeView);
nativeView.ViewChanged -= ViewChanged;
}

public static void MapContent(ScrollViewHandler handler, IScrollView scrollView)
{
if (handler.MauiContext == null)
{
return;
}

handler.NativeView.Content = scrollView.Content.ToNative(handler.MauiContext);
}

public static void MapHorizontalScrollBarVisibility(ScrollViewHandler handler, IScrollView scrollView)
{
handler.NativeView?.UpdateScrollBarVisibility(scrollView.Orientation, scrollView.HorizontalScrollBarVisibility);
}

public static void MapVerticalScrollBarVisibility(ScrollViewHandler handler, IScrollView scrollView)
{
handler.NativeView.VerticalScrollBarVisibility = scrollView.VerticalScrollBarVisibility.ToWindowsScrollBarVisibility();
}

public static void MapOrientation(ScrollViewHandler handler, IScrollView scrollView)
{
handler.NativeView?.UpdateScrollBarVisibility(scrollView.Orientation, scrollView.HorizontalScrollBarVisibility);
}

void ViewChanged(object? sender, ScrollViewerViewChangedEventArgs e)
{
VirtualView.VerticalOffset = NativeView.VerticalOffset;
VirtualView.HorizontalOffset = NativeView.HorizontalOffset;

if (e.IsIntermediate == false)
{
VirtualView.ScrollFinished();
}
}
}
}
21 changes: 21 additions & 0 deletions src/Core/src/Handlers/ScrollView/ScrollViewHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#nullable enable
using System;

namespace Microsoft.Maui.Handlers
{
public partial class ScrollViewHandler
{
public static PropertyMapper<IScrollView, ScrollViewHandler> ScrollViewMapper = new(ViewMapper)
{
[nameof(IScrollView.Content)] = MapContent,
[nameof(IScrollView.HorizontalScrollBarVisibility)] = MapHorizontalScrollBarVisibility,
[nameof(IScrollView.VerticalScrollBarVisibility)] = MapVerticalScrollBarVisibility,
[nameof(IScrollView.Orientation)] = MapOrientation,
};

public ScrollViewHandler() : base(ScrollViewMapper)
{

}
}
}
25 changes: 25 additions & 0 deletions src/Core/src/Handlers/ScrollView/ScrollViewHandler.iOS.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Text;
using UIKit;

namespace Microsoft.Maui.Handlers
{
public partial class ScrollViewHandler : ViewHandler<IScrollView, UIScrollView>
{
public ScrollViewHandler(PropertyMapper mapper) : base(mapper)
{
}

protected override UIScrollView CreateNativeView()
{
throw new NotImplementedException();
}

public static void MapContent(ScrollViewHandler handler, IScrollView scrollView) { }
public static void MapHorizontalScrollBarVisibility(ScrollViewHandler handler, IScrollView scrollView) { }
public static void MapVerticalScrollBarVisibility(ScrollViewHandler handler, IScrollView scrollView) { }
public static void MapOrientation(ScrollViewHandler handler, IScrollView scrollView) { }
public static void MapContentSize(ScrollViewHandler handler, IScrollView scrollView) { }
}
}
Loading

0 comments on commit e0ebddc

Please sign in to comment.