diff --git a/README.md b/README.md
index fa0ee1d..f27d66b 100644
--- a/README.md
+++ b/README.md
@@ -94,21 +94,14 @@ ___Please star ⭐ if you like it, helps very much!___
## What's New
-### Nuget 1.2.9.7
+### Nuget 1.2.9.8
for SkiaSharp 2.88.9-preview.2.2
-* [FluentExtensions](https://github.com/taublast/DrawnUi.Maui/blob/main/src/Engine/Internals/Extensions/FluentExtensions.cs) for code-behind
-* Added gestures delegate `OnGestures` to SkiaLayout.
-* HotFix for SkiaCarousel always setting index at 0 upon initialization.
-* HotFix for random crash accessing disposed LoadedImageSource.
-* [HotFix](https://github.com/taublast/DrawnUi.Maui/issues/136) for loading images from StreamImageSource
-* SkiaShape new Types: Polygon and Line. New property for their Points: Smooth (0-1) to smooth angles.
-* Shapes demo page inside SandBox project.
-* VisualElement Shadow property now supported everywhere as an optional addition to existing shadows.
-* Removed SkiaImage clipping to better support shadows.
-* SkiaLabel new property AutoFont: Find and set system font where the first glyph in text is present. Useful for some quick unicode rendering like emoji etc.
-* Updated Getsures nuget for correct lock inside MAUI native ScrollView, use Getures="Lock" for Canvas.
-* Fixed controls sometimes not invalidated when canvas suface size changes
-* Other fixes.
+
+* DisposeObject optimized for background.
+* Templated layout measurement optimized.
+* HotFix for gestures crash on iOS when targeting ios lower than 18.
+* Nuget targets ios 17.
+
## About
diff --git a/dev/github_uploadnugets.bat b/dev/github_uploadnugets.bat
index 2252670..0558fdb 100644
--- a/dev/github_uploadnugets.bat
+++ b/dev/github_uploadnugets.bat
@@ -13,8 +13,8 @@ REM Define the source directory for the packages
set "source_dir=E:\Nugets"
REM Define the list of file masks for the packages
-set "mask[1]=DrawnUi.Maui*.1.2.9.7*.nupkg"
-set "mask[2]=AppoMobi.Maui.DrawnUi.1.2.9.7*.*nupkg"
+set "mask[1]=DrawnUi.Maui*.1.2.9.8*.nupkg"
+set "mask[2]=AppoMobi.Maui.DrawnUi.1.2.9.8*.*nupkg"
set "mask_count=2"
REM Loop through each file mask
diff --git a/dev/nuget_uploadnugets.bat b/dev/nuget_uploadnugets.bat
index d1d3722..6b5d8d9 100644
--- a/dev/nuget_uploadnugets.bat
+++ b/dev/nuget_uploadnugets.bat
@@ -13,8 +13,8 @@ REM Define the source directory for the packages
set "source_dir=E:\Nugets"
REM Define the list of file masks for the packages
-set "mask[1]=DrawnUi.Maui*.1.2.9.7*.nupkg"
-set "mask[2]=AppoMobi.Maui.DrawnUi.1.2.9.7*.*nupkg"
+set "mask[1]=DrawnUi.Maui*.1.2.9.8*.nupkg"
+set "mask[2]=AppoMobi.Maui.DrawnUi.1.2.9.8*.*nupkg"
set "mask_count=2"
REM Loop through each file mask
diff --git a/src/Addons/DrawnUi.Maui.Camera/DrawnUi.Maui.Camera.csproj b/src/Addons/DrawnUi.Maui.Camera/DrawnUi.Maui.Camera.csproj
index 6dbbf4a..566b3e6 100644
--- a/src/Addons/DrawnUi.Maui.Camera/DrawnUi.Maui.Camera.csproj
+++ b/src/Addons/DrawnUi.Maui.Camera/DrawnUi.Maui.Camera.csproj
@@ -1,6 +1,6 @@
- net8.0;net8.0-android;net8.0-ios;net8.0-maccatalyst
+ net8.0;net8.0-android;net8.0-ios17.0;net8.0-maccatalyst17.0
$(TargetFrameworks);net8.0-windows10.0.19041.0
true
true
@@ -44,7 +44,7 @@
-
+
\ No newline at end of file
diff --git a/src/Addons/DrawnUi.Maui.Game/DrawnUi.Maui.Game.csproj b/src/Addons/DrawnUi.Maui.Game/DrawnUi.Maui.Game.csproj
index 8232e47..1e2b06a 100644
--- a/src/Addons/DrawnUi.Maui.Game/DrawnUi.Maui.Game.csproj
+++ b/src/Addons/DrawnUi.Maui.Game/DrawnUi.Maui.Game.csproj
@@ -1,6 +1,6 @@
- net8.0;net8.0-android;net8.0-ios;net8.0-maccatalyst
+ net8.0;net8.0-android;net8.0-ios17.0;net8.0-maccatalyst17.0
$(TargetFrameworks);net8.0-windows10.0.19041.0
true
true
@@ -42,7 +42,7 @@
-
+
diff --git a/src/Addons/DrawnUi.Maui.MapsUi/src/DrawnUi.Maui.MapsUi.csproj b/src/Addons/DrawnUi.Maui.MapsUi/src/DrawnUi.Maui.MapsUi.csproj
index d06c087..afb2499 100644
--- a/src/Addons/DrawnUi.Maui.MapsUi/src/DrawnUi.Maui.MapsUi.csproj
+++ b/src/Addons/DrawnUi.Maui.MapsUi/src/DrawnUi.Maui.MapsUi.csproj
@@ -1,6 +1,6 @@
- net8.0;net8.0-android;net8.0-ios;net8.0-maccatalyst
+ net8.0;net8.0-android;net8.0-ios17.0;net8.0-maccatalyst17.0
$(TargetFrameworks);net8.0-windows10.0.19041.0
true
true
@@ -54,7 +54,7 @@
-
+
diff --git a/src/Addons/DrawnUi.Maui.Rive/DrawnUi.Maui.Rive.csproj b/src/Addons/DrawnUi.Maui.Rive/DrawnUi.Maui.Rive.csproj
index 694847f..0ff5d8e 100644
--- a/src/Addons/DrawnUi.Maui.Rive/DrawnUi.Maui.Rive.csproj
+++ b/src/Addons/DrawnUi.Maui.Rive/DrawnUi.Maui.Rive.csproj
@@ -1,6 +1,6 @@
- net8.0;net8.0-android;net8.0-ios;net8.0-maccatalyst
+ net8.0;net8.0-android;net8.0-ios17.0;net8.0-maccatalyst17.0
$(TargetFrameworks);net8.0-windows10.0.19041.0
true
true
@@ -47,7 +47,7 @@
-
+
diff --git a/src/Addons/DrawnUi.MauiGraphics/DrawnUi.MauiGraphics.csproj b/src/Addons/DrawnUi.MauiGraphics/DrawnUi.MauiGraphics.csproj
index 9d1c496..bac1512 100644
--- a/src/Addons/DrawnUi.MauiGraphics/DrawnUi.MauiGraphics.csproj
+++ b/src/Addons/DrawnUi.MauiGraphics/DrawnUi.MauiGraphics.csproj
@@ -1,6 +1,6 @@
- net8.0;net8.0-android;net8.0-ios;net8.0-maccatalyst
+ net8.0;net8.0-android;net8.0-ios17.0;net8.0-maccatalyst17.0
$(TargetFrameworks);net8.0-windows10.0.19041.0
true
true
@@ -41,7 +41,7 @@
-
+
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index ba4d863..fef7825 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -5,13 +5,13 @@
Using SkiaSharp 2.xx. Checkout the DrawnUi Sandbox project for usage example.
- 1.2.9.7
+ 1.2.9.8
$(DefineConstants);SKIA3
Using SkiaSharp 3-preview. New handlers, SKSL, WinUI hardware acceleration etc..
- 1.3.56.1-pre
+ 1.3.56.2-pre
\ No newline at end of file
diff --git a/src/Engine/Controls/Navigation/SkiaShell.NavigationLayer.cs b/src/Engine/Controls/Navigation/SkiaShell.NavigationLayer.cs
index a36dcba..215c9ba 100644
--- a/src/Engine/Controls/Navigation/SkiaShell.NavigationLayer.cs
+++ b/src/Engine/Controls/Navigation/SkiaShell.NavigationLayer.cs
@@ -74,12 +74,9 @@ public async Task Close(T control, bool animated)
await _shell.UnfreezeRootLayout(control, animated);
}
- control.SetParent(null);
+ control?.DisposeObject();
+ control?.SetParent(null);
- Tasks.StartDelayed(TimeSpan.FromSeconds(3.5), () =>
- {
- control?.Dispose();
- });
}
catch (Exception e)
{
@@ -122,4 +119,4 @@ public async Task CloseAll()
}
-}
\ No newline at end of file
+}
diff --git a/src/Engine/Controls/Navigation/SkiaShell.cs b/src/Engine/Controls/Navigation/SkiaShell.cs
index eb03508..466338c 100644
--- a/src/Engine/Controls/Navigation/SkiaShell.cs
+++ b/src/Engine/Controls/Navigation/SkiaShell.cs
@@ -1,7 +1,7 @@
-using AppoMobi.Maui.Navigation;
-using System.Collections.ObjectModel;
+using System.Collections.ObjectModel;
using System.Numerics;
using System.Runtime.CompilerServices;
+using AppoMobi.Maui.Navigation;
namespace DrawnUi.Maui.Controls
{
@@ -1020,10 +1020,7 @@ async Task RemoveModal(SkiaControl control, bool animated)
OnLayersChanged(control);
control.SetParent(null); //unregister gestures etc
- Tasks.StartDelayed(TimeSpan.FromSeconds(3.5), () =>
- {
- control.Dispose();
- });
+ ShellLayout?.DisposeObject(control);
}
}
@@ -1193,10 +1190,7 @@ public virtual async Task UnfreezeRootLayout(SkiaControl control, bool animated)
RootLayout.RemoveSubView(screenshot);
- Tasks.StartDelayed(TimeSpan.FromSeconds(3.5), () =>
- {
- screenshot?.Dispose();
- });
+ RootLayout.DisposeObject(screenshot);
}
}
@@ -1788,10 +1782,7 @@ void Act()
});
}
if (kill != null)
- Tasks.StartDelayed(TimeSpan.FromSeconds(3.5), () =>
- {
- kill?.Dispose();
- });
+ ShellLayout?.DisposeObject(kill);
}
protected virtual void ReplaceRootLayout(ISkiaControl newLayout)
@@ -1813,10 +1804,7 @@ protected virtual void ReplaceRootLayout(ISkiaControl newLayout)
ImportRootLayout();
if (kill != null)
- Tasks.StartDelayed(TimeSpan.FromSeconds(3.5), () =>
- {
- kill?.Dispose();
- });
+ ShellLayout?.DisposeObject(kill);
}
protected virtual void ImportShellLayout()
diff --git a/src/Engine/Controls/PlayFrames/SkiaGif.cs b/src/Engine/Controls/PlayFrames/SkiaGif.cs
index 5ce90b4..d7594d5 100644
--- a/src/Engine/Controls/PlayFrames/SkiaGif.cs
+++ b/src/Engine/Controls/PlayFrames/SkiaGif.cs
@@ -1,6 +1,4 @@
using DrawnUi.Maui.Features.Images;
-using System.Collections.Concurrent;
-using System.Text;
namespace DrawnUi.Maui.Controls;
@@ -163,7 +161,7 @@ public void SetAnimation(GifAnimation animation, bool disposePrevious)
Start();
if (kill != null && disposePrevious)
- Tasks.StartDelayed(TimeSpan.FromSeconds(2), () => { kill.Dispose(); });
+ DisposeObject(kill);
Invalidate();
@@ -262,4 +260,4 @@ public string Source
set => SetValue(SourceProperty, value);
}
-}
\ No newline at end of file
+}
diff --git a/src/Engine/Controls/ViewSwitcher/SkiaViewSwitcher.cs b/src/Engine/Controls/ViewSwitcher/SkiaViewSwitcher.cs
index 028d2df..b16144c 100644
--- a/src/Engine/Controls/ViewSwitcher/SkiaViewSwitcher.cs
+++ b/src/Engine/Controls/ViewSwitcher/SkiaViewSwitcher.cs
@@ -824,42 +824,42 @@ protected virtual async Task SetupTransitionAnimation(
switch (doubleViewTransitionType)
{
case DoubleViewTransitionType.Pop:
- //from left to right
- break;
+ //from left to right
+ break;
case DoubleViewTransitionType.Push:
- previousVisibleView.ZIndex = -1;
- newVisibleView.ZIndex = 0;
+ previousVisibleView.ZIndex = -1;
+ newVisibleView.ZIndex = 0;
- //from right to left
- translateTo = this.Width;
- newVisibleView.Opacity = 0.001;
- newVisibleView.TranslationX = (float)translateTo;
- break;
+ //from right to left
+ translateTo = this.Width;
+ newVisibleView.Opacity = 0.001;
+ newVisibleView.TranslationX = (float)translateTo;
+ break;
case DoubleViewTransitionType.SelectRightTab:
- translateTo = this.Width;
+ translateTo = this.Width;
- newVisibleView.ZIndex = 1;
- previousVisibleView.ZIndex = 0;
- newVisibleView.Opacity = 0.001;
- newVisibleView.TranslationX = (float)translateTo * 0.75;
- break;
+ newVisibleView.ZIndex = 1;
+ previousVisibleView.ZIndex = 0;
+ newVisibleView.Opacity = 0.001;
+ newVisibleView.TranslationX = (float)translateTo * 0.75;
+ break;
case DoubleViewTransitionType.SelectLeftTab:
- translateTo = -this.Width;
+ translateTo = -this.Width;
- newVisibleView.ZIndex = 1;
- previousVisibleView.ZIndex = 0;
- newVisibleView.Opacity = 0.001;
- newVisibleView.TranslationX = (float)translateTo * 0.75;
- break;
+ newVisibleView.ZIndex = 1;
+ previousVisibleView.ZIndex = 0;
+ newVisibleView.Opacity = 0.001;
+ newVisibleView.TranslationX = (float)translateTo * 0.75;
+ break;
default:
- newVisibleView.TranslationX = 0;
- newVisibleView.TranslationY = 0;
- newVisibleView.Opacity = 1;
- break;
+ newVisibleView.TranslationX = 0;
+ newVisibleView.TranslationY = 0;
+ newVisibleView.Opacity = 1;
+ break;
}
}
@@ -875,79 +875,79 @@ protected virtual async Task ExecuteTransitionAnimation(
switch (doubleViewTransitionType)
{
case DoubleViewTransitionType.Pop:
- //from left to right
- easing = PagesAnimationEasing;
- speed = PagesAnimationSpeed;
- Task animateOld1 = previousVisibleView.TranslateToAsync(translateTo, 0, speed, easing);
- Task animateOld2 = previousVisibleView.FadeToAsync(0.9, speed, easing);
+ //from left to right
+ easing = PagesAnimationEasing;
+ speed = PagesAnimationSpeed;
+ Task animateOld1 = previousVisibleView.TranslateToAsync(translateTo, 0, speed, easing);
+ Task animateOld2 = previousVisibleView.FadeToAsync(0.9, speed, easing);
- try
- {
- var cancelAnimation = new CancellationTokenSource(TimeSpan.FromSeconds(2));
- await Task.WhenAll(animateOld1, animateOld2).WithCancellation(cancelAnimation.Token);
- }
- catch (Exception e)
- {
- Debug.WriteLine(e);
- }
- break;
+ try
+ {
+ var cancelAnimation = new CancellationTokenSource(TimeSpan.FromSeconds(2));
+ await Task.WhenAll(animateOld1, animateOld2).WithCancellation(cancelAnimation.Token);
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine(e);
+ }
+ break;
case DoubleViewTransitionType.Push:
- easing = PagesAnimationEasing;
- speed = PagesAnimationSpeed;
- //from right to left
- Task in1 = newVisibleView.TranslateToAsync(0, 0, speed, easing);
- Task in2 = newVisibleView.FadeToAsync(1.0, speed, easing);
- try
- {
- var cancelAnimation = new CancellationTokenSource(TimeSpan.FromSeconds(2));
- await Task.WhenAll(in1, in2).WithCancellation(cancelAnimation.Token).WithCancellation(cancelAnimation.Token);
- }
- catch (Exception e)
- {
- Debug.WriteLine(e);
- }
- break;
+ easing = PagesAnimationEasing;
+ speed = PagesAnimationSpeed;
+ //from right to left
+ Task in1 = newVisibleView.TranslateToAsync(0, 0, speed, easing);
+ Task in2 = newVisibleView.FadeToAsync(1.0, speed, easing);
+ try
+ {
+ var cancelAnimation = new CancellationTokenSource(TimeSpan.FromSeconds(2));
+ await Task.WhenAll(in1, in2).WithCancellation(cancelAnimation.Token).WithCancellation(cancelAnimation.Token);
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine(e);
+ }
+ break;
case DoubleViewTransitionType.SelectLeftTab:
- translateTo = -this.Width;
+ translateTo = -this.Width;
- Task animateOldM = previousVisibleView.TranslateToAsync(-translateTo, 0, (uint)speed, easing);
- Task animateNewM = newVisibleView.TranslateToAsync(0, 0, (uint)speed, easing);
- Task animateNewM1 = newVisibleView.FadeToAsync(1.0, (uint)speed, Easing.Linear);
+ Task animateOldM = previousVisibleView.TranslateToAsync(-translateTo, 0, (uint)speed, easing);
+ Task animateNewM = newVisibleView.TranslateToAsync(0, 0, (uint)speed, easing);
+ Task animateNewM1 = newVisibleView.FadeToAsync(1.0, (uint)speed, Easing.Linear);
- try
- {
- var cancelAnimation =
- new CancellationTokenSource(TimeSpan.FromSeconds(2));
+ try
+ {
+ var cancelAnimation =
+ new CancellationTokenSource(TimeSpan.FromSeconds(2));
- await Task.WhenAll(animateOldM, animateNewM, animateNewM1).WithCancellation(cancelAnimation.Token);
- }
- catch (Exception e)
- {
- Debug.WriteLine(e);
- }
- break;
+ await Task.WhenAll(animateOldM, animateNewM, animateNewM1).WithCancellation(cancelAnimation.Token);
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine(e);
+ }
+ break;
case DoubleViewTransitionType.SelectRightTab:
- translateTo = this.Width;
+ translateTo = this.Width;
- animateOldM = previousVisibleView.TranslateToAsync(-translateTo, 0, (uint)speed, easing);
- animateNewM = newVisibleView.TranslateToAsync(0, 0, (uint)speed, easing);
- animateNewM1 = newVisibleView.FadeToAsync(1.0, (uint)speed, Easing.Linear);
+ animateOldM = previousVisibleView.TranslateToAsync(-translateTo, 0, (uint)speed, easing);
+ animateNewM = newVisibleView.TranslateToAsync(0, 0, (uint)speed, easing);
+ animateNewM1 = newVisibleView.FadeToAsync(1.0, (uint)speed, Easing.Linear);
- try
- {
- var cancelAnimation =
- new CancellationTokenSource(TimeSpan.FromSeconds(2));
+ try
+ {
+ var cancelAnimation =
+ new CancellationTokenSource(TimeSpan.FromSeconds(2));
- await Task.WhenAll(animateOldM, animateNewM, animateNewM1).WithCancellation(cancelAnimation.Token);
- }
- catch (Exception e)
- {
- Debug.WriteLine(e);
- }
- break;
+ await Task.WhenAll(animateOldM, animateNewM, animateNewM1).WithCancellation(cancelAnimation.Token);
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine(e);
+ }
+ break;
}
}
@@ -1198,7 +1198,7 @@ protected void UnloadView(NavigationStackEntry view)
SendOnDisappearing(view.View);
if (!view.Preserve && view.View is IDisposable disposable)
{
- disposable.Dispose();
+ DisposeObject(disposable);
}
}
else
diff --git a/src/Engine/Draw/Base/SkiaControl.Cache.cs b/src/Engine/Draw/Base/SkiaControl.Cache.cs
index 6fb5dc8..e70c87f 100644
--- a/src/Engine/Draw/Base/SkiaControl.Cache.cs
+++ b/src/Engine/Draw/Base/SkiaControl.Cache.cs
@@ -397,12 +397,10 @@ protected virtual bool UseRenderingObject(SkiaDrawingContext context, SKRect dra
var kill = RenderObjectPrevious;
RenderObjectPrevious = null;
RenderObjectPreviousNeedsUpdate = false;
+
if (kill != null)
{
- Tasks.StartDelayed(TimeSpan.FromSeconds(3.5), () =>
- {
- kill.Dispose();
- });
+ DisposeObject(kill);
}
}
@@ -725,10 +723,7 @@ protected void CreateRenderingObjectAndPaint(
}
if (!UsesCacheDoubleBuffering && usingCacheType != SkiaCacheType.ImageComposite)
{
- Tasks.StartDelayed(TimeSpan.FromSeconds(3.5), () =>
- {
- oldObject.Dispose();
- });
+ DisposeObject(oldObject);
}
}
diff --git a/src/Engine/Draw/Base/SkiaControl.Shared.cs b/src/Engine/Draw/Base/SkiaControl.Shared.cs
index 66a268c..41e82cb 100644
--- a/src/Engine/Draw/Base/SkiaControl.Shared.cs
+++ b/src/Engine/Draw/Base/SkiaControl.Shared.cs
@@ -2537,6 +2537,14 @@ public static (double X1, double Y1, double X2, double Y2) LinearGradientAngleTo
return (startPoint.x, startPoint.y, endPoint.x, endPoint.y);
}
+ public static TimeSpan DisposalDelay = TimeSpan.FromSeconds(3.5);
+
+ public ObjectAliveType IsAlive { get; set; }
+
+ public void DisposeObject()
+ {
+ DisposeObject(this);
+ }
///
/// Dispose with needed delay.
@@ -2550,7 +2558,7 @@ public virtual void DisposeObject(IDisposable disposable)
{
try
{
- view.ToBeDisposed.Enqueue(disposable);
+ view.DisposeObject(disposable);
}
catch (Exception e)
{
@@ -2559,11 +2567,20 @@ public virtual void DisposeObject(IDisposable disposable)
}
else
{
- Tasks.StartDelayed(TimeSpan.FromSeconds(3.5), () =>
+ if (disposable is SkiaControl skia)
+ {
+ skia.IsAlive = ObjectAliveType.BeingDisposed;
+ }
+
+ Tasks.StartDelayed(DisposalDelay, () =>
{
try
{
disposable?.Dispose();
+ if (disposable is SkiaControl skia)
+ {
+ skia.IsAlive = ObjectAliveType.Disposed;
+ }
}
catch (Exception e)
{
@@ -4002,7 +4019,7 @@ public void Dispose()
SizeChanged -= ViewSizeChanged;
//for the double buffering case it's safer to delay
- Tasks.StartDelayed(TimeSpan.FromSeconds(1), () =>
+ Tasks.StartDelayed(DisposalDelay, () =>
{
RenderObject = null;
diff --git a/src/Engine/Draw/Layout/SkiaLayout.ColumnRow.cs b/src/Engine/Draw/Layout/SkiaLayout.ColumnRow.cs
index eb26b94..631947a 100644
--- a/src/Engine/Draw/Layout/SkiaLayout.ColumnRow.cs
+++ b/src/Engine/Draw/Layout/SkiaLayout.ColumnRow.cs
@@ -305,13 +305,13 @@ public virtual ScaledSize MeasureStack(SKRect rectForChildrenPixels, float scale
var layoutStructure = BuildStackStructure(scale);
- bool useOneTemplate =
- IsTemplated &&
- //ItemSizingStrategy == ItemSizingStrategy.MeasureFirstItem &&
- RecyclingTemplate == RecyclingTemplate.Enabled;
+ bool standalone = false;
+ bool useOneTemplate = IsTemplated && ItemSizingStrategy == ItemSizingStrategy.MeasureFirstItem &&
+ RecyclingTemplate != RecyclingTemplate.Disabled;
if (useOneTemplate)
{
+ standalone = true;
template = ChildrenFactory.GetTemplateInstance();
}
@@ -328,6 +328,17 @@ public virtual ScaledSize MeasureStack(SKRect rectForChildrenPixels, float scale
var columnsCount = layoutStructure.GetColumnCountForRow(row);
+ var needMeasureAll = true;
+ if (useOneTemplate)
+ {
+ needMeasureAll = RecyclingTemplate == RecyclingTemplate.Disabled ||
+ ItemSizingStrategy == ItemSizingStrategy.MeasureAllItems ||
+ (ItemSizingStrategy == ItemSizingStrategy.MeasureFirstItem
+ && columnsCount != Split)
+ || !(ItemSizingStrategy == ItemSizingStrategy.MeasureFirstItem
+ && firstCell != null);
+ }
+
if (!DynamicColumns && columnsCount < Split)
{
columnsCount = Split;
@@ -518,7 +529,19 @@ public virtual ScaledSize MeasureStack(SKRect rectForChildrenPixels, float scale
if (useOneTemplate)
{
- ChildrenFactory.ReleaseView(template);
+ if (standalone)
+ ChildrenFactory.ReleaseTemplateInstance(template);
+ else
+ ChildrenFactory.ReleaseView(template);
+ }
+
+ if (HorizontalOptions.Alignment == LayoutAlignment.Fill && WidthRequest < 0)
+ {
+ stackWidth = rectForChildrenPixels.Width;
+ }
+ if (VerticalOptions.Alignment == LayoutAlignment.Fill && HeightRequest < 0)
+ {
+ stackHeight = rectForChildrenPixels.Height;
}
return ScaledSize.FromPixels(stackWidth, stackHeight, scale);
diff --git a/src/Engine/Draw/Layout/SkiaLayout.ViewsAdapter.cs b/src/Engine/Draw/Layout/SkiaLayout.ViewsAdapter.cs
index e4181b3..fb205ee 100644
--- a/src/Engine/Draw/Layout/SkiaLayout.ViewsAdapter.cs
+++ b/src/Engine/Draw/Layout/SkiaLayout.ViewsAdapter.cs
@@ -1,14 +1,13 @@
using System.Collections;
namespace DrawnUi.Maui.Draw;
-
///
/// Top level class for working with ItemTemplates. Holds visible views.
///
public class ViewsAdapter : IDisposable
{
public static bool LogEnabled = false;
-
+ public bool IsDisposed;
private readonly SkiaLayout _parent;
public ViewsAdapter(SkiaLayout parent)
@@ -19,6 +18,8 @@ public ViewsAdapter(SkiaLayout parent)
public void Dispose()
{
DisposeViews();
+
+ IsDisposed = true;
}
object lockVisible = new();
@@ -27,6 +28,9 @@ protected void UpdateVisibleViews()
{
lock (lockVisible)
{
+ if (IsDisposed)
+ return;
+
foreach (var view in _dicoCellsInUse.Values.ToList())
{
view.InvalidateInternal();
@@ -39,6 +43,9 @@ protected void DisposeVisibleViews()
{
lock (lockVisible)
{
+ if (IsDisposed)
+ return;
+
foreach (var view in _dicoCellsInUse.Values)
{
view.Dispose();
@@ -49,6 +56,9 @@ protected void DisposeVisibleViews()
protected void DisposeViews()
{
+ if (IsDisposed)
+ return;
+
_templatedViewsPool?.Dispose();
DisposeVisibleViews();
}
@@ -76,6 +86,9 @@ public void MarkViewAsHidden(int index)
{
lock (lockVisible)
{
+ if (IsDisposed)
+ return;
+
if (_parent.IsTemplated && _parent.RecyclingTemplate == RecyclingTemplate.Enabled)
{
if (_dicoCellsInUse.ContainsKey(index))
@@ -104,6 +117,9 @@ protected virtual void AttachView(SkiaControl view, int index)
//todo check how it behaves when sources changes
//lock (_lockTemplates)
{
+ if (IsDisposed)
+ return;
+
view.Parent = _parent;
if (index == 0 || view.ContextIndex != index)
//if (view.BindingContext == null || _parent.RecyclingTemplate == RecyclingTemplate.Enabled)
@@ -138,6 +154,9 @@ protected virtual void AttachView(SkiaControl view, int index)
///
public void AddMoreToPool(int oversize)
{
+ if (IsDisposed)
+ return;
+
if (_templatedViewsPool != null && AddedMore < oversize)
{
var add = oversize - AddedMore;
@@ -160,6 +179,10 @@ public void AddMoreToPool(int oversize)
///
public void FillPool(int size, IList context)
{
+ if (IsDisposed)
+ return;
+
+
FillPool(size);
if (context == null)
@@ -177,6 +200,9 @@ public void FillPool(int size, IList context)
///
public void FillPool(int size)
{
+ if (IsDisposed)
+ return;
+
if (size > 0)
{
while (_templatedViewsPool.Size < size && _templatedViewsPool.Size < _templatedViewsPool.MaxSize)
@@ -193,6 +219,9 @@ public string GetDebugInfo()
public SkiaControl GetChildAt(int index, SkiaControl template = null)
{
+ if (IsDisposed)
+ return null;
+
if (index >= 0)
{
//lock (lockVisible)
@@ -200,26 +229,26 @@ public SkiaControl GetChildAt(int index, SkiaControl template = null)
if (_parent.IsTemplated)
{
- if (_dicoCellsInUse.TryGetValue(index, out SkiaControl ready))
+ if (template == null && _dicoCellsInUse.TryGetValue(index, out SkiaControl ready))
{
if (LogEnabled)
{
Trace.WriteLine($"[ViewsAdapter] {_parent.Tag} returned a ready view {ready.Uid}");
}
- //#if DEBUG
- // try
- // {
- // if (!object.Equals(_dataContexts[index], ready.BindingContext))
- // {
- // Trace.WriteLine($"[ViewsAdapter] {_parent.Tag} ready view has different context!");
- // }
- // }
- // catch (Exception e)
- // {
- // Trace.WriteLine(e);
- // }
- //#endif
+#if DEBUG
+ //try
+ //{
+ // if (!object.Equals(_dataContexts[index], ready.BindingContext))
+ // {
+ // Trace.WriteLine($"[ViewsAdapter] {_parent.Tag} ready view has different context!");
+ // }
+ //}
+ //catch (Exception e)
+ //{
+ // Trace.WriteLine(e);
+ //}
+#endif
AttachView(ready, index);
return ready;
@@ -232,6 +261,20 @@ public SkiaControl GetChildAt(int index, SkiaControl template = null)
return null;
}
+#if DEBUG
+ //try
+ //{
+ // if (!object.Equals(_dataContexts[index], view.BindingContext))
+ // {
+ // Trace.WriteLine($"[ViewsAdapter] {_parent.Tag} ready view has different context!");
+ // }
+ //}
+ //catch (Exception e)
+ //{
+ // Trace.WriteLine(e);
+ //}
+#endif
+
AttachView(view, index);
//save visible view for future use only if template is not provided
@@ -251,7 +294,6 @@ public SkiaControl GetChildAt(int index, SkiaControl template = null)
}
return view;
-
}
else
{
@@ -269,6 +311,10 @@ public SkiaControl GetChildAt(int index, SkiaControl template = null)
public int GetChildrenCount()
{
+ if (IsDisposed)
+ return 0;
+
+
if (!_parent.IsTemplated)
{
var children = _parent.GetUnorderedSubviews();
@@ -335,6 +381,7 @@ public int PoolSize
private float _forScale;
private int _forSplit;
+
///
/// Main method to initialize templates, can use InitializeTemplatesInBackground as an option.
///
@@ -344,6 +391,10 @@ public int PoolSize
/// Pre-create number of views to avoid lag spikes later, useful to do in backgound.
public void InitializeTemplates(Func