Skip to content

Commit

Permalink
Update CommandBarFlyout close and open animations. (#4988)
Browse files Browse the repository at this point in the history
* Change CommandBarFlyout's Opening and Closing storyboards to opacity animations from clip animations.

* Disable transitions for Visual state changes made while the CommandBarFlyout is opening, we only want to fade in while opening.

* Fix Test failure.

* Remove the shadow animation with the new opacity animation as it is not required.

* Fix shadow issues, turn off drop shadows for V1 styles.

* Fix test control CBF test failures

* respond to feedback

* remove the primary shadow when closing all animation types.
  • Loading branch information
StephenLPeters authored May 18, 2021
1 parent 0689765 commit f56157d
Show file tree
Hide file tree
Showing 8 changed files with 236 additions and 170 deletions.
63 changes: 42 additions & 21 deletions dev/CommandBarFlyout/CommandBarFlyout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,22 +127,41 @@ CommandBarFlyout::CommandBarFlyout()

if (auto commandBar = m_commandBar.get())
{
// If we don't have IFlyoutBase5 available, then we assume a standard show mode.
if (!thisAsFlyoutBase5 || thisAsFlyoutBase5.ShowMode() == winrt::FlyoutShowMode::Standard)
{
commandBar.IsOpen(true);
}

// If we are in AlwaysExpanded mode then we want to make sure we open in Standard ShowMode
// Otherwise the timing on the creation of the two drops shows is such that the primary items
// draw their shadow on top of the secondary items.
// When CommandBarFlyout is in AlwaysOpen state, don't show the overflow button
if (AlwaysExpanded())
{
commandBar.IsOpen(true);
commandBar.OverflowButtonVisibility(winrt::Windows::UI::Xaml::Controls::CommandBarOverflowButtonVisibility::Collapsed);
if (thisAsFlyoutBase5)
{
thisAsFlyoutBase5.ShowMode(winrt::FlyoutShowMode::Standard);
}
}
else
{
commandBar.OverflowButtonVisibility(winrt::Windows::UI::Xaml::Controls::CommandBarOverflowButtonVisibility::Auto);
}
SharedHelpers::QueueCallbackForCompositionRendering(
[strongThis = get_strong(), thisAsFlyoutBase5, commandBar]
{
if (auto const commandBarFlyoutCommandBar = winrt::get_self<CommandBarFlyoutCommandBar>(commandBar))
{
auto const scopeGuard = gsl::finally([commandBarFlyoutCommandBar]()
{
commandBarFlyoutCommandBar->m_commandBarFlyoutIsOpening = false;
});
commandBarFlyoutCommandBar->m_commandBarFlyoutIsOpening = true;

// If we don't have IFlyoutBase5 available, then we assume a standard show mode.
if (!thisAsFlyoutBase5 || thisAsFlyoutBase5.ShowMode() == winrt::FlyoutShowMode::Standard)
{
commandBar.IsOpen(true);
}
}
}
);
}

if (m_primaryCommands.Size() > 0)
Expand Down Expand Up @@ -170,6 +189,9 @@ CommandBarFlyout::CommandBarFlyout()
{
if (auto commandBar = winrt::get_self<CommandBarFlyoutCommandBar>(m_commandBar.get()))
{
// We are not able to fade this shadow out with the V2 default opacity closing animition.
// Additionally we drop shadows doing play well with the clip animation of the V1 style.
// So we need to remove it in all cases.
RemoveDropShadow();

if (!m_isClosingAfterCloseAnimation && commandBar->HasCloseAnimation())
Expand All @@ -184,20 +206,22 @@ CommandBarFlyout::CommandBarFlyout()
m_isClosingAfterCloseAnimation = false;
});
}
else
{
// If we don't have an animation, close the command bar and thus it's subflyouts.
commandBar->IsOpen(false);
}

// Close commandbar and thus other associated flyouts
commandBar->IsOpen(false);

//CommandBarFlyoutCommandBar.Closed will be called when
//clicking the more (...) button, we clear the translations
//here
commandBar->ClearShadow();
//Drop shadows do not play nicely with clip animations, if we are using both, clear the shadow
if (SharedHelpers::Is21H1OrHigher() && commandBar->OpenAnimationKind() == CommandBarFlyoutOpenCloseAnimationKind::Clip)
{
commandBar->ClearShadow();
}
}
}
});

