diff --git a/Handlers/FlexLayoutHandler.cs b/Handlers/FlexLayoutHandler.cs
index 9ff66e5..fb9d678 100644
--- a/Handlers/FlexLayoutHandler.cs
+++ b/Handlers/FlexLayoutHandler.cs
@@ -97,7 +97,7 @@ public class FlexLayoutHandler : LayoutHandler
Microsoft.Maui.Layouts.FlexAlignContent.Stretch => FlexAlignContent.Stretch,
Microsoft.Maui.Layouts.FlexAlignContent.SpaceBetween => FlexAlignContent.SpaceBetween,
Microsoft.Maui.Layouts.FlexAlignContent.SpaceAround => FlexAlignContent.SpaceAround,
- Microsoft.Maui.Layouts.FlexAlignContent.SpaceEvenly => FlexAlignContent.SpaceAround,
+ Microsoft.Maui.Layouts.FlexAlignContent.SpaceEvenly => FlexAlignContent.SpaceEvenly,
_ => FlexAlignContent.Stretch,
};
}
diff --git a/Types/FlexAlignContent.cs b/Types/FlexAlignContent.cs
index 16d6473..9c87869 100644
--- a/Types/FlexAlignContent.cs
+++ b/Types/FlexAlignContent.cs
@@ -1,5 +1,9 @@
namespace Microsoft.Maui.Platform;
+///
+/// Specifies how flex lines are aligned within the flex container.
+/// Matches Microsoft.Maui.Layouts.FlexAlignContent enum.
+///
public enum FlexAlignContent
{
Start,
@@ -7,5 +11,6 @@ public enum FlexAlignContent
End,
Stretch,
SpaceBetween,
- SpaceAround
+ SpaceAround,
+ SpaceEvenly
}
diff --git a/Views/SkiaScrollView.cs b/Views/SkiaScrollView.cs
index d9c1d16..4544059 100644
--- a/Views/SkiaScrollView.cs
+++ b/Views/SkiaScrollView.cs
@@ -603,9 +603,113 @@ public class SkiaScrollView : SkiaView
///
public void ScrollTo(float x, float y, bool animated = false)
{
- // TODO: Implement animation
- ScrollX = x;
- ScrollY = y;
+ if (animated)
+ {
+ // Animated scroll - use async version
+ _ = ScrollToAsync(x, y, animated);
+ }
+ else
+ {
+ ScrollX = x;
+ ScrollY = y;
+ }
+ }
+
+ ///
+ /// Scrolls to the specified position asynchronously with optional animation.
+ /// Matches MAUI's ScrollView.ScrollToAsync signature.
+ ///
+ public async Task ScrollToAsync(double x, double y, bool animated)
+ {
+ if (!animated)
+ {
+ ScrollX = (float)x;
+ ScrollY = (float)y;
+ return;
+ }
+
+ // Animate scroll over 250ms (standard MAUI animation duration)
+ const int animationDurationMs = 250;
+ const int frameIntervalMs = 16; // ~60fps
+ int steps = animationDurationMs / frameIntervalMs;
+
+ float startX = _scrollX;
+ float startY = _scrollY;
+ float targetX = (float)x;
+ float targetY = (float)y;
+
+ for (int i = 1; i <= steps; i++)
+ {
+ float progress = (float)i / steps;
+ // Use ease-out cubic for smooth deceleration
+ float easedProgress = 1f - (1f - progress) * (1f - progress) * (1f - progress);
+
+ _scrollX = startX + (targetX - startX) * easedProgress;
+ _scrollY = startY + (targetY - startY) * easedProgress;
+
+ Invalidate();
+ await Task.Delay(frameIntervalMs);
+ }
+
+ // Ensure we end at exact target position
+ ScrollX = targetX;
+ ScrollY = targetY;
+ }
+
+ ///
+ /// Scrolls to make the specified element visible.
+ /// Matches MAUI's ScrollView.ScrollToAsync signature for elements.
+ ///
+ public Task ScrollToAsync(SkiaView element, ScrollToPosition position, bool animated)
+ {
+ if (element == null || _content == null)
+ return Task.CompletedTask;
+
+ var elementBounds = element.Bounds;
+ float targetX = _scrollX;
+ float targetY = _scrollY;
+
+ // Calculate viewport dimensions
+ float viewportWidth = Bounds.Width;
+ float viewportHeight = Bounds.Height;
+
+ switch (position)
+ {
+ case ScrollToPosition.Start:
+ targetX = elementBounds.Left;
+ targetY = elementBounds.Top;
+ break;
+
+ case ScrollToPosition.Center:
+ targetX = elementBounds.Left - (viewportWidth - elementBounds.Width) / 2;
+ targetY = elementBounds.Top - (viewportHeight - elementBounds.Height) / 2;
+ break;
+
+ case ScrollToPosition.End:
+ targetX = elementBounds.Right - viewportWidth;
+ targetY = elementBounds.Bottom - viewportHeight;
+ break;
+
+ case ScrollToPosition.MakeVisible:
+ default:
+ // Only scroll if element is not fully visible
+ if (elementBounds.Left < _scrollX)
+ targetX = elementBounds.Left;
+ else if (elementBounds.Right > _scrollX + viewportWidth)
+ targetX = elementBounds.Right - viewportWidth;
+
+ if (elementBounds.Top < _scrollY)
+ targetY = elementBounds.Top;
+ else if (elementBounds.Bottom > _scrollY + viewportHeight)
+ targetY = elementBounds.Bottom - viewportHeight;
+ break;
+ }
+
+ // Clamp to valid scroll range
+ targetX = Math.Clamp(targetX, 0, ScrollableWidth);
+ targetY = Math.Clamp(targetY, 0, ScrollableHeight);
+
+ return ScrollToAsync(targetX, targetY, animated);
}
///
@@ -773,6 +877,33 @@ public enum ScrollBarVisibility
Auto
}
+///
+/// Specifies the position within the ScrollView to scroll an element to.
+/// Matches Microsoft.Maui.ScrollToPosition enum.
+///
+public enum ScrollToPosition
+{
+ ///
+ /// Scroll so the element is just visible (minimal scroll).
+ ///
+ MakeVisible,
+
+ ///
+ /// Scroll so the element is at the start of the viewport.
+ ///
+ Start,
+
+ ///
+ /// Scroll so the element is at the center of the viewport.
+ ///
+ Center,
+
+ ///
+ /// Scroll so the element is at the end of the viewport.
+ ///
+ End
+}
+
///
/// Event args for scroll events.
///