Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expander #478

Merged
merged 47 commits into from
Nov 8, 2022
Merged

Expander #478

merged 47 commits into from
Nov 8, 2022

Conversation

VladislavAntonyuk
Copy link
Collaborator

@VladislavAntonyuk VladislavAntonyuk commented Jul 1, 2022

Description of Change

New Expander control.
Uses custom implementation on Android and iOS and native WinUI expander control.

Linked Issues

PR Checklist

Additional information

Copy link
Member

@pictos pictos left a comment

Choose a reason for hiding this comment

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

Great work man, I did a quick review. I'll re-review again tomorrow since I'm a little sleepy and I may have missed something.

@VladislavAntonyuk VladislavAntonyuk marked this pull request as ready for review July 5, 2022 21:02
Copy link
Member

@pictos pictos left a comment

Choose a reason for hiding this comment

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

@VladislavAntonyuk Thanks for this PR. I have some code suggestions and also found some bugs in all platforms. I'll do the Android and Windows in another post since the assets are on my Windows machine.

General

IMHO, since Windows provide control for that we should try to follow its guidelines, for example on Windows the header has an arrow icon and the controls have a better arrangement, we should mimic that for Android and Apple as well.

iOS / macOS

  1. We need to click two times to collapse or expand the control, as you can see in the video below.

Uploading Screen Recording 2022-07-05 at 20.13.22.mov…

  1. The Baboon expander doesn't appear

Screen Shot 2022-07-05 at 20 14 02

  1. The simple and multiple expanders doesn't work as well, they aren't renderer on screen. And the size isn't correctly applied to the ListView cell.

Screen Shot 2022-07-05 at 20 13 01

public ExpandDirection Direction { get; }

/// <summary>
/// Event occurred when IsExpanded changed.
Copy link
Member

Choose a reason for hiding this comment

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

This is not an event, can we change the term? Maybe method? Let's remember that we shouldn't influence the implementor in any way

}

Header.Clickable = true;
Header.SetOnClickListener(new HeaderClickEventListener(this));
Copy link
Member

Choose a reason for hiding this comment

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

So this one is tricky. Because if we use the Listener and the dev wants to customize it then he will lose all our implementation and will have to copy and paste our HeaderClickEventListener, since it's internal, is it what we want?

On the other hand, we can use the Click event to implement our logic, that way the dev can add his on delegate and keep our implementation as well.


partial void Draw()
{
if (Header is null || Content is null)
Copy link
Member

Choose a reason for hiding this comment

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

I see that we need to set the Header and the Content in order to use the Expander, but this is not very clear. Should add a log message/throw an exception telling the dev that he should provide both views?

I would say that could be a good idea to provide a default Header, maybe a BoxView? (If that isn't too hard)


partial void Draw()
{
if (Header is null || Content is null)
Copy link
Member

Choose a reason for hiding this comment

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

I see that we need to set the Header and the Content in order to use the Expander, but this is not very clear. Should add a log message/throw an exception telling the dev that he should provide both views?

I would say that could be a good idea to provide a default Header, maybe a BoxView? (If that isn't too hard)

}

var expanderGesture = new UITapGestureRecognizer();
expanderGesture.AddTarget(() => {
Copy link
Member

Choose a reason for hiding this comment

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

Just a small suggestion (:

Suggested change
expanderGesture.AddTarget(() => {
expanderGesture.AddTarget(() =>
{

Comment on lines 120 to 126
#if WINDOWS
VirtualView.IsExpanded = false;
VirtualView.ExpandedChanged(false);
#else
VirtualView.IsExpanded = !e.IsCollapsed;
VirtualView.ExpandedChanged(!e.IsCollapsed);
#endif
Copy link
Member

Choose a reason for hiding this comment

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

Can we merge those? They have the same names for properties and method. And !e.IsCollapsed should be false for Windows, or not?

/// <summary>
/// Event invoked when IsExpanded changed
/// </summary>
public event EventHandler<ExpanderCollapsedEventArgs> Collapsed
Copy link
Member

Choose a reason for hiding this comment

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

We shouldn't use event handlers here. Core shouldn't force any pattern. The best solution is to call the IExpander.ExpandedChanged method here.

If we've any Event Handler exposed (public) in another control we should fix it.

/// <summary>
/// Extension methods to support <see cref="IExpander"/>
/// </summary>
public static partial class MauiExpanderExtensions
Copy link
Member

Choose a reason for hiding this comment

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

We don't need the partial here

Suggested change
public static partial class MauiExpanderExtensions
public static class MauiExpanderExtensions

/// </summary>
public static void SetIsExpanded(this MauiExpander mauiExpander, bool isExpanded)
{
if (mauiExpander.IsExpanded != isExpanded)
Copy link
Member

Choose a reason for hiding this comment

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

Do we need this check? This check should be in the IsExpanded.Setter, that way will check for any type of value change.

@pictos
Copy link
Member

pictos commented Jul 6, 2022

Windows

  1. On Windows, when I resize the App window the Expander stop to works on CollectionView, as you can see in the picture below Bradon's card should be expanded (arrow down) but isn't. I got the notification and everything, but the card doesn't expand.

image

  1. On the Baboons page, there's odd behavior, when I expand it changes its position and horizontal size, not sure if that's automatically calculated, but that could break some layouts out there. See the video below.
expander.mp4

Android

  1. On the Baboon page the content doesn't respect the screen size

image

  1. Is hard to trigger the expander on mobile looks like there's a delay between the time that I pressed the header and the animation to collapse/expand starts.

  2. Didn't renderer in ListView and CollectionView

image

@VladislavAntonyuk
Copy link
Collaborator Author

VladislavAntonyuk commented Jul 9, 2022

Thank you for detailed review @pictos.
I will try to fix all layout issues.
As for iOS, this may be related to what we discussed: dotnet/maui#3643

Windows uses native WinUI control, I didn't create custom MauiExpander.Windows. So it's a default behavior. There is a property to use all available horizontal space. I can set it to true by default

@pictos
Copy link
Member

pictos commented Jul 9, 2022

@VladislavAntonyuk for ListView maybe you can try this. I believe that the dev will need to perform some properties on the ListView but you can call the Cell.ForceUpdateSize method.

@VladislavAntonyuk
Copy link
Collaborator Author

@VladislavAntonyuk for ListView maybe you can try this. I believe that the dev will need to perform some properties on the ListView but you can call the Cell.ForceUpdateSize method.

Is it for sample? I believe it is not correct to call this method inside Expander. It's not its responsibility

@pictos
Copy link
Member

pictos commented Jul 9, 2022

@VladislavAntonyuk for ListView maybe you can try this. I believe that the dev will need to perform some properties on the ListView but you can call the Cell.ForceUpdateSize method.

Is it for sample? I believe it is not correct to call this method inside Expander. It's not its responsibility

I thought to call that inside the expander, if the parent is a ListView. So the expander will communicate to the ListView that it needs to resize the cell.

Add samples

Fix BindingContext is null


Android Expander


iOS Configure Header


Do not arrange content on expanded change


More samples, fix Android


InvalidateMeasure, add animation


Animation Android. fix WIndows build


Update sample


Fix PR comments


Fix Apple animation


Fix pipeline


Expander tests


Summary
@TheCodeTraveler TheCodeTraveler added pending documentation This feature requires documentation do not merge Do not merge this PR labels Jul 15, 2022
@TheCodeTraveler
Copy link
Collaborator

Just adding the do-not-merge and pending documentation tags so that we don't forget to update the docs!

@VladislavAntonyuk
Copy link
Collaborator Author

@pictos unfortunately Cell.ForceUpdateSize doesn't work.
Android:
I cannot reproduce the issue with rendering inside ListView/CollectionView:
image
Fixed layout in C# Sample:
image

Windows:
CollectionView incorrectly calculates the size of the cell:
image

and
image
As you can see ListView correctly displays content. On CollectionView the first cell renderers correctly. The second cell is opened, but there is no content.

@VladislavAntonyuk
Copy link
Collaborator Author

@pictos I've just updated the sample and copied/pasted the code from XCT expander to compare the behavior.
On Android I see the same results for both implementations.
On Windows, the main question here, is which one do we want to use?

@TheCodeTraveler
Copy link
Collaborator

/dotnet format

@VladislavAntonyuk
Copy link
Collaborator Author

/dotnet format

hope it won't delete the dotnet world

@jmbowman1107
Copy link

When will this be merged?

@TheCodeTraveler TheCodeTraveler added the hacktoberfest-accepted A PR that has been approved during Hacktoberfest label Nov 1, 2022
@TheCodeTraveler
Copy link
Collaborator

Hey Vlad! I made a couple tweaks to Expander to simplify how it works and to reduce memory usage.

  • In Constructor, initialize Grid with 2 RowDefinitions:
    public Expander()
    {
      // ...
      base.Content = new Grid
      {
          RowDefinitions =
          {
      	    new RowDefinition(GridLength.Auto),
      	    new RowDefinition(GridLength.Auto)
          }
      };
    }
  • Bind Content.IsVisible to IsExpanded
    • Ensures Expander's Content is visible when expanded
    • Ensures Expander's Content is not visible when not expanded
    Content.SetBinding(IsVisibleProperty, new Binding(nameof(Expander.IsExpanded), source: this));
  • Set Rows When Direction changes:
    switch (expandDirection)
    {
        case ExpandDirection.Down:
      	  ContentGrid.SetRow(Header, 0);
      	  ContentGrid.SetRow(Content, 1);
      	  break;
    
        case ExpandDirection.Up:
      	  ContentGrid.SetRow(Header, 1);
      	  ContentGrid.SetRow(Content, 0);
      	  break;
    
        default:
      	  throw new NotSupportedException($"{nameof(ExpandDirection)} {expandDirection} is not yet supported");
    }

Copy link
Collaborator

@TheCodeTraveler TheCodeTraveler left a comment

Choose a reason for hiding this comment

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

Hey Vlad!

ListView support isn't working properly on iOS.

I confirmed that it is working on Android.

Simulator.Screen.Recording.-.iPhone.14.-.2022-11-06.at.12.27.25.mp4

@TheCodeTraveler TheCodeTraveler removed the do not merge Do not merge this PR label Nov 7, 2022
@TheCodeTraveler TheCodeTraveler added this to the v1.4.0 milestone Nov 7, 2022
@TheCodeTraveler
Copy link
Collaborator

TheCodeTraveler commented Nov 8, 2022

@VladislavAntonyuk Since ListView is (basically) deprecated in favor of CollectionView, let's move forward with the following tasks so that we can merge this PR to ensure we get Expander into v1.4.0:

  • Open Bug Issue noting that Expander does not support ListView
  • Remove ListView support from Expander
    • In ForceUpdateLayoutSizeForItemsView(), replace code in the if(element is ListView listView) block with throw new NotSupportedException($"{nameof(Expander)} is not yet supported on ListView");
  • Open Docs PR for Expander
    • Add warning about not supporting ListView

Once we've finished these, I'm happy to Approve + Merge this PR 🙌

Comment on lines 218 to 223
if (element is ListView listView)
{
foreach (var child in listView.AllChildren.OfType<Cell>())
{
child.ForceUpdateSize();
}
Copy link
Collaborator

@TheCodeTraveler TheCodeTraveler Nov 8, 2022

Choose a reason for hiding this comment

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

Here's my recommendation to remove ListView support from this release of Expander

Suggested change
if (element is ListView listView)
{
foreach (var child in listView.AllChildren.OfType<Cell>())
{
child.ForceUpdateSize();
}
if (element is ListView listView)
{
throw new NotSupportedException($"{nameof(Expander)} is not yet supported inside {nameof(ListView)}");

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I suggest keeping it, because ListView works much better on WinUI.

@TheCodeTraveler TheCodeTraveler merged commit 1ea488c into main Nov 8, 2022
@TheCodeTraveler TheCodeTraveler deleted the Expander branch November 8, 2022 21:54
@github-actions github-actions bot locked and limited conversation to collaborators Nov 22, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
hacktoberfest-accepted A PR that has been approved during Hacktoberfest pending documentation This feature requires documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Proposal] Expander
6 participants