Expander not working properly in iOS if wrapped inside ScrollView

Hi, I'm trying to use the SFExpander control in my project in one page. But because that page contains many controls I have to use ScrollView control to wrap all other controls. 

When I'm adding SFExpander to page its not working properly. The scrollview's height is not getting increased when expanding the SFExpander in iOS. I have to set the height of scrollview manually than it works, which is not proper way, it should increase automatically based on the content. 


I have attached screen recording and sample code for your reference. 

# Steps to reproduce the bug

  1. Open the sample app project 
  2. Run the app in iOS simulator 
  3. Go to the Additional Info tab 
  4. Click on Expander header and notice the bug.
  5. Set height of scrollview to 100 and check the Expander control again, it will work. 

This happens only in iOS. 

Do we have any work around for this?



Attachment: code_and_recordings_91da20aa.zip


7 Replies

JR Jayashree Ravishankar Syncfusion Team July 9, 2024 01:35 PM UTC

Hi Divyesh Bhatt


We have checked the reported issue. When you try to expand the expander item, the height of the expander is updated properly, but the scrollview height is not updated because the layout calls are missing for the scrollview when the expander item is expanded.

To address this, we invoke InvalidateMeasure() for the ScrollView when the SfExpander height changes.


Please refer to the following code snippet:


<syncfusion:SfExpander

    AnimationDuration="500"

    IsExpanded="False"

    HeaderBackground="WhiteSmoke"  PropertyChanged="SfExpander_PropertyChanged">

</syncfusion:SfExpander>

 

 private void SfExpander_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)

 {

     if(e.PropertyName == "Height")

     {

         (scrollview as IView).InvalidateMeasure();

     }

 }


We have attached a video for your reference. Please let us know if you have any other queries.



Regards,

jayashree


Attachment: iosexpander_331ffd2f.zip


DB Divyesh Bhatt July 9, 2024 05:33 PM UTC

Yes, but when we Collapse the SFExpander the height remains unchanged, check the attached video. How to handle this?


Attachment: SFExpander_with_property_changed_event_b19121ad.zip


JR Jayashree Ravishankar Syncfusion Team July 10, 2024 09:25 AM UTC

Hi Divyesh Bhatt


Sorry for the inconvenience. In the previous update, we only checked with SfExpander inside the ScrollView as you disabled the toolkit expander in your sample.

After we added the toolkit expander, the ScrollView height was not updated when the SfExpander got collapsed since the PropertyChanged event for "Height" is not triggered for SfExpander when it gets collapsed.


To address this, we invoked the PropertyChanged event for the Grid inside the expander content and called InvalidateMeasure() for the ScrollView when the Grid height changes.


Please refer to the following code snippet:

<syncfusion:SfExpander.Content>

    <Grid Padding="18,8,18,18"  RowSpacing="6" PropertyChanged="Grid_PropertyChanged">

------------------------------------------

------------------------------------------

        </Grid>

</syncfusion:SfExpander.Content>

 

 private void Grid_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)

 {

 

     if (e.PropertyName == "Height")

     {

         (scrollview as IView).InvalidateMeasure();

     }

 }

 


We have attached a video for your reference. Please let us know if you have any other queries.


Attachment: expanderios_8a107089.zip


DB Divyesh Bhatt July 11, 2024 05:51 AM UTC

OK this solution will work only when we the Expander control and ScrollViewControl in same page, but what in case where we have ExpanderControl in the ContentView and adding it dynamically in to the PageWhere we have the ScrollView. So will not directly able to access that scrollview, so how to handle that? Is there any proper solution for this?



JR Jayashree Ravishankar Syncfusion Team July 12, 2024 10:31 AM UTC

Hi Divyesh Bhatt,


As we mentioned in a previous update, the ScrollView size is not updated due to lack of layout calls when SfExpander's size is changed. Therefore, we need to refresh the ScrollView in required place.

Since you couldn't access the ScrollView in another ContentView (which contains the expander), you can get the ScrollView by accessing the expander's parent.

 

Please refer to the attached code snippet:

private void Grid_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)

{

       if (e.PropertyName == "Height")

       {

           var expanderParent = expander.Parent;

           while(expanderParent is not ScrollView)

           {

               expanderParent = expanderParent.Parent;

           }

           (expanderParent as IView)!.InvalidateMeasure();

       }

}

 

 

Please let us know if you have any other queries.



DB Divyesh Bhatt July 13, 2024 06:22 PM UTC

# ParentContentView.xaml

<Grid Margin="4" RowDefinitions="*" Padding="10,0">


    <listview:SfListView

        x:Name="_contentTarget"

        VerticalOptions="Fill"

        HorizontalOptions="Fill"

        Padding="5,0"

        ItemsSource="{Binding TargetItems}"

        ItemTemplate="{StaticResource CustomFieldTemplateSelector}"

        SelectionBackground="Transparent"

        AutoFitMode="Height" />


</Grid>


# ChildContentView.xaml

<VerticalStackLayout PropertyChanged="VerticalStackLayout_PropertyChanged">

<expander:SfExpander x:Name="_expander" AutomationId="_tabItem">

    <expander:SfExpander.Header>

        <Grid>

            <Label

                Text="{Binding Path=Label}"

                Style="{StaticResource Key=TabItemLabelStyle}"/>

        </Grid>

    </expander:SfExpander.Header>


    <expander:SfExpander.Content>

         <listview:SfListView

            x:Name="childControlsList"

            VerticalOptions="Fill"

            HorizontalOptions="Fill"

            Padding="15,0"

            ItemsSource="{Binding TargetItems}"

            ItemTemplate="{StaticResource CustomFieldTemplateSelector}"

            SelectionBackground="Transparent"

            AutoFitMode="Height"/>

    </expander:SfExpander.Content>

</expander:SfExpander>

</VerticalStackLayout>


This is my control structure. As I'm having other isseus with scrollview I have used SfListView control. SfExpander that is in child also have the SFListView.


I have used last logic you have provided in ChildContentView like this:


void VerticalStackLayout_PropertyChanged(System.Object sender, System.ComponentModel.PropertyChangedEventArgs e)

{

    if (e.PropertyName == "Height")

    {

        var expanderParent = _expander.Parent;

        while (expanderParent is not SfListView)

        {

            expanderParent = expanderParent.Parent;

        }


      (childControlsList as IView)!.InvalidateMeasure();

    }

}


But its still not working, check the attached screen recording. And let me know is there any solution available for this?


Attachment: Screen_Recording_20240713_290f1b4b.zip


JR Jayashree Ravishankar Syncfusion Team July 15, 2024 12:09 PM UTC

Hi Divyesh Bhatt,


When changing the height of SfListView content dynamically, you need to set "AutoFitMode" to DynamicHeight for SfListView. If the issue persists, it might be due to missing layout calls in the parent when the content or size of the child element changes. In the MAUI framework, the parent element does not receive notifications about its child element properties (such as size, font, text, etc.), and this issue has already been logged in the framework.


To address this, you can try refreshing the SfListView with every expansion and collapse to update the height of each item at runtime. Since notifications are not received when the content changes, using RefreshView can help layout the items again after expansion and collapse. Below is a code snippet for your reference.


Code snippet

 

<expander:SfExpander x:Name="_expander" Expanded="expander_Expanded" Collapsed=" expander_Collapsed" AutomationId="_tabItem">

    <expander:SfExpander.Content>

         <listview:SfListView

            x:Name="childControlsList"

            AutoFitMode="DynamicHeight"/>

    </expander:SfExpander.Content>

</expander:SfExpander>

 

 

private void expander_Expanded(object sender, Syncfusion.Maui.Expander.ExpandedAndCollapsedEventArgs e)

{

        var expanderParent = _expander.Parent;

        while (expanderParent is not SfListView)

        {

            expanderParent = expanderParent.Parent;

        }

      (expanderParent as SfListView)?.RefreshView();

 

}

private void expander_Collapsed(object sender, Syncfusion.Maui.Expander.ExpandedAndCollapsedEventArgs e)

{

        var expanderParent = _expander.Parent;

        while (expanderParent is not SfListView)

        {

            expanderParent = expanderParent.Parent;

        }

      (expanderParent as SfListView)?.RefreshView();

}


You can also find the reported issue in the framework on GitHub via the following link:
Github link - 
https://github.com/dotnet/maui/issues/14741


If you are still facing any issues, could you please share a issue reproducing sample? This would be really helpful for us to find a solution as soon as possible.


Loader.
Up arrow icon