190 строки
4.6 KiB
C#
190 строки
4.6 KiB
C#
using System;
|
|
using System.ComponentModel;
|
|
using Windows.Foundation;
|
|
using Windows.UI.Xaml;
|
|
using Windows.UI.Xaml.Controls;
|
|
|
|
#if WINDOWS_UWP
|
|
|
|
namespace Xamarin.Forms.Platform.UWP
|
|
#else
|
|
|
|
namespace Xamarin.Forms.Platform.WinRT
|
|
#endif
|
|
{
|
|
public class ScrollViewRenderer : ViewRenderer<ScrollView, ScrollViewer>
|
|
{
|
|
VisualElement _currentView;
|
|
|
|
public ScrollViewRenderer()
|
|
{
|
|
AutoPackage = false;
|
|
}
|
|
|
|
public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
|
|
{
|
|
SizeRequest result = base.GetDesiredSize(widthConstraint, heightConstraint);
|
|
result.Minimum = new Size(40, 40);
|
|
return result;
|
|
}
|
|
|
|
protected override Windows.Foundation.Size ArrangeOverride(Windows.Foundation.Size finalSize)
|
|
{
|
|
if (Element == null)
|
|
return finalSize;
|
|
|
|
Element.IsInNativeLayout = true;
|
|
|
|
Control?.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));
|
|
|
|
Element.IsInNativeLayout = false;
|
|
|
|
return finalSize;
|
|
}
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (Control != null)
|
|
{
|
|
Control.ViewChanged -= OnViewChanged;
|
|
}
|
|
|
|
base.Dispose(disposing);
|
|
}
|
|
|
|
protected override Windows.Foundation.Size MeasureOverride(Windows.Foundation.Size availableSize)
|
|
{
|
|
if (Element == null)
|
|
return new Windows.Foundation.Size(0, 0);
|
|
|
|
double width = Math.Max(0, Element.Width);
|
|
double height = Math.Max(0, Element.Height);
|
|
var result = new Windows.Foundation.Size(width, height);
|
|
|
|
Control?.Measure(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
protected override void OnElementChanged(ElementChangedEventArgs<ScrollView> e)
|
|
{
|
|
base.OnElementChanged(e);
|
|
|
|
if (e.OldElement != null)
|
|
{
|
|
e.OldElement.ScrollToRequested -= OnScrollToRequested;
|
|
}
|
|
|
|
if (e.NewElement != null)
|
|
{
|
|
if (Control == null)
|
|
{
|
|
SetNativeControl(new ScrollViewer { HorizontalScrollBarVisibility = ScrollBarVisibility.Auto, VerticalScrollBarVisibility = ScrollBarVisibility.Auto });
|
|
|
|
Control.ViewChanged += OnViewChanged;
|
|
}
|
|
|
|
Element.ScrollToRequested += OnScrollToRequested;
|
|
|
|
UpdateOrientation();
|
|
|
|
LoadContent();
|
|
}
|
|
}
|
|
|
|
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
|
{
|
|
base.OnElementPropertyChanged(sender, e);
|
|
|
|
if (e.PropertyName == "Content")
|
|
LoadContent();
|
|
else if (e.PropertyName == Layout.PaddingProperty.PropertyName)
|
|
UpdateMargins();
|
|
else if (e.PropertyName == ScrollView.OrientationProperty.PropertyName)
|
|
UpdateOrientation();
|
|
}
|
|
|
|
void LoadContent()
|
|
{
|
|
if (_currentView != null)
|
|
{
|
|
_currentView.Cleanup();
|
|
}
|
|
|
|
_currentView = Element.Content;
|
|
|
|
IVisualElementRenderer renderer = null;
|
|
if (_currentView != null)
|
|
{
|
|
renderer = _currentView.GetOrCreateRenderer();
|
|
}
|
|
|
|
Control.Content = renderer != null ? renderer.ContainerElement : null;
|
|
|
|
UpdateMargins();
|
|
}
|
|
|
|
void OnScrollToRequested(object sender, ScrollToRequestedEventArgs e)
|
|
{
|
|
double x = e.ScrollX, y = e.ScrollY;
|
|
|
|
ScrollToMode mode = e.Mode;
|
|
if (mode == ScrollToMode.Element)
|
|
{
|
|
Point pos = Element.GetScrollPositionForElement((VisualElement)e.Element, e.Position);
|
|
x = pos.X;
|
|
y = pos.Y;
|
|
mode = ScrollToMode.Position;
|
|
}
|
|
|
|
if (mode == ScrollToMode.Position)
|
|
{
|
|
Control.ChangeView(x, y, null, !e.ShouldAnimate);
|
|
}
|
|
Element.SendScrollFinished();
|
|
}
|
|
|
|
void OnViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
|
|
{
|
|
Element.SetScrolledPosition(Control.HorizontalOffset, Control.VerticalOffset);
|
|
|
|
if (!e.IsIntermediate)
|
|
Element.SendScrollFinished();
|
|
}
|
|
|
|
void UpdateMargins()
|
|
{
|
|
var element = Control.Content as FrameworkElement;
|
|
if (element == null)
|
|
return;
|
|
|
|
switch (Element.Orientation)
|
|
{
|
|
case ScrollOrientation.Horizontal:
|
|
// need to add left/right margins
|
|
element.Margin = new Windows.UI.Xaml.Thickness(Element.Padding.Left, 0, Element.Padding.Right, 0);
|
|
break;
|
|
case ScrollOrientation.Vertical:
|
|
// need to add top/bottom margins
|
|
element.Margin = new Windows.UI.Xaml.Thickness(0, Element.Padding.Top, 0, Element.Padding.Bottom);
|
|
break;
|
|
case ScrollOrientation.Both:
|
|
// need to add all margins
|
|
element.Margin = new Windows.UI.Xaml.Thickness(Element.Padding.Left, Element.Padding.Top, Element.Padding.Right, Element.Padding.Bottom);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void UpdateOrientation()
|
|
{
|
|
if (Element.Orientation == ScrollOrientation.Horizontal || Element.Orientation == ScrollOrientation.Both)
|
|
{
|
|
Control.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
|
|
}
|
|
else
|
|
{
|
|
Control.HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled;
|
|
}
|
|
}
|
|
}
|
|
} |