Add lazy loading threshold
This commit is contained in:
Родитель
9fc459992b
Коммит
8dfc8e3477
|
@ -28,8 +28,7 @@
|
|||
<TextBlock HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Foreground="OrangeRed"
|
||||
IsHitTestVisible="False"
|
||||
Text="Please scroll down to see the effect." />
|
||||
IsHitTestVisible="False"><Run Text="Please scroll down to see the effect." /><LineBreak /><Run Text="The default threshold for triggering lazy loading is 300 px." /></TextBlock>
|
||||
<Button Width="48"
|
||||
Height="48"
|
||||
HorizontalAlignment="Right"
|
||||
|
|
|
@ -71,7 +71,7 @@ namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
|
|||
|
||||
if (ImageExBase.IsLazyLoadingSupported)
|
||||
{
|
||||
SampleController.Current.RegisterNewCommand("Lazy loading sample (17763 or higher supported)", (sender, args) =>
|
||||
SampleController.Current.RegisterNewCommand("Lazy loading sample", (sender, args) =>
|
||||
{
|
||||
var imageExLazyLoadingControl = new ImageExLazyLoadingControl();
|
||||
imageExLazyLoadingControl.CloseButtonClick += (s, a) =>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Foreground" Value="{ThemeResource ApplicationForegroundThemeBrush}" />
|
||||
<Setter Property="IsTabStop" Value="False" />
|
||||
<Setter Property="LazyLoadingThreshold" Value="300" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="controls:ImageEx">
|
||||
|
|
|
@ -54,12 +54,17 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
/// <summary>
|
||||
/// Identifies the <see cref="EnableLazyLoading"/> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty EnableLazyLoadingProperty = DependencyProperty.Register(nameof(EnableLazyLoading), typeof(bool), typeof(ImageExBase), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty EnableLazyLoadingProperty = DependencyProperty.Register(nameof(EnableLazyLoading), typeof(bool), typeof(ImageExBase), new PropertyMetadata(false, EnableLazyLoadingChanged));
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether <see cref="EnableLazyLoading"/> is supported
|
||||
/// Identifies the <see cref="LazyLoadingThreshold"/> dependency property.
|
||||
/// </summary>
|
||||
public static bool IsLazyLoadingSupported { get; } = ApiInformation.IsEventPresent("Windows.UI.Xaml.FrameworkElement", nameof(EffectiveViewportChanged));
|
||||
public static readonly DependencyProperty LazyLoadingThresholdProperty = DependencyProperty.Register(nameof(LazyLoadingThreshold), typeof(double), typeof(ImageExBase), new PropertyMetadata(default(double), LazyLoadingThresholdChanged));
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether <see cref="EnableLazyLoading"/> is supported, always return true.
|
||||
/// </summary>
|
||||
public static bool IsLazyLoadingSupported { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Returns a mask that represents the alpha channel of an image as a <see cref="CompositionBrush"/>
|
||||
|
@ -160,5 +165,30 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
get { return (bool)GetValue(EnableLazyLoadingProperty); }
|
||||
set { SetValue(EnableLazyLoadingProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating the threshold for triggering lazy loading.
|
||||
/// </summary>
|
||||
public double LazyLoadingThreshold
|
||||
{
|
||||
get { return (double)GetValue(LazyLoadingThresholdProperty); }
|
||||
set { SetValue(LazyLoadingThresholdProperty, value); }
|
||||
}
|
||||
|
||||
private static void EnableLazyLoadingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is ImageExBase control)
|
||||
{
|
||||
control.InvalidateLazyLoading();
|
||||
}
|
||||
}
|
||||
|
||||
private static void LazyLoadingThresholdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is ImageExBase control)
|
||||
{
|
||||
control.InvalidateLazyLoading();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -82,7 +82,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
|
||||
if (IsLazyLoadingSupported)
|
||||
{
|
||||
EffectiveViewportChanged += ImageExBase_EffectiveViewportChanged;
|
||||
LayoutUpdated += ImageExBase_LayoutUpdated;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,6 +213,22 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
return base.ArrangeOverride(finalSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// from https://referencesource.microsoft.com/#WindowsBase/Base/System/Windows/Rect.cs,04390f584fcba8e4
|
||||
/// </summary>
|
||||
private static bool IntersectsWith(Rect rect1, Rect rect2)
|
||||
{
|
||||
if (rect1.IsEmpty || rect2.IsEmpty)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (rect1.Left <= rect2.Right) &&
|
||||
(rect1.Right >= rect2.Left) &&
|
||||
(rect1.Top <= rect2.Bottom) &&
|
||||
(rect1.Bottom >= rect2.Top);
|
||||
}
|
||||
|
||||
private void OnImageOpened(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ImageExOpened?.Invoke(this, new ImageExOpenedEventArgs());
|
||||
|
@ -225,15 +241,36 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
VisualStateManager.GoToState(this, FailedState, true);
|
||||
}
|
||||
|
||||
private void ImageExBase_EffectiveViewportChanged(FrameworkElement sender, EffectiveViewportChangedEventArgs args)
|
||||
private void ImageExBase_LayoutUpdated(object sender, object e)
|
||||
{
|
||||
var bringIntoViewDistanceX = args.BringIntoViewDistanceX;
|
||||
var bringIntoViewDistanceY = args.BringIntoViewDistanceY;
|
||||
InvalidateLazyLoading();
|
||||
}
|
||||
|
||||
var width = ActualWidth;
|
||||
var height = ActualHeight;
|
||||
private void InvalidateLazyLoading()
|
||||
{
|
||||
if (!IsLoaded)
|
||||
{
|
||||
_isInViewport = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (bringIntoViewDistanceX <= width && bringIntoViewDistanceY <= height)
|
||||
var hostElement = GetHostElement();
|
||||
if (hostElement == null)
|
||||
{
|
||||
_isInViewport = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var controlRect = TransformToVisual(hostElement)
|
||||
.TransformBounds(new Rect(0, 0, ActualWidth, ActualHeight));
|
||||
var lazyLoadingThreshold = LazyLoadingThreshold;
|
||||
var hostRect = new Rect(
|
||||
0 - lazyLoadingThreshold,
|
||||
0 - lazyLoadingThreshold,
|
||||
hostElement.ActualWidth + (2 * lazyLoadingThreshold),
|
||||
hostElement.ActualHeight + (2 * lazyLoadingThreshold));
|
||||
|
||||
if (IntersectsWith(controlRect, hostRect))
|
||||
{
|
||||
_isInViewport = true;
|
||||
|
||||
|
@ -249,5 +286,36 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
_isInViewport = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find ascendant element until <see cref="ScrollViewer" /> or root element.
|
||||
/// </summary>
|
||||
/// <returns><see cref="ScrollViewer"/> or root element.</returns>
|
||||
private FrameworkElement GetHostElement()
|
||||
{
|
||||
FrameworkElement hostElement = this;
|
||||
while (true)
|
||||
{
|
||||
var parent = VisualTreeHelper.GetParent(hostElement) as FrameworkElement;
|
||||
if (parent == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (parent is ScrollViewer)
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
|
||||
hostElement = parent;
|
||||
}
|
||||
|
||||
if (ReferenceEquals(hostElement, this))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return hostElement;
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче