Open Domik234 opened 5 months ago
Hi I'm an AI powered bot that finds similar issues based off the issue title.
Please view the issues below to see if they solve your problem, and if the issue describes your problem please consider closing this one and thumbs upping the other issue to help us prioritize it. Thank you!
Note: You can give me feedback by thumbs upping or thumbs downing this comment.
This issue has been verified using Visual Studio 17.11.0 Preview 2.1(8.0.61 & 8.0.60). Can repro on iOS platform.
CollectionViewHandler.GetDesiredSize (or it's parent's GetDesiredSize) forgets to add insets from Controller.CollectionView.AdjustedContentInset used for Header and Footer to the height of CollectionView!
public class XCollectionViewHandler : CollectionViewHandler
{
public XCollectionViewHandler() : base(/* vlastní mapper? */) { }
#if IOS
public override Size GetDesiredSize(double widthConstraint, double heightConstraint)
{
var size = base.GetDesiredSize(widthConstraint, heightConstraint);
var insets = Controller.CollectionView.AdjustedContentInset.Top + Controller.CollectionView.AdjustedContentInset.Bottom;
//Console.WriteLine("GetDesiredSize is " + size.ToString() + " and edited is " + newSize.ToString());
return new Size(size.Width, Math.Min(size.Height + insets, heightConstraint));
}
#endif
}
Second problem is that when I set VerticalOptions to something else than Fill - it is calculated also wrong and it can go to space out of it's bounds thanks to:
CollectionView is able to ignore layouted bounds.
Problem is somewhere in the method of LayoutExtensions.ComputeFrame(IView, Rect) called from VisualElement.ArrangeOverride.
It looks like it doesn't care about really available space and it sets whatever it wants but more propably there will be error in the method LayoutExtensions.AlignVertical(IView, Rect, Thickness)
with equation or simply forgotten check if it is still in bounds.
//This is broken
protected virtual Size ArrangeOverride(Rect bounds)
{
Frame = this.ComputeFrame(bounds);
Handler?.PlatformArrange(Frame);
return Frame.Size;
}
When the parameter bounds
's Y = 48 -> ComputeFrame is able to set the the Frame Y value like 17. So the view's Frame
is able to begin in another view!
This can be fixed easily by this:
public class XCollectionView : CollectionView
{
protected override Size ArrangeOverride(Rect bounds)
{
//base.ArrangeOverride(bounds); - Base doesn't work. Let's take it's content out and edit it.
//1. Save the computedFrame that app wants to use.
var computedFrame = this.ComputeFrame(bounds);
//2. Set Y to be the maximum value of original bounds' Y and computerFrame's Y - that means it cannot be higher than it is allowed.
//3. Set the Height of Frame to the minimum value of original bounds's Y + Height and computerFrame's Height - reverse process of the maximum for Y
//Steps 2 and 3 limit the Frame to be exactly in the available bounds for the layout that calculated it.
Frame = new Rect(computedFrame.Left, Math.Max(bounds.Top, computedFrame.Top), computedFrame.Width, Math.Min(bounds.Height, computedFrame.Height));
Handler?.PlatformArrange(Frame);
return Frame.Size;
}
}
I've already tested this for all cases that I use with all combinations of VerticalOptions settings. In this case I've completely ignored horizontal orientation possibility but by the principle I may be solved the same logic.
Ideally solving this directly in the ComputeFrame could solve most of this problems because this won't be the only case where this happens and breaks UI drawing but that will need more testing.
using Microsoft.Maui.Controls.Handlers.Items;
using Microsoft.Maui.Layouts;
namespace MauiApp1.Components
{
public class XCollectionView : CollectionView
{
protected override Size ArrangeOverride(Rect bounds)
{
var computedFrame = this.ComputeFrame(bounds);
Frame = new Rect(computedFrame.Left, Math.Max(bounds.Top, computedFrame.Top), computedFrame.Width, Math.Min(bounds.Height, computedFrame.Height));
Handler?.PlatformArrange(Frame);
return Frame.Size;
}
}
public class XCollectionViewHandler : CollectionViewHandler
{
public XCollectionViewHandler() : base() { }
#if IOS
public override Size GetDesiredSize(double widthConstraint, double heightConstraint)
{
var size = base.GetDesiredSize(widthConstraint, heightConstraint);
var insets = Controller.CollectionView.AdjustedContentInset.Top + Controller.CollectionView.AdjustedContentInset.Bottom;
return new Size(size.Width, Math.Min(size.Height + insets, heightConstraint));
}
#endif
}
}
Don't forget to register the handler!
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
})
//Don't forget to add this!!! - Start
.ConfigureMauiHandlers(handlers =>
{
handlers.AddHandler<XCollectionView, XCollectionViewHandler>();
});
//Don't forget to add this!!! - End
#if DEBUG
builder.Logging.AddDebug();
#endif
return builder.Build();
}
}
Description
CollectionView without Header and Footer is calculated correctly.
When Header or Footer is added - measurement of these views is not included to size of CollectionView.
VerticalOptions: Fill + Grid.Row = Star
![IMG_0188](https://github.com/dotnet/maui/assets/9479585/627b8991-1f26-41ea-aa6a-defe9a190ec6)VerticalOptions: End - Scrolled to Top + Grid.Row = Star
![IMG_0189](https://github.com/dotnet/maui/assets/9479585/e91e58ef-2a93-4d25-89ef-bc75fe09dac5)VerticalOptions: End - Scrolled to Bottom + Grid.Row = Star
![IMG_0190](https://github.com/dotnet/maui/assets/9479585/764bf29e-4221-4c0b-8a73-879a75be0de8)When you set RowDefinitions to auto, auto - it's broken the same way (for VerticalOptions: Fill) as when you set VerticalOptions to Start, Center or End + having Header or Footer.
VerticalOptions: Fill + Grid.Row = Auto
![IMG_0191](https://github.com/dotnet/maui/assets/9479585/6e50288b-4689-49dd-9a2e-5b40095421df)Prepared repo has buttons to switch situations as needed for enabling Header/Footer, switching VerticalOptions for CV and adding new items and removing last item.
Red = Control Bar Yellow = CV Header Orange = CV Footer
Bonus Situation:
CollectionView with VO set not to Fill breaks Grid's measurement when items use CV's available space
![IMG_0192](https://github.com/dotnet/maui/assets/9479585/793bd780-ff2e-4ee7-a134-7a6e8f49879f)Not tested: Horizontal CV
Steps to Reproduce
Run the repo.
Link to public reproduction project repository
https://github.com/Domik234/Issue-MauiCollectionViewVerticalOptionsEndBugs
Version with bug
8.0.61 SR6.1
Is this a regression from previous behavior?
Yes, this used to work in Xamarin.Forms
Last version that worked well
Unknown/Other
Affected platforms
iOS
Affected platform versions
No response
Did you find any workaround?
-
Relevant log output