Skip to content

Commit

Permalink
fix: Apply zoom and content offset simultaneously on iOS
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinZikmund committed Apr 9, 2022
1 parent d149662 commit e92379f
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
using System.Collections.Generic;
using System.Text;
using CoreGraphics;
using UIKit;
using Uno.Extensions;

using Uno.Foundation.Logging;
using Windows.Foundation;
using UIKit;

#if NET6_0_OR_GREATER
using ObjCRuntime;
Expand All @@ -26,6 +25,44 @@ public UIEdgeInsets ContentInset

Size? IScrollContentPresenter.CustomContentExtent => NativePanel?.ContentSize;

CGPoint IUIScrollView.ContentOffset => NativePanel?.ContentOffset ?? default(CGPoint);

nfloat IUIScrollView.ZoomScale => NativePanel?.ZoomScale ?? default(nfloat);

void IUIScrollView.ApplyZoomScale(nfloat scale, bool animated)
{
if (NativePanel == null)
{
return;
}

if (animated)
{
NativePanel.SetZoomScale(scale, animated);
}
else
{
NativePanel.ZoomScale = scale;
}
}

void IUIScrollView.ApplyContentOffset(CGPoint contentOffset, bool animated)
{
if (NativePanel == null)
{
return;
}

if (animated)
{
NativePanel.SetContentOffset(contentOffset, animated);
}
else
{
NativePanel.ContentOffset = contentOffset;
}
}

public void SetContentOffset(CGPoint contentOffset, bool animated)
{
NativePanel?.SetContentOffset(contentOffset, animated);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,14 @@ internal interface IUIScrollView
{
CGPoint UpperScrollLimit { get; }

void SetContentOffset(CGPoint contentOffset, bool animated);
CGPoint ContentOffset { get; }

void ApplyContentOffset(CGPoint contentOffset, bool animated);

#if __IOS__
void SetZoomScale(nfloat scale, bool animated);
nfloat ZoomScale { get; }

void ApplyZoomScale(nfloat scale, bool animated);
#endif
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ partial class NativeScrollContentPresenter : UIScrollView, DependencyObject, ISe
private bool _isInAnimatedScroll;

CGPoint IUIScrollView.UpperScrollLimit => UpperScrollLimit;

CGPoint IUIScrollView.ContentOffset => ContentOffset;

nfloat IUIScrollView.ZoomScale => ZoomScale;

internal CGPoint UpperScrollLimit
{
get
Expand Down Expand Up @@ -158,6 +163,30 @@ public override void SetContentOffset(CGPoint contentOffset, bool animated)
}
}

void IUIScrollView.ApplyZoomScale(nfloat scale, bool animated)
{
if (!animated)
{
ZoomScale = scale;
}
else
{
base.SetZoomScale(scale, true);
}
}

void IUIScrollView.ApplyContentOffset(CGPoint contentOffset, bool animated)
{
if (!animated)
{
ContentOffset = contentOffset;
}
else
{
base.SetContentOffset(contentOffset, true);
}
}

partial void OnContentChanged(UIView previousView, UIView newView)
{
// If Content is a view it may have already been set as Content somewhere else in certain scenarios
Expand All @@ -166,7 +195,7 @@ partial void OnContentChanged(UIView previousView, UIView newView)
previousView.RemoveFromSuperview();
}

// Ensure we're working with an empty view, in case previously removed views were missed.
// Ensure we're working with an empty view, in case previously removed views were missed.
while (Subviews.Length > 0)
{
Subviews[0].RemoveFromSuperview();
Expand Down Expand Up @@ -534,7 +563,7 @@ public override void TouchesBegan(NSSet touches, UIEvent evt)
// (e.g. it would prevent all sub-sequent events for the given pointer).

_touchTarget = parent;
_touchTarget.TouchesBegan(touches, evt, canBubbleNatively: true);
_touchTarget.TouchesBegan(touches, evt, canBubbleNatively: true);
}
}

Expand Down
26 changes: 14 additions & 12 deletions src/Uno.UI/UI/Xaml/Controls/ScrollViewer/ScrollViewer.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,24 +86,31 @@ private bool ChangeViewNative(double? horizontalOffset, double? verticalOffset,
var desiredOffsets = new Windows.Foundation.Point(horizontalOffset ?? HorizontalOffset, verticalOffset ?? VerticalOffset);
var clampedOffsets = new Windows.Foundation.Point(MathEx.Clamp(desiredOffsets.X, 0, limit.X), MathEx.Clamp(desiredOffsets.Y, 0, limit.Y));

var contentOffsetChange =
(horizontalOffset != null && _scrollableContainer.ContentOffset.X != horizontalOffset) ||
(verticalOffset != null && _scrollableContainer.ContentOffset.Y != verticalOffset);

var zoomFactorChange = zoomFactor != null && _scrollableContainer.ZoomScale != zoomFactor;

var success = desiredOffsets == clampedOffsets;

if (zoomFactor is { } zoom && zoom != _scrollableContainer.ZoomScale)
{
_scrollableContainer.ApplyZoomScale(zoom, !disableAnimation);
}

if (!success && IsArrangeDirty)
{
// If the the requested offsets are out-of - bounds, but we actually does have our final bounds yet,
// we allow to set the desired offsets. If needed, they will then be clamped by the OnAfterArrange().
// This is needed to allow a ScrollTo before the SV has been layouted.

_pendingChangeView = (horizontalOffset, verticalOffset, disableAnimation);
_scrollableContainer.SetContentOffset(desiredOffsets, !disableAnimation);
_scrollableContainer.ApplyContentOffset(desiredOffsets, !disableAnimation);
}
else
{
_scrollableContainer.SetContentOffset(clampedOffsets, !disableAnimation);
}

if(zoomFactor is { } zoom)
{
ChangeViewZoom(zoom, disableAnimation);
_scrollableContainer.ApplyContentOffset(clampedOffsets, !disableAnimation);
}

// Return true if successfully scrolled to asked offsets
Expand All @@ -130,11 +137,6 @@ partial void OnZoomModeChangedPartial(ZoomMode zoomMode)
}
}

private void ChangeViewZoom(float zoomFactor, bool disableAnimation)
{
_scrollableContainer?.SetZoomScale(zoomFactor, animated: !disableAnimation);
}

private void UpdateZoomedContentAlignment()
{
if (ZoomFactor != 1 && Content is IFrameworkElement fe)
Expand Down
24 changes: 24 additions & 0 deletions src/Uno.UI/UI/Xaml/Controls/TextBox/MultilineTextBoxView.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,30 @@ public partial class MultilineTextBoxView : UITextView, ITextBoxView, Dependency

CGPoint IUIScrollView.UpperScrollLimit { get { return (CGPoint)(ContentSize - Frame.Size); } }

void IUIScrollView.ApplyZoomScale(nfloat scale, bool animated)
{
if (animated)
{
SetZoomScale(scale, animated);
}
else
{
ZoomScale = scale;
}
}

void IUIScrollView.ApplyContentOffset(CGPoint contentOffset, bool animated)
{
if (animated)
{
SetContentOffset(contentOffset, animated);
}
else
{
ContentOffset = contentOffset;
}
}

public MultilineTextBoxView(TextBox textBox)
{
_textBox = new WeakReference<TextBox>(textBox);
Expand Down

0 comments on commit e92379f

Please sign in to comment.