// If we didn't close the CommandBar in the Closing event, we want to do it here,
// in order to ensure that we're always starting from a known state when opening the flyout.
// Close the CommandBar in order to ensure that we're always starting from a known state when opening the flyout.
Closed({
[this](auto const&, auto const&)
{
Expand Down Expand Up @@ -271,10 +295,7 @@ winrt::Control CommandBarFlyout::CreatePresenter()

if (SharedHelpers::Is21H1OrHigher())
{
// Since DropShadows don't play well with the entrance animation for the presenter,
// we'll need to fade it in. This name helps us locate the element to set the fade in
// flag in the OS code.
presenter.Name(L"DropShadowFadeInTarget");
commandBar->SetPresenter(presenter);

// We'll need to remove the presenter's drop shadow on the commandBar's Opening/Closing
// because we need it to disappear during its expand/shrink animation when the Overflow is opened.
Expand All @@ -290,7 +311,7 @@ winrt::Control CommandBarFlyout::CreatePresenter()
// We'll only need to do the mid-animation remove/add when the "..." button is
// pressed to open/close the overflow. This means we shouldn't do it for AlwaysExpanded
// and if there's nothing in the overflow.
if (!AlwaysExpanded() && m_secondaryCommands.Size() > 0)
if (m_secondaryCommands.Size() > 0)
{
RemoveDropShadow();
}
Expand Down
142 changes: 97 additions & 45 deletions dev/CommandBarFlyout/CommandBarFlyoutCommandBar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ CommandBarFlyoutCommandBar::CommandBarFlyoutCommandBar()
{
COMMANDBARFLYOUT_TRACE_INFO(*this, TRACE_MSG_METH, METH_NAME, this);

UpdateUI();
UpdateUI(!m_commandBarFlyoutIsOpening);

// Programmatically focus the first primary command if any, else programmatically focus the first secondary command if any.
auto commands = PrimaryCommands().Size() > 0 ? PrimaryCommands() : (SecondaryCommands().Size() > 0 ? SecondaryCommands() : nullptr);
Expand Down Expand Up @@ -67,7 +67,7 @@ CommandBarFlyoutCommandBar::CommandBarFlyoutCommandBar()
{
COMMANDBARFLYOUT_TRACE_VERBOSE(*this, TRACE_MSG_METH, METH_NAME, this);

UpdateUI();
UpdateUI(!m_commandBarFlyoutIsOpening);
}
});

Expand Down Expand Up @@ -108,7 +108,7 @@ CommandBarFlyoutCommandBar::CommandBarFlyoutCommandBar()
COMMANDBARFLYOUT_TRACE_VERBOSE(*this, TRACE_MSG_METH, METH_NAME, this);

UpdateFlowsFromAndFlowsTo();
UpdateUI();
UpdateUI(!m_commandBarFlyoutIsOpening);
});

// Since we own these vectors, we don't need to cache the event tokens -
Expand All @@ -120,7 +120,7 @@ CommandBarFlyoutCommandBar::CommandBarFlyoutCommandBar()
COMMANDBARFLYOUT_TRACE_VERBOSE(*this, TRACE_MSG_METH, METH_NAME, this);

UpdateFlowsFromAndFlowsTo();
UpdateUI();
UpdateUI(!m_commandBarFlyoutIsOpening);
}
});

Expand All @@ -131,7 +131,7 @@ CommandBarFlyoutCommandBar::CommandBarFlyoutCommandBar()

m_secondaryItemsRootSized = false;
UpdateFlowsFromAndFlowsTo();
UpdateUI();
UpdateUI(!m_commandBarFlyoutIsOpening);
}
});
}
Expand All @@ -158,8 +158,24 @@ void CommandBarFlyoutCommandBar::OnApplyTemplate()
m_overflowPopup.set(GetTemplateChildT<winrt::Popup>(L"OverflowPopup", thisAsControlProtected));
m_secondaryItemsRoot.set(GetTemplateChildT<winrt::FrameworkElement>(L"OverflowContentRoot", thisAsControlProtected));
m_moreButton.set(GetTemplateChildT<winrt::ButtonBase>(L"MoreButton", thisAsControlProtected));
m_openingStoryboard.set(GetTemplateChildT<winrt::Storyboard>(L"OpeningStoryboard", thisAsControlProtected));
m_closingStoryboard.set(GetTemplateChildT<winrt::Storyboard>(L"ClosingStoryboard", thisAsControlProtected));
m_openingStoryboard.set([this, thisAsControlProtected]()
{
if (auto const opacityStoryBoard = GetTemplateChildT<winrt::Storyboard>(L"OpeningOpacityStoryboard", thisAsControlProtected))
{
m_openAnimationKind = CommandBarFlyoutOpenCloseAnimationKind::Opacity;
return opacityStoryBoard;
}
m_openAnimationKind = CommandBarFlyoutOpenCloseAnimationKind::Clip;
return GetTemplateChildT<winrt::Storyboard>(L"OpeningStoryboard", thisAsControlProtected);
}());
m_closingStoryboard.set([this, thisAsControlProtected]()
{
if (auto const opacityStoryBoard = GetTemplateChildT<winrt::Storyboard>(L"ClosingOpacityStoryboard", thisAsControlProtected))
{
return opacityStoryBoard;
}
return GetTemplateChildT<winrt::Storyboard>(L"ClosingStoryboard", thisAsControlProtected);
}());

if (auto& overflowPopup = m_overflowPopup.get())
{
Expand Down Expand Up @@ -195,6 +211,7 @@ void CommandBarFlyoutCommandBar::OnApplyTemplate()
AttachEventHandlers();
UpdateFlowsFromAndFlowsTo();
UpdateUI(false /* useTransitions */);
SetPresenterName(m_flyoutPresenter.get());
}

void CommandBarFlyoutCommandBar::SetOwningFlyout(
Expand Down Expand Up @@ -228,7 +245,7 @@ void CommandBarFlyoutCommandBar::AttachEventHandlers()
[this](auto const&, auto const&)
{
m_secondaryItemsRootSized = true;
UpdateUI();
UpdateUI(!m_commandBarFlyoutIsOpening);
}
});

Expand Down Expand Up @@ -534,7 +551,7 @@ void CommandBarFlyoutCommandBar::UpdateUI(
UpdateTemplateSettings();
UpdateVisualState(useTransitions);

UpdateShadow();
UpdateProjectedShadow();
}

void CommandBarFlyoutCommandBar::UpdateVisualState(
Expand Down Expand Up @@ -617,15 +634,18 @@ void CommandBarFlyoutCommandBar::UpdateVisualState(
{
if (shouldExpandUp)
{
winrt::VisualStateManager::GoToState(*this, L"NoOuterOverflowContentRootShadow", useTransitions);
winrt::VisualStateManager::GoToState(*this, L"ExpandedUpWithPrimaryCommands", useTransitions);
}
else
{
winrt::VisualStateManager::GoToState(*this, L"OuterOverflowContentRootShadow", useTransitions);
winrt::VisualStateManager::GoToState(*this, L"ExpandedDownWithPrimaryCommands", useTransitions);
}
}
else
{
winrt::VisualStateManager::GoToState(*this, L"OuterOverflowContentRootShadow", useTransitions);
if (shouldExpandUp)
{
winrt::VisualStateManager::GoToState(*this, L"ExpandedUpWithoutPrimaryCommands", useTransitions);
Expand All @@ -638,6 +658,7 @@ void CommandBarFlyoutCommandBar::UpdateVisualState(
}
else
{
winrt::VisualStateManager::GoToState(*this, L"NoOuterOverflowContentRootShadow", useTransitions);
winrt::VisualStateManager::GoToState(*this, L"Default", useTransitions);
winrt::VisualStateManager::GoToState(*this, L"Collapsed", useTransitions);
}
Expand Down Expand Up @@ -1181,62 +1202,93 @@ void CommandBarFlyoutCommandBar::EnsureTabStopUniqueness(
}
}

void CommandBarFlyoutCommandBar::UpdateShadow()
void CommandBarFlyoutCommandBar::UpdateProjectedShadow()
{
if (PrimaryCommands().Size() > 0)
if (SharedHelpers::IsThemeShadowAvailable() && !SharedHelpers::Is21H1OrHigher())
{
AddShadow();
if (PrimaryCommands().Size() > 0)
{
AddProjectedShadow();
}
else if (PrimaryCommands().Size() == 0)
{
ClearProjectedShadow();
}
}
else if (PrimaryCommands().Size() == 0)
}

void CommandBarFlyoutCommandBar::AddProjectedShadow()
{
//This logic applies to projected shadows, which are the default on < 21H1.
//See additional notes in CommandBarFlyout::CreatePresenter().
//Apply Shadow on the Grid named "ContentRoot", this is the first element below
//the clip animation of the commandBar. This guarantees that shadow respects the
//animation
winrt::IControlProtected thisAsControlProtected = *this;
auto grid = GetTemplateChildT<winrt::Grid>(L"ContentRoot", thisAsControlProtected);

if (winrt::IUIElement10 grid_uiElement10 = grid)
{
ClearShadow();
if (!grid_uiElement10.Shadow())
{
winrt::Windows::UI::Xaml::Media::ThemeShadow shadow;
grid_uiElement10.Shadow(shadow);

const auto translation = winrt::float3{ grid.Translation().x, grid.Translation().y, 32.0f };
grid.Translation(translation);
}
}
}

void CommandBarFlyoutCommandBar::AddShadow()
void CommandBarFlyoutCommandBar::ClearProjectedShadow()
{
if (SharedHelpers::IsThemeShadowAvailable() && !SharedHelpers::Is21H1OrHigher())
// This logic applies to projected shadows, which are the default on < 21H1.
// See additional notes in CommandBarFlyout::CreatePresenter().
winrt::IControlProtected thisAsControlProtected = *this;
auto grid = GetTemplateChildT<winrt::Grid>(L"ContentRoot", thisAsControlProtected);
if (winrt::IUIElement10 grid_uiElement10 = grid)
{
//This logic applies to projected shadows, which are the default on < 21H1.
//See additional notes in CommandBarFlyout::CreatePresenter().
//Apply Shadow on the Grid named "ContentRoot", this is the first element below
//the clip animation of the commandBar. This guarantees that shadow respects the
//animation
winrt::IControlProtected thisAsControlProtected = *this;
auto grid = GetTemplateChildT<winrt::Grid>(L"ContentRoot", thisAsControlProtected);

if (winrt::IUIElement10 grid_uiElement10 = grid)
if (grid_uiElement10.Shadow())
{
if (!grid_uiElement10.Shadow())
{
winrt::Windows::UI::Xaml::Media::ThemeShadow shadow;
grid_uiElement10.Shadow(shadow);
grid_uiElement10.Shadow(nullptr);

const auto translation = winrt::float3{ grid.Translation().x, grid.Translation().y, 32.0f };
grid.Translation(translation);
}
//Undo the elevation
const auto translation = winrt::float3{ grid.Translation().x, grid.Translation().y, 0.0f };
grid.Translation(translation);
}
}
}


void CommandBarFlyoutCommandBar::ClearShadow()
{
if (SharedHelpers::IsThemeShadowAvailable() && !SharedHelpers::Is21H1OrHigher())
{
// This logic applies to projected shadows, which are the default on < 21H1.
// See additional notes in CommandBarFlyout::CreatePresenter().
winrt::IControlProtected thisAsControlProtected = *this;
auto grid = GetTemplateChildT<winrt::Grid>(L"ContentRoot", thisAsControlProtected);
if (winrt::IUIElement10 grid_uiElement10 = grid)
{
if (grid_uiElement10.Shadow())
{
grid_uiElement10.Shadow(nullptr);
ClearProjectedShadow();
}
winrt::VisualStateManager::GoToState(*this, L"NoOuterOverflowContentRootShadow", true/*useTransitions*/);
}

//Undo the elevation
const auto translation = winrt::float3{ grid.Translation().x, grid.Translation().y, 0.0f };
grid.Translation(translation);
}

void CommandBarFlyoutCommandBar::SetPresenter(winrt::FlyoutPresenter const& presenter)
{
m_flyoutPresenter = winrt::make_weak(presenter);
}

void CommandBarFlyoutCommandBar::SetPresenterName(winrt::FlyoutPresenter const& presenter)
{
// Since DropShadows don't play well with clip entrance animations for the presenter,
// we'll need to fade it in. This name helps us locate the element to set the fade in
// flag in the OS code.
if (presenter)
{
if (OpenAnimationKind() == CommandBarFlyoutOpenCloseAnimationKind::Clip)
{
presenter.Name(L"DropShadowFadeInTarget");
}
else
{
presenter.Name(L"");
}
}
}
Expand Down
Loading

0 comments on commit f56157d

Please sign in to comment.