Skip to content

Commit

Permalink
Implement View Transformations
Browse files Browse the repository at this point in the history
  • Loading branch information
jsuarezruiz committed May 11, 2021
1 parent ebaec02 commit ff6203e
Show file tree
Hide file tree
Showing 18 changed files with 827 additions and 10 deletions.
8 changes: 8 additions & 0 deletions src/Compatibility/Core/src/Android/VisualElementTracker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ void SetElement(VisualElement oldElement, VisualElement newElement)
}
}

[PortHandler]
void UpdateAnchorX()
{
VisualElement view = _renderer.Element;
Expand All @@ -278,6 +279,7 @@ void UpdateAnchorX()
aview.PivotX = target;
}

[PortHandler]
void UpdateAnchorY()
{
VisualElement view = _renderer.Element;
Expand Down Expand Up @@ -400,6 +402,7 @@ void UpdateOpacity()
Performance.Stop(reference);
}

[PortHandler]
void UpdateRotation()
{
VisualElement view = _renderer.Element;
Expand All @@ -408,6 +411,7 @@ void UpdateRotation()
aview.Rotation = (float)view.Rotation;
}

[PortHandler]
void UpdateRotationX()
{
VisualElement view = _renderer.Element;
Expand All @@ -416,6 +420,7 @@ void UpdateRotationX()
aview.RotationX = (float)view.RotationX;
}

[PortHandler]
void UpdateRotationY()
{
VisualElement view = _renderer.Element;
Expand All @@ -424,6 +429,7 @@ void UpdateRotationY()
aview.RotationY = (float)view.RotationY;
}

[PortHandler]
void UpdateScale()
{
VisualElement view = _renderer.Element;
Expand All @@ -433,6 +439,7 @@ void UpdateScale()
aview.ScaleY = (float)view.Scale * (float)view.ScaleY;
}

[PortHandler]
void UpdateTranslationX()
{
VisualElement view = _renderer.Element;
Expand All @@ -441,6 +448,7 @@ void UpdateTranslationX()
aview.TranslationX = _context.ToPixels(view.TranslationX);
}

[PortHandler]
void UpdateTranslationY()
{
VisualElement view = _renderer.Element;
Expand Down
1 change: 1 addition & 0 deletions src/Compatibility/Core/src/iOS/VisualElementTracker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ void SetElement(VisualElement oldElement, VisualElement newElement)
}
}

