Как я могу предотвратить вмешательство XAML VisualStates в анимацию композиции пользовательского интерфейса Windows?

#uwp #composition #winui

#uwp #композиция #winui

Вопрос:

Я считаю, что инструменты Windows.UI.Composition конфликтуют с визуальными состояниями XAML на кнопках.

GIF # 1 Когда кнопка находится в обычном состоянии, без наведения курсора, анимация работает, и кнопки успешно исчезают при прокрутке вниз, а затем снова успешно появляются при прокрутке вверх.

GIF # 2 Если курсор наведен на кнопку, когда анимация композиции завершается, и мышь выходит из кнопки перед прокруткой вверх, я полагаю, что состояние наведения указателя зависает, а непрозрачность 0% застревает. Единственный способ исправить это — снова навести курсор мыши, чтобы отменить отображение визуальных состояний XAML.

Кнопки могут исчезать и появляться снова.
Кнопки исчезают и не появляются до события PointerOver

Все кнопки находятся в одной и той же панели стека, которая является целью анимации непрозрачности. Когда у одной кнопки возникает эта проблема, вся панель стека застревает с непрозрачностью 0%. Приведенный ниже код представляет собой общую суть, некоторые фрагменты опущены для краткости. Я не думаю, что это проблема с кодом, я думаю, что это ограничение платформы, и я ищу обходной путь.

 CompositionPropertySet _scrollerPropertySet = 
ElementCompositionPreview.GetScrollViewerManipulationPropertySet((ScrollViewer)sender);
Compositor _compositor = _scrollerPropertySet.Compositor;
CompositionPropertySet _props = _compositor.CreatePropertySet();
_props.InsertScalar("progress", 0);
var scrollingProperties = 
_scrollerPropertySet.GetSpecializedReference<ManipulationPropertySetReferenceNode>();
var props = _props.GetReference();
var progressNode = props.GetScalarProperty("progress");
ExpressionNode progressAnimation = EF.Clamp(-scrollingProperties.Translation.Y / clampSizeNode, 0, 1);
_props.StartAnimation("progress", progressAnimation);

// StackPanel relevant code:

Visual carOperationButtonStackPanelVisual= 
ElementCompositionPreview.GetElementVisual(CarOperationStackPanel);
ExpressionNode carSubtitleObjectOpacityAnimation = 1 - (progressNode * 2);
carOperationButtonStackPanelVisual.StartAnimation("Opacity", carSubtitleObjectOpacityAnimation);
  

Ответ №1:

В приведенном выше фрагменте кода, ближе к концу, эта строка

 ExpressionNode carSubtitleObjectOpacityAnimation = 1 - (progressNode * 2);
  

должно быть

 ExpressionNode carSubtitleObjectOpacityAnimation = ExpressionFunctions.Lerp(0, 1, 1 - (progressNode * 2));
  

Это заставит непрозрачность обновляться с помощью линейной интерполяции от 0 до 1. Для чего это стоит, я скопировал исходный код из репозитория образцов пользовательского интерфейса Win, который не использует Lerp() для непрозрачности. Я пришел к выводу, что Lerp более обременителен для системы, но необходим, когда элементы управления имеют визуальные состояния. Пример репозитория анимирует простой текстовый блок (у которого нет визуальных состояний).