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

CollectionView Items display issue when Header is resized on iOS #12429

Closed
tranb3r opened this issue Jan 5, 2023 · 18 comments · May be fixed by #21812
Closed

CollectionView Items display issue when Header is resized on iOS #12429

tranb3r opened this issue Jan 5, 2023 · 18 comments · May be fixed by #21812
Labels
area-controls-collectionview CollectionView, CarouselView, IndicatorView delighter-sc p/2 Work that is important, but is currently not scheduled for release platform/iOS 🍎 s/triaged Issue has been reviewed s/verified Verified / Reproducible Issue ready for Engineering Triage t/bug Something isn't working
Milestone

Comments

@tranb3r
Copy link

tranb3r commented Jan 5, 2023

Description

When the size of a CollectionView Header increases, it's displayed on top of Items, on iOS.
No issue on Android.

In this example, when clicking on the Add button, a row is added to the Header of the CollectionView (above the line), in order to increase the size of the Header. On Android, the Items (below the row) move down accordingly. On iOS, the Header size increases and is displayed on top of Items.

Steps to Reproduce

  1. Create a Maui app
  2. Add a CollectionView with HeaderTemplate
  3. Increase size of Header and observe what happens

Link to public reproduction project repository

https://github.com/tranb3r/Issues/tree/main/MauiAppCollectionViewHeaderResize

Version with bug

7.0 (current)

Last version that worked well

Unknown/Other

Affected platforms

iOS

Affected platform versions

iOS 16.1

Did you find any workaround?

no

Relevant log output

No response

@tranb3r tranb3r added the t/bug Something isn't working label Jan 5, 2023
@rachelkang rachelkang added platform/iOS 🍎 area-controls-collectionview CollectionView, CarouselView, IndicatorView labels Jan 5, 2023
@rachelkang rachelkang added this to the Backlog milestone Jan 5, 2023
@ghost
Copy link

ghost commented Jan 5, 2023

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

@eth-ellis
Copy link
Contributor

I am experiencing this issue also.

To add it is also occurring for the CollectionView footer as can be seen below:

Android (Working) -
Android

iOS (Not working) -
iOS

Reproduction link: https://github.com/eth-ellis/Issue-Repro/tree/main/MauiAppCollectionViewFooterResize

@tranb3r Did you end up finding a workaround since raising?

@tranb3r
Copy link
Author

tranb3r commented Feb 20, 2023

@eth-ellis
Yes, I do have a workaround: invalidate the header to force a redraw.

        if (CollectionViewRef.Header is VisualElement headerVisualElement)
        {
            headerVisualElement.InvalidateMeasureNonVirtual(InvalidationTrigger.Undefined);
        }

I've updated my sample project with a "fix" button.

@jinxinjuan jinxinjuan added s/triaged Issue has been reviewed s/verified Verified / Reproducible Issue ready for Engineering Triage labels Jun 8, 2023
@jinxinjuan
Copy link

Verified this issue with Visual Studio Enterprise 17.7.0 Preview 1.0. Can repro on iOS platform with sample project. MauiAppCollectionViewHeaderResize
But have a workaround via clicking "fix" button,

@metalium84
Copy link

metalium84 commented Dec 10, 2023

I'm facing the same issue with .NET 8 and iOS 17.0. Any updates on this? CollectionViews with headers seems like quite a crucial thing to work properly!

@samhouts samhouts added the p/1 Work that is important, and has been scheduled for release in this or an upcoming sprint label Dec 19, 2023
@unamed000
Copy link

Confirmed still an issue in latest .NET 8. CollectionView is a fundamental view which is very important and it should work in these simple cases....

kubaflo added a commit to kubaflo/maui that referenced this issue Apr 13, 2024
kubaflo added a commit to kubaflo/maui that referenced this issue Apr 13, 2024
kubaflo added a commit to kubaflo/maui that referenced this issue Apr 13, 2024
kubaflo added a commit to kubaflo/maui that referenced this issue Apr 13, 2024
kubaflo added a commit to kubaflo/maui that referenced this issue Apr 15, 2024
@Pughgramming
Copy link

It appears this issue is still present. I see there was a PR for a potential fix two weeks ago, is there any update or workaround at this time?

@bengavin
Copy link

bengavin commented Jun 5, 2024

^ bump this again - we could use this fix in the next SR please :) cc: @kubaflo @PureWeen

@WanftMoon
Copy link

Bump, using workaround, but this def need fix.

@thisisthekap
Copy link
Contributor

As the workaround is not working for us, this issue forced us to use bindable layouts, which induced a performance degradation.

Therefore, this issue has high priority for us.

@PureWeen PureWeen added p/2 Work that is important, but is currently not scheduled for release and removed p/1 Work that is important, and has been scheduled for release in this or an upcoming sprint labels Jul 2, 2024
kubaflo added a commit to kubaflo/maui that referenced this issue Jul 19, 2024
kubaflo added a commit to kubaflo/maui that referenced this issue Jul 19, 2024
@michiel-nwa
Copy link

michiel-nwa commented Aug 5, 2024

@thisisthekap could you elaborate a bit on how you were able to get it to work? Not sure if I understand what you did.

Still looking into if/how the workaround can somehow be used when using a HeaderTemplate.

@thisisthekap
Copy link
Contributor

@michiel-nwa We replaced CollectionView with e.g. VerticalStackLayout including a DataTemplate for the items.

@michiel-nwa
Copy link

michiel-nwa commented Aug 5, 2024

@thisisthekap Thanks, that is not what I was looking for.

I ended up registering for BindingContextChanged and then PropertyChanged changes on the BindingContext in the HeaderTemplate. And then calling the invalidation from the workaround on every change. Seems to work for now.

@filyXplor
Copy link

@michiel-nwa I haven't been able to fix it yet, could you give an example of what you did?

@jaysidri
Copy link

jaysidri commented Aug 6, 2024

@michiel-nwa How did you invalidate the layout and force it to redraw? A workaround described here: #12429 (comment) did this but the InvalidationTrigger enum is now internal.

headerVisualElement.InvalidateMeasureNonVirtual(InvalidationTrigger.Undefined);

@michiel-nwa
Copy link

@filyXplor @jaysidri I basically applied the given workaround in the sample code to my situation:

myList.HeaderTemplate = new DataTemplate(() => {
   var header = new Grid();
   // Some layout with bindings etc.
   
    System.ComponentModel.PropertyChangedEventHandler invalidate = (object sender, System.ComponentModel.PropertyChangedEventArgs e) => {
        if(e.PropertyName==nameof(MyModel.RelevantProperty)){
            header.InvalidateMeasureNonVirtual(Microsoft.Maui.Controls.Internals.InvalidationTrigger.Undefined);
        }
    }				
    
    header.BindingContextChanged += (a1, a2) => {
          var bc = header.BindingContext as INotifyPropertyChanged;
          if (bc != null)
          {
               bc.PropertyChanged -= invalidate;
	       bc.PropertyChanged += invalidate;
          }
          header.InvalidateMeasureNonVirtual(Microsoft.Maui.Controls.Internals.InvalidationTrigger.Undefined);
    };
    return header;
});

Far from ideal, but at least lets me continue until the issue is fixed.

@rudyspano
Copy link

Our alternative "generic" solution that works in all our cases based on Handlers

public class LayoutHandler : Microsoft.Maui.Handlers.LayoutHandler
   {
       protected override LayoutView CreatePlatformView() => new LayoutViewExtended(VirtualView);

       private class LayoutViewExtended : LayoutView
       {
           private readonly ILayout _virtualView;
           private Size _currentFixedSize;

           public LayoutViewExtended(ILayout virtualView)
           {
               _virtualView = virtualView;
           }

           public override void LayoutSubviews()
           {
               base.LayoutSubviews();

               FixCollectionViewHeaderFooter();
           }

           /// <summary>
           /// Hack: Fix current issue with Headers and Footers that change in terms of size
           /// <see cref="https://github.com/dotnet/maui/issues/17885"/>
           /// </summary>
           private void FixCollectionViewHeaderFooter()
           {
               if (_virtualView.Parent is not CollectionView collectionView
                   || collectionView.Header != _virtualView && collectionView.Footer != _virtualView)
               {
                   return;
               }

               var bounds = AdjustForSafeArea(Bounds).ToRectangle();

               var widthConstraint = bounds.Width;
               var heightConstraint = bounds.Height;

               var size = CrossPlatformLayout.CrossPlatformMeasure(widthConstraint, double.PositiveInfinity);

               if (size.Height <= 0 || size.Width <= 0
                   || _currentFixedSize == size)
               {
                   return;
               }

               if (collectionView.Width > 0)
               {
                   widthConstraint = Math.Min(collectionView.Width, widthConstraint);
               }

               if (CrossPlatformLayout is VisualElement element
                   && (Math.Abs(heightConstraint - size.Height) > 0.1 || Math.Abs(widthConstraint - size.Width) > 0.1))
               {
                   element.InvalidateMeasureNonVirtual(InvalidationTrigger.Undefined);
                   _currentFixedSize = size;
               }
           }
       }
   }

@maonaoda
Copy link
Contributor

maonaoda commented Aug 6, 2024

#17885
my workaround is same as this.

The new CollectionViewHandler2 is recently available on net9, maybe could fix this.( '▿ ' )

Our alternative "generic" solution that works in all our cases based on Handlers

public class LayoutHandler : Microsoft.Maui.Handlers.LayoutHandler
   {
       protected override LayoutView CreatePlatformView() => new LayoutViewExtended(VirtualView);

       private class LayoutViewExtended : LayoutView
       {
           private readonly ILayout _virtualView;
           private Size _currentFixedSize;

           public LayoutViewExtended(ILayout virtualView)
           {
               _virtualView = virtualView;
           }

           public override void LayoutSubviews()
           {
               base.LayoutSubviews();

               FixCollectionViewHeaderFooter();
           }

           /// <summary>
           /// Hack: Fix current issue with Headers and Footers that change in terms of size
           /// <see cref="https://github.com/dotnet/maui/issues/17885"/>
           /// </summary>
           private void FixCollectionViewHeaderFooter()
           {
               if (_virtualView.Parent is not CollectionView collectionView
                   || collectionView.Header != _virtualView && collectionView.Footer != _virtualView)
               {
                   return;
               }

               var bounds = AdjustForSafeArea(Bounds).ToRectangle();

               var widthConstraint = bounds.Width;
               var heightConstraint = bounds.Height;

               var size = CrossPlatformLayout.CrossPlatformMeasure(widthConstraint, double.PositiveInfinity);

               if (size.Height <= 0 || size.Width <= 0
                   || _currentFixedSize == size)
               {
                   return;
               }

               if (collectionView.Width > 0)
               {
                   widthConstraint = Math.Min(collectionView.Width, widthConstraint);
               }

               if (CrossPlatformLayout is VisualElement element
                   && (Math.Abs(heightConstraint - size.Height) > 0.1 || Math.Abs(widthConstraint - size.Width) > 0.1))
               {
                   element.InvalidateMeasureNonVirtual(InvalidationTrigger.Undefined);
                   _currentFixedSize = size;
               }
           }
       }
   }

github-actions bot pushed a commit to kubaflo/maui that referenced this issue Oct 10, 2024
github-actions bot pushed a commit to kubaflo/maui that referenced this issue Oct 10, 2024
rmarinho pushed a commit that referenced this issue Oct 10, 2024
kubaflo added a commit to kubaflo/maui that referenced this issue Oct 11, 2024
rmarinho pushed a commit that referenced this issue Oct 18, 2024
rmarinho pushed a commit that referenced this issue Oct 21, 2024
kubaflo added a commit to kubaflo/maui that referenced this issue Oct 31, 2024
@github-actions github-actions bot locked and limited conversation to collaborators Nov 23, 2024
rmarinho pushed a commit to kubaflo/maui that referenced this issue Dec 16, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-controls-collectionview CollectionView, CarouselView, IndicatorView delighter-sc p/2 Work that is important, but is currently not scheduled for release platform/iOS 🍎 s/triaged Issue has been reviewed s/verified Verified / Reproducible Issue ready for Engineering Triage t/bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.