[PortHandler("Partially ported")]
void UpdateNativeControl()
{
Performance.Start(out string reference);
Expand Down
15 changes: 15 additions & 0 deletions src/Controls/samples/Controls.Sample/Pages/MainPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ void SetupMauiLayout()
verticalStack.Add(CreateResizingButton());

AddTextResizeDemo(verticalStack);
verticalStack.Add(CreateTransformations());

verticalStack.Add(new Label { Text = " ", Padding = new Thickness(10) });
var label = new Label { Text = "End-aligned text", BackgroundColor = Colors.Fuchsia, HorizontalTextAlignment = TextAlignment.End };
Expand All @@ -74,6 +75,8 @@ void SetupMauiLayout()
new Button
{
Text = "Push a Page",
Rotation = 15,
Scale = 1.5,
Command = new Command(async () =>
{
await Navigation.PushAsync(new SemanticsPage());
Expand Down Expand Up @@ -357,6 +360,18 @@ IView CreateSampleGrid()
return layout;
}

IView CreateTransformations()
{
var verticalStack = new VerticalStackLayout();
var label = new Button { BackgroundColor = Colors.Red, TextColor = Colors.White, Text = "Transformations" };
var rotationSlider = new Slider { Minimum = -360, Maximum = 360 };
rotationSlider.ValueChanged += (sender, e) => label.Rotation = e.NewValue;
verticalStack.Add(rotationSlider);
verticalStack.Add(label);

return verticalStack;
}

void AddTextResizeDemo(Microsoft.Maui.ILayout layout)
{
var resizeTestButton = new Button { Text = "Resize Test" };
Expand Down
3 changes: 1 addition & 2 deletions src/Core/src/Core/IFrameworkElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Primitives;


namespace Microsoft.Maui
{
/// <summary>
/// Represents a framework-level set of properties, events, and methods for .NET MAUI elements.
/// </summary>
public interface IFrameworkElement
public interface IFrameworkElement : ITransform
{
/// <summary>
/// Gets a value indicating whether this FrameworkElement is enabled in the user interface.
Expand Down
63 changes: 63 additions & 0 deletions src/Core/src/Core/ITransform.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
namespace Microsoft.Maui
{
/// <summary>
/// Provides functionality to be able to apply transformations to a View.
/// </summary>
public interface ITransform
{
/// <summary>
/// Gets the X translation delta of the element.
/// </summary>
double TranslationX { get; }

/// <summary>
/// Gets the Y translation delta of the element.
/// </summary>
double TranslationY { get; }

/// <summary>
/// Gets the scale factor applied to the element.
/// </summary>
double Scale { get; }

/// <summary>
/// Gets the scale about the X-axis factor applied to the element.
/// </summary>
double ScaleX { get; }

/// <summary>
/// Gets the scale about the Y-axis factor applied to the element.
/// </summary>
double ScaleY { get; }

/// <summary>
/// Gets the rotation (in degrees) about the Z-axis (affine rotation)
/// when the element is rendered.
/// </summary>
double Rotation { get; }

/// <summary>
/// Gets the rotation (in degrees) about the X-axis (perspective rotation)
/// when the element is rendered.
/// </summary>
double RotationX { get; }

/// <summary>
/// Gets the rotation (in degrees) about the Y-axis (perspective rotation)
/// when the element is rendered.
/// </summary>
double RotationY { get; }

/// <summary>
/// Gets the X component of the center point for any transform, relative
/// to the bounds of the element.
/// </summary>
double AnchorX { get; }

/// <summary>
/// Gets the Y component of the center point for any transform, relative
/// to the bounds of the element.
/// </summary>
double AnchorY { get; }
}
}
52 changes: 51 additions & 1 deletion src/Core/src/Handlers/View/ViewHandler.Android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,61 @@ partial void DisconnectingHandler(NativeView? nativeView)
if (nativeView.IsAlive() && AccessibilityDelegate != null)
{
AccessibilityDelegate.Handler = null;
AndroidX.Core.View.ViewCompat.SetAccessibilityDelegate(nativeView, null);
ViewCompat.SetAccessibilityDelegate(nativeView, null);
AccessibilityDelegate = null;
}
}

public static void MapTranslationX(IViewHandler handler, IView view)
{
((NativeView?)handler.NativeView)?.UpdateTranslationX(view);
}

public static void MapTranslationY(IViewHandler handler, IView view)
{
((NativeView?)handler.NativeView)?.UpdateTranslationY(view);
}

public static void MapScale(IViewHandler handler, IView view)
{
((NativeView?)handler.NativeView)?.UpdateScale(view);
}

public static void MapScaleX(IViewHandler handler, IView view)
{
((NativeView?)handler.NativeView)?.UpdateScaleX(view);
}

public static void MapScaleY(IViewHandler handler, IView view)
{
((NativeView?)handler.NativeView)?.UpdateScaleY(view);
}

public static void MapRotation(IViewHandler handler, IView view)
{
((NativeView?)handler.NativeView)?.UpdateRotation(view);
}

public static void MapRotationX(IViewHandler handler, IView view)
{
((NativeView?)handler.NativeView)?.UpdateRotationX(view);
}

public static void MapRotationY(IViewHandler handler, IView view)
{
((NativeView?)handler.NativeView)?.UpdateRotationY(view);
}

public static void MapAnchorX(IViewHandler handler, IView view)
{
((NativeView?)handler.NativeView)?.UpdateAnchorX(view);
}

public static void MapAnchorY(IViewHandler handler, IView view)
{
((NativeView?)handler.NativeView)?.UpdateAnchorY(view);
}

static partial void MappingSemantics(IViewHandler handler, IView view)
{
if (view.Semantics != null &&
Expand Down
25 changes: 25 additions & 0 deletions src/Core/src/Handlers/View/ViewHandler.Standard.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace Microsoft.Maui.Handlers
{
public partial class ViewHandler
{
public static void MapTranslationX(IViewHandler handler, IView view) { }

public static void MapTranslationY(IViewHandler handler, IView view) { }

public static void MapScale(IViewHandler handler, IView view) { }

public static void MapScaleX(IViewHandler handler, IView view) { }

public static void MapScaleY(IViewHandler handler, IView view) { }

public static void MapRotation(IViewHandler handler, IView view) { }

public static void MapRotationX(IViewHandler handler, IView view) { }

public static void MapRotationY(IViewHandler handler, IView view) { }

public static void MapAnchorX(IViewHandler handler, IView view) { }

public static void MapAnchorY(IViewHandler handler, IView view) { }
}
}
58 changes: 58 additions & 0 deletions src/Core/src/Handlers/View/ViewHandler.Windows.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#nullable enable
using NativeView = Microsoft.UI.Xaml.FrameworkElement;

namespace Microsoft.Maui.Handlers
{
public partial class ViewHandler
{
public static void MapTranslationX(IViewHandler handler, IView view)
{
((NativeView?)handler.NativeView)?.UpdateTransformation(view);
}

public static void MapTranslationY(IViewHandler handler, IView view)
{
((NativeView?)handler.NativeView)?.UpdateTransformation(view);
}

public static void MapScale(IViewHandler handler, IView view)
{
((NativeView?)handler.NativeView)?.UpdateTransformation(view);
}

public static void MapScaleX(IViewHandler handler, IView view)
{
((NativeView?)handler.NativeView)?.UpdateTransformation(view);
}

public static void MapScaleY(IViewHandler handler, IView view)
{
((NativeView?)handler.NativeView)?.UpdateTransformation(view);
}

public static void MapRotation(IViewHandler handler, IView view)
{
((NativeView?)handler.NativeView)?.UpdateTransformation(view);
}

public static void MapRotationX(IViewHandler handler, IView view)
{
((NativeView?)handler.NativeView)?.UpdateTransformation(view);
}

public static void MapRotationY(IViewHandler handler, IView view)
{
((NativeView?)handler.NativeView)?.UpdateTransformation(view);
}

public static void MapAnchorX(IViewHandler handler, IView view)
{
((NativeView?)handler.NativeView)?.UpdateTransformation(view);
}

public static void MapAnchorY(IViewHandler handler, IView view)
{
((NativeView?)handler.NativeView)?.UpdateTransformation(view);
}
}
}
25 changes: 22 additions & 3 deletions src/Core/src/Handlers/View/ViewHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,20 @@ public abstract partial class ViewHandler : IViewHandler
[nameof(IView.Height)] = MapHeight,
[nameof(IView.IsEnabled)] = MapIsEnabled,
[nameof(IView.Semantics)] = MapSemantics,
Actions = {
[nameof(IFrameworkElement.InvalidateMeasure)] = MapInvalidateMeasure
}
[nameof(IView.TranslationX)] = MapTranslationX,
[nameof(IView.TranslationY)] = MapTranslationY,
[nameof(IView.Scale)] = MapScale,
[nameof(IView.ScaleX)] = MapScale,
[nameof(IView.ScaleY)] = MapScale,
[nameof(IView.Rotation)] = MapRotation,
[nameof(IView.RotationX)] = MapRotationX,
[nameof(IView.RotationY)] = MapRotationY,
[nameof(IView.AnchorX)] = MapAnchorX,
[nameof(IView.AnchorY)] = MapAnchorY,
Actions =
{
[nameof(IFrameworkElement.InvalidateMeasure)] = MapInvalidateMeasure
}
};

internal ViewHandler()
Expand Down Expand Up @@ -77,12 +88,20 @@ public bool HasContainer

private protected void ConnectHandler(NativeView? nativeView)
{
#if __IOS__
_layer = nativeView?.Layer;
_originalAnchor = _layer?.AnchorPoint;
#endif
}

partial void DisconnectingHandler(NativeView? nativeView);

private protected void DisconnectHandler(NativeView? nativeView)
{
#if __IOS__
_layer = null;
_originalAnchor = null;
#endif
DisconnectingHandler(nativeView);

if (VirtualView != null)
Expand Down
Loading

0 comments on commit ff6203e

Please sign in to comment.