Skip to content

Add ExpanderAnimationBehavior, IExpansionController#3124

Open
stephenquan wants to merge 11 commits intoCommunityToolkit:mainfrom
stephenquan:feature/stephenquan/2521-expander-v2
Open

Add ExpanderAnimationBehavior, IExpansionController#3124
stephenquan wants to merge 11 commits intoCommunityToolkit:mainfrom
stephenquan:feature/stephenquan/2521-expander-v2

Conversation

@stephenquan
Copy link
Copy Markdown
Contributor

@stephenquan stephenquan commented Mar 1, 2026

…EventArgs

Description of Change

Enables animated expand/collapse behavior for the Expander by wrapping the user’s content Expander.Content in a Expander.ContentHost (ContentView) and animating changes to Expander.ContentHost.HeightRequest.

  • Add Expander.ContentHost property (read-only).
  • Add IExpansionController interface.
  • Add Expander.ExpansionController property.
  • Add Expander.ExpandedChanging event with ExpandedChangingEventArgs.
  • Add ExpansionAnimationBehavior behavior.
  • Update the sample app to demonstrate ExpandedAnimationBehavior.

Opt in to animations by assigning ExpansionAnimationBehavior to either (1) Expander.Behaviors, or (2) Expander.ExpansionController. Alternatively, custom animations can be created by implementing IExpansionController.

Linked Issues

PR Checklist

Additional information

This is a reboot of the work that began in PR #2723 and PR #2522.

Copilot AI review requested due to automatic review settings March 1, 2026 11:52
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a pluggable expansion/collapse pipeline to Expander to enable animated transitions via an IExpansionController, plus a default animation behavior and updated samples demonstrating the new functionality.

Changes:

  • Introduces IExpansionController and wires Expander.ExpansionController into the expand/collapse flow.
  • Adds ExpandedChanging + ExpandedChangingEventArgs, and refactors Expander content handling to use a ContentHost container suitable for animation.
  • Adds ExpanderAnimationBehavior implementing IExpansionController, and updates the sample page to demonstrate animation timing.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
src/CommunityToolkit.Maui/Views/Expander/Expander.shared.cs Adds controller-based expand/collapse pipeline, new event, and ContentHost wrapper used for animation.
src/CommunityToolkit.Maui/Interfaces/IExpansionController.shared.cs New interface to plug in animated (or instant) expand/collapse implementations.
src/CommunityToolkit.Maui/Behaviors/ExpanderAnimationBehavior.shared.cs New behavior implementing IExpansionController using Animation to animate expansion/collapse.
src/CommunityToolkit.Maui.Core/Primitives/ExpandedChangingEventArgs.shared.cs New event args for “about to change expanded state”.
src/CommunityToolkit.Maui.Core/Primitives/Defaults/ExpanderAnimationBehaviorDefaults.shared.cs Defaults for easing/duration used by ExpanderAnimationBehavior.
samples/CommunityToolkit.Maui.Sample/Pages/Views/Expander/ExpanderPage.xaml.cs Measures elapsed time between ExpandedChanging and ExpandedChanged and shows it in a toast.
samples/CommunityToolkit.Maui.Sample/Pages/Views/Expander/ExpanderPage.xaml Applies ExpanderAnimationBehavior in samples and hooks ExpandedChanging/ExpandedChanged handlers.

Copilot AI review requested due to automatic review settings March 2, 2026 00:29
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 7 comments.

Copilot AI review requested due to automatic review settings March 2, 2026 04:29
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.

Copilot AI review requested due to automatic review settings March 2, 2026 09:15
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 7 comments.

Copilot AI review requested due to automatic review settings March 2, 2026 09:41
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Comment on lines 104 to 106
<mct:Expander x:DataType="sample:ContentCreator"
HeightRequest="180"
ExpandedChanged="Expander_ExpandedChanged">
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GridItemsLayout sample sets a hard-coded HeightRequest="180" on the Expander, which prevents the control from naturally resizing based on expanded/collapsed state and introduces an unexplained magic number. If this is required as a workaround for GridItemsLayout item sizing, consider documenting why in a comment (or remove the fixed height and apply the animation behavior here instead) so the sample demonstrates expected expander behavior.

Copilot uses AI. Check for mistakes.
Comment on lines +231 to +235
_ = Dispatcher.Dispatch(async () =>
{
await expansionGate.Task;
ResizeExpanderInItemsView2(tappedEventArgs);
});
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ResizeExpanderInItemsView awaits expansionGate.Task, but expansionGate is a mutable field that gets replaced on each IsExpanded change. With rapid toggles, this dispatched lambda can end up awaiting a different gate instance than the one completed by the corresponding transition, causing hangs/missed size updates. Capture the current gate/task into a local before dispatch/await, and ensure the same captured gate instance is the one completed by the matching expand/collapse transition.

Copilot uses AI. Check for mistakes.
Comment on lines +292 to +295
finally
{
expansionGate.TrySetResult();
}
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ExpandedChangedAsync signals completion via expansionGate.TrySetResult() on the mutable field. If expansionGate has been replaced by a newer transition while this async method was awaiting the controller, it will complete the wrong gate and leave the previous one uncompleted (which can block awaiting resize logic). Capture the current TaskCompletionSource into a local at the start of the transition and complete that captured instance in finally.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Proposal] Expander animation

4 participants