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:

4a09bf0453/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
This commit is contained in:
msftbot[bot] 2022-01-04 13:35:50 +00:00 коммит произвёл GitHub
Родитель a6296043b6 c99142919b
Коммит c1cdfee555
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 18 добавлений и 8 удалений

Просмотреть файл

@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Numerics;
using Windows.UI.Composition;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Hosting;
@ -48,10 +50,10 @@ namespace Microsoft.Toolkit.Uwp.UI.Media
/// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance for the current event.</param>
private static async void OnVisualFactoryPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var element = (UIElement)d;
var attachedVisual = await ((AttachedVisualFactoryBase)e.NewValue).GetAttachedVisualAsync(element);
UIElement element = (UIElement)d;
Visual attachedVisual = await ((AttachedVisualFactoryBase)e.NewValue).GetAttachedVisualAsync(element);
attachedVisual.BindSize(element);
attachedVisual.RelativeSizeAdjustment = Vector2.One;
ElementCompositionPreview.SetElementChildVisual(element, attachedVisual);
}

Просмотреть файл

@ -18,11 +18,11 @@ namespace Microsoft.Toolkit.Uwp.UI.Media
internal static class CompositionObjectExtensions
{
/// <summary>
/// Starts an <see cref="ExpressionAnimation"/> to keep the size of the source <see cref="CompositionObject"/> in sync with the target <see cref="UIElement"/>
/// Starts an <see cref="ExpressionAnimation"/> to keep the size of the source <see cref="Visual"/> in sync with the target <see cref="UIElement"/>
/// </summary>
/// <param name="source">The <see cref="CompositionObject"/> to start the animation on</param>
/// <param name="source">The <see cref="Visual"/> to start the animation on</param>
/// <param name="target">The target <see cref="UIElement"/> to read the size updates from</param>
public static void BindSize(this CompositionObject source, UIElement target)
public static void BindSize(this Visual source, UIElement target)
{
var visual = ElementCompositionPreview.GetElementVisual(target);
var bindSizeAnimation = source.Compositor.CreateExpressionAnimation($"{nameof(visual)}.Size");

Просмотреть файл

@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Numerics;
using System.Threading.Tasks;
using Microsoft.Toolkit.Uwp.UI.Animations;
using Windows.Graphics.Effects;
@ -188,7 +189,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Media.Pipelines
/// <returns>A <see cref="Task{T}"/> that returns the final <see cref="SpriteVisual"/> instance to use</returns>
public async Task<SpriteVisual> AttachAsync(UIElement target, UIElement reference = null)
{
var visual = Window.Current.Compositor.CreateSpriteVisual();
SpriteVisual visual = Window.Current.Compositor.CreateSpriteVisual();
visual.Brush = await BuildAsync();
@ -196,7 +197,14 @@ namespace Microsoft.Toolkit.Uwp.UI.Media.Pipelines
if (reference != null)
{
visual.BindSize(reference);
if (reference == target)
{
visual.RelativeSizeAdjustment = Vector2.One;
}
else
{
visual.BindSize(reference);
}
}
return visual;