Skip to content

Commit c1cdfee

Browse files
author
msftbot[bot]
authored
Optimize Visual size sync through RelativeSizeAdjustment over expression animations (#4397)
## PR Type What kind of change does this PR introduce? <!-- Please uncomment one or more options below that apply to this PR. --> - Optimization <!-- - Bugfix --> <!-- - Feature --> <!-- - Code style update (formatting) --> <!-- - Refactoring (no functional changes, no api changes) --> <!-- - Build or CI related changes --> <!-- - Documentation content changes --> <!-- - Sample app changes --> <!-- - Other... Please describe: --> ## What is the current behavior? All `Visual` objects created through our pipeline system are kept in sync with target objects through an expression animation. <!-- Please describe the current behavior that you are modifying, or link to a relevant issue. --> ## What is the new behavior? We're now just using [Visual.RelativeSizeAdjustment](https://docs.microsoft.com/en-us/uwp/api/windows.ui.composition.visual.relativesizeadjustment) to achieve the same without the animation overhead. I did test this in the sample app, but still adding the testing required tag as I'd like more validation on this. ## Open questions I'm wondering whether there's a way to also optimize this bit here by removing the animation: https://github.com/CommunityToolkit/WindowsCommunityToolkit/blob/4a09bf04531fb24e20dd8f42b18c0460f22d3ef3/Microsoft.Toolkit.Uwp.UI/Extensions/VisualExtensions.cs#L502-L511 Haven't yet figured out a solution though 🤔 **EDIT:** spoke with Chris, yeah there isn't a way to do this, nevermind 🤣 ## PR Checklist Please check if your PR fulfills the following requirements: <!-- and remove the ones that are not applicable to the current PR --> - [X] Tested code with current [supported SDKs](../#supported) - [ ] New component - [ ] Pull Request has been submitted to the documentation repository [instructions](../blob/main/Contributing.md#docs). Link: <!-- docs PR link --> - [ ] Added description of major feature to project description for NuGet package (4000 total character limit, so don't push entire description over that) - [ ] If control, added to Visual Studio Design project - [ ] Sample in sample app has been added / updated (for bug fixes / features) - [ ] Icon has been created (if new sample) following the [Thumbnail Style Guide and templates](https://github.com/CommunityToolkit/WindowsCommunityToolkit-design-assets) - [ ] New major technical changes in the toolkit have or will be added to the [Wiki](https://github.com/CommunityToolkit/WindowsCommunityToolkit/wiki) e.g. build changes, source generators, testing infrastructure, sample creation changes, etc... - [ ] Tests for the changes have been added (for bug fixes / features) (if applicable) - [X] Header has been added to all new source files (run _build/UpdateHeaders.bat_) - [X] Contains **NO** breaking changes
2 parents a629604 + c991429 commit c1cdfee

File tree

3 files changed

+18
-8
lines changed

3 files changed

+18
-8
lines changed

Microsoft.Toolkit.Uwp.UI.Media/Extensions/UIElementExtensions.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using System.Numerics;
6+
using Windows.UI.Composition;
57
using Windows.UI.Xaml;
68
using Windows.UI.Xaml.Hosting;
79

@@ -48,10 +50,10 @@ public static void SetVisualFactory(UIElement element, AttachedVisualFactoryBase
4850
/// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance for the current event.</param>
4951
private static async void OnVisualFactoryPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
5052
{
51-
var element = (UIElement)d;
52-
var attachedVisual = await ((AttachedVisualFactoryBase)e.NewValue).GetAttachedVisualAsync(element);
53+
UIElement element = (UIElement)d;
54+
Visual attachedVisual = await ((AttachedVisualFactoryBase)e.NewValue).GetAttachedVisualAsync(element);
5355

54-
attachedVisual.BindSize(element);
56+
attachedVisual.RelativeSizeAdjustment = Vector2.One;
5557

5658
ElementCompositionPreview.SetElementChildVisual(element, attachedVisual);
5759
}

Microsoft.Toolkit.Uwp.UI.Media/Extensions/Windows.UI.Composition/CompositionObjectExtensions.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ namespace Microsoft.Toolkit.Uwp.UI.Media
1818
internal static class CompositionObjectExtensions
1919
{
2020
/// <summary>
21-
/// Starts an <see cref="ExpressionAnimation"/> to keep the size of the source <see cref="CompositionObject"/> in sync with the target <see cref="UIElement"/>
21+
/// Starts an <see cref="ExpressionAnimation"/> to keep the size of the source <see cref="Visual"/> in sync with the target <see cref="UIElement"/>
2222
/// </summary>
23-
/// <param name="source">The <see cref="CompositionObject"/> to start the animation on</param>
23+
/// <param name="source">The <see cref="Visual"/> to start the animation on</param>
2424
/// <param name="target">The target <see cref="UIElement"/> to read the size updates from</param>
25-
public static void BindSize(this CompositionObject source, UIElement target)
25+
public static void BindSize(this Visual source, UIElement target)
2626
{
2727
var visual = ElementCompositionPreview.GetElementVisual(target);
2828
var bindSizeAnimation = source.Compositor.CreateExpressionAnimation($"{nameof(visual)}.Size");

Microsoft.Toolkit.Uwp.UI.Media/Pipelines/PipelineBuilder.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System;
66
using System.Collections.Generic;
77
using System.Diagnostics.Contracts;
8+
using System.Numerics;
89
using System.Threading.Tasks;
910
using Microsoft.Toolkit.Uwp.UI.Animations;
1011
using Windows.Graphics.Effects;
@@ -188,15 +189,22 @@ public async Task<CompositionBrush> BuildAsync()
188189
/// <returns>A <see cref="Task{T}"/> that returns the final <see cref="SpriteVisual"/> instance to use</returns>
189190
public async Task<SpriteVisual> AttachAsync(UIElement target, UIElement reference = null)
190191
{
191-
var visual = Window.Current.Compositor.CreateSpriteVisual();
192+
SpriteVisual visual = Window.Current.Compositor.CreateSpriteVisual();
192193

193194
visual.Brush = await BuildAsync();
194195

195196
ElementCompositionPreview.SetElementChildVisual(target, visual);
196197

197198
if (reference != null)
198199
{
199-
visual.BindSize(reference);
200+
if (reference == target)
201+
{
202+
visual.RelativeSizeAdjustment = Vector2.One;
203+
}
204+
else
205+
{
206+
visual.BindSize(reference);
207+
}
200208
}
201209

202210
return visual;

0 commit comments

Comments
 (0)