Migrated from https://bugzilla.xamarin.com/show_bug.cgi?id=44525.
Issue is resolved in RecycleElement mode, but not in RetainElement mode and other scenarios.
Test case is in Control Gallery, but it needs to be updated with other CachingStrategies and new info in Bugzilla ticket.
Preserve
attribute1.) There is no need for a custom cell at all as it doesn't do anything
2.) Bug: If set to RetainElement the new text is shown, but the image is not resized at all until you scroll down and scroll back up it is resized correct.
3.) Bug: if set to it to RecycleElement then it doesn't resize at first and you can't see the rest of the text, but as soon as you scroll down and up it is resized correct.
If a control of the Item inside the ListView is hidden, Android will automatically adjust the height of the UI Item, but iOS will not automatically adjust the height
Does anyone have a work-around for this issue on iOS? I'm hitting this now also. We have some labels which we should when the item is selected so need the view cell to automatically expand when they are shown.
Just hit this on 3.1.0.697729 and it is really apparent on the 5s and SE . I have a label that wraps up to three lines in a listview. When I first land on the screen, the first line of text is cut off for almost my entire list of items and a ton of items are crammed into the top of the list (at a rate of 1/2 label height per item, since they're cut off). Once I scroll down, any item that goes off screen will come back on screen with whatever size of row they were replaced with. For instance, if the first item in my list should take three rows of text, it gets cut off halfway through the first line. I then scroll down, and the item that replaces it takes two lines of text. When I scroll back up, the first item has two lines' worth of space, even if it should have three.
I had 2.4.0.282 before (long story) and this was not happening at all. Maybe referencing the logic from that release will help?
Side note: Pull to refresh makes them all look correct.
One more note: This seems to be happening if the data is present before the screen first appears (say, in a multi-tab view). If I delay the data binding until after the screen is visible, this goes away.
Another note related to my last post: Even when I manage to get the screen to look right on first load, changing orientation breaks it again.
More data related to my as-yet-unsuccessful troubleshooting attempts:
Given a listview that has a custom control (no custom renderers) as the data template
AND the custom control's top-level element has a specific HeightRequest
AND HasUnevenRows=true
THEN the listview renders all rows at exactly that HeightRequest, regardless of content.
Given the above, but with MinHeightRequest, the rows are collapsed in on themselves.
Given the above, but with neither MHR or HR, the rows are collapsed in on themselves.
If I set the height of the custom control's top-level Element (in this case a grid) to a specific HeightRequest, then the listview, despite HasUnevenRows=true, will render every single row with that height, regardless of content.
Whereas if I leave that off, or try using MinimumHeightRequest=x, the issue remains.
I also want to add that this is happening for me regardless of mode: RecycleElement, RecycleElementAndDataTemplate, and RetainElement all behave in this way, except with Retain it never resizes anything ever, and the sizes are just terrible.
Any one find the solution of it?
@jassmith @samhouts I'm wondering what your timeframe is for fixing _high impact_ issues. Some of the reported ones go as far back as Dec 2017.
Any time frame to fix this blocking issue ?
I found that if I don't use a custom control resizing works. By that I mean if I take my XAML from within the custom control and move it to the ViewCell in the DataTemplate directly (plus fixing bindings), sizing seems to be fine.
For example, if I have a control that is a grid with stuff in it I can adjust the XAML as below.
Broken
<DataTemplate><ViewCell><alias:control … /></ViewCell></DataTemplate>
Works:
<DataTemplate><ViewCell><Grid>...</Grid></ViewCell></DataTemplate>
Hopefully this workaround saves someone out there some sanity while we wait.
@LucasJordan, my custom control is already inside a ContentView
and yet this bug is occurring in my app.
Honestly, at this point I just cannot believe that we are already in the version 3.x of this framework (with the version 4.0 about to be released) and something as basic as creating a list with uneven rows is still misbehaving and causing issues. Plus, this is a blocking bug labeled as "high impact", but after several months we still have no solution for it.
Sorry for the rant, but this problem is just driving me crazy. I really hope we can get either a solution or a functioning workaround soon.
@LucasJordan, my custom control is already inside a
ContentView
and yet this bug is occurring in my app.Honestly, at this point I just cannot believe that we are already in the version 3.x of this framework (with the version 4.0 about to be released) and something as basic as creating a list with uneven rows is still misbehaving and causing issues. Plus, this is a blocking bug labeled as "high impact", but after several months we still have no solution for it.
Sorry for the rant, but this problem is just driving me crazy. I really hope we can get either a solution or a functioning workaround soon.
It's open source - they don't turn down PRs - if in dire need you can always post a PR. With any open source library comes the understanding that if I really need something either I need to code it myself or wait for a fix. It's why for really complex apps or apps that require UI to just work we code Xamarin Native/Classic and only for smaller apps do we use Forms.
@LucasJordan, my custom control is already inside a
ContentView
and yet this bug is occurring in my app.Honestly, at this point I just cannot believe that we are already in the version 3.x of this framework (with the version 4.0 about to be released) and something as basic as creating a list with uneven rows is still misbehaving and causing issues. Plus, this is a blocking bug labeled as "high impact", but after several months we still have no solution for it.
Sorry for the rant, but this problem is just driving me crazy. I really hope we can get either a solution or a functioning workaround soon.
It's open source - they don't turn down PRs - if in dire need you can always post a PR. With any open source library comes the understanding that if I really need something either I need to code it myself or wait for a fix. It's why for really complex apps or apps that require UI to just work we code Xamarin Native/Classic and only for smaller apps do we use Forms.
Yeah, it looks like choosing Xamarin Forms for a complex app isn't the best idea...
The thing is that, while I understand that this is just an open source library like any other, I still expect it to meet certain standards, mostly because it is officially backed up by Microsoft and because it has been out there for a while, which means that by now it should be fairly stable (at the very least, I would expect the basic functionality of creating lists to work without major issues).
Anyway, sorry again for the rant; let's just focus on discussing only about the original issue to keep the comment section clean.
I managed to implement a workaround that fixed the issue in my case, so I will explain here what I did just in case it is of any help.
Initially, I had a list in which each element was a custom view:
...
<ListView
HasUnevenRows="true"
ItemsSource="{Binding MyItemsSource}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<alias:MyCustomView
Data="{Binding MyData}"/>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
...
And this custom view had some bindings on it:
<ContentView
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyNamespace.MyCustomView"
x:Name="this">
<Label
Text="{Binding Data, Source={x:Reference this}}" />
</ContentView>
public partial class MyCustomView : ContentView
{
public static readonly BindableProperty DataProperty =
BindableProperty.Create(
nameof(Data),
typeof(string),
typeof(MyCustomView),
null);
public string Data
{
get => (string)GetValue(DataProperty);
set => SetValue(DataProperty, value);
}
public MyCustomView()
{
InitializeComponent();
}
}
My initial goal was to measure the height of the view MyCustomView
as soon as it was given a binding context, just so I could set the height of the cell with the measured height of the view. However, I saw that the measurement that I was obtaining inside OnBindingContextChanged()
after calling Measure()
was always wrong.
I did some debugging and I realised that, even though the property Data
had already been set in the view MyCustomView
at the time when I was trying to get the measurement, the text of the label contained within the custom view was still empty, which I understand was happening because the bindings couldn't propagate fast enough to the inner elements. This made me realise that my issue was occurring because Xamarin Forms was measuring the height of my custom view before all its elements were updated, which was causing the measurement to be wrong.
To work around this, I decided to replace all the bindings with assignations, just like this:
<ContentView
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyNamespace.MyCustomView"
x:Name="this">
<!-- No binding here; the value will be set on code -->
<Label
x:Name="MyLabel" />
</ContentView>
public partial class MyCustomView : ContentView
{
public static readonly BindableProperty DataProperty =
BindableProperty.Create(
nameof(Data),
typeof(string),
typeof(MyCustomView),
null,
propertyChanged: OnDataChanged);
public string Data
{
get => (string)GetValue(DataProperty);
set => SetValue(DataProperty, value);
}
public MyCustomView()
{
InitializeComponent();
}
private static void OnDataChanged(BindableObject bindable, object oldvalue, object newvalue)
{
if (bindable is MyCustomView myCustomView)
{
// Setting the text of this element manually instead of using bindings
myCustomView.MyLabel.Text = myCustomView.Data;
}
}
}
And voilà! The list was finally working smoothly and without problems. Of course, this implementation is not ideal, as you have to take care of updating all the elements manually, but it is still better than a list that doesn't display the rows correctly.
TL;DR: I replaced all the bindings of my custom view with manual assignations and the list started working properly.
I've worked around this with cell.ForceUpdateSize()
There's still an issue with updating the cell height when doing changes in the DataTemplate
. I have a button that is only visible when a cell is selected. When I select the cell, the height doesn't change to fit the new contents on iOS. It works perfectly on Android.
Xamarin.Forms version: 3.6.0.220655
Relevant ListView
properties:
HasUnevenRows="True"
CachingStrategy="RecycleElement"
RowHeight="-1"
Screenshot iOS:
Screenshot Android:
As others have mentioned, we have tried cell.ForceUpdateSize()
but this causes the list scroll height to jump around as the cells themselves force a resize. We have a custom HTML renderer inside a cell and this causes the content to be clipped.
@samhouts Is there any movement on this issue getting resolved?
Unfortunately, there is no progress on this issue yet. However, we can confirm that the CollectionView will not suffer from this problem and will not require ForceUpdateSize
!
A work around that has worked well for me is to invert and back the HasUnevenRows. This forces a clean cell update that ForceUpdateSize doesn't have. ForceUpdateSize can cause some controls in a cell to not get set.
Inside a ViewCell:
if (this.Parent is ListView list)
{
list.HasUnevenRows = !list.HasUnevenRows;
list.HasUnevenRows = !list.HasUnevenRows;
}
This fix no longer works, at least with Xamarin.Forms 4.1. Observed that HasUnevenRows just stays false, and never switches back to false. ForceUpdateSize Works on Android, but redraws the whole list on iOS and eventually freezes the whole app.
I'm currently running into this problem :/
Here the results of a small test:
The ListView:
<ListView IsGroupingEnabled="true"
HasUnevenRows="true"
ItemsSource="{Binding BudgetGroupList}"
ItemSelected="Handle_ItemSelected"
ItemTapped="Handle_ItemTapped"
ItemTemplate="{StaticResource BudgetTemplateSelector}"
GroupHeaderTemplate="{StaticResource BudgetTemplateSelector}"
CachingStrategy="RetainElement"
x:Name="listViewBudget"
>
The XAML of the ViewCell – This is the version that doesn't resize correctly:
As you can see it is a ViewCell that holds a Grid with an Autosize row and three columns.
A StackLayout with a Label is put inside the first column. Problem occurs if Text is longer and Word Wrap kicks in
Some Rows are resized correctly, some are not
<?xml version="1.0" encoding="UTF-8"?>
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TIMB.Pages.Budget.ViewCells.TestCell"
BindingContextChanged="Handle_BindingContextChanged"
>
<ViewCell.View>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<StackLayout Grid.Row="0" Grid.Column="0"
Padding="10"
VerticalOptions="CenterAndExpand">
<Label Grid.Row="0" Grid.Column="0"
x:Name="labBezeichnung"
Text="{Binding KategorieBezeichnung, FallbackValue='Bezeichnung die etwas länger ist'}"
FontSize="Large"
/>
</StackLayout>
</Grid>
</ViewCell.View>
</ViewCell>
Now, if i skip the StackLayout and put the Label directly into the Grid row - it works correctly:
<?xml version="1.0" encoding="UTF-8"?>
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TIMB.Pages.Budget.ViewCells.TestCell"
BindingContextChanged="Handle_BindingContextChanged"
>
<ViewCell.View>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<!--<StackLayout Grid.Row="0" Grid.Column="0"
Padding="10"
VerticalOptions="CenterAndExpand">-->
<Label Grid.Row="0" Grid.Column="0"
x:Name="labBezeichnung"
Text="{Binding KategorieBezeichnung, FallbackValue='Bezeichnung die etwas länger ist'}"
FontSize="Large"
/>
<!--</StackLayout>-->
</Grid>
</ViewCell.View>
</ViewCell>
It breaks again if i put some Custom Controls inside the other columns - These controls again are build with a Grid / Frame / StackLayout Combination like:
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TIMB.Controls.EditLabel"
>
<ContentView.Content>
<Grid>
<Frame BackgroundColor="#b3f5b4"
x:Name="theFrame"
Padding="10,0,10,0"
HeightRequest="20"
CornerRadius="15"
HasShadow="false"
VerticalOptions="CenterAndExpand"
HorizontalOptions="FillAndExpand">
<StackLayout Orientation="Horizontal"
HorizontalOptions="FillAndExpand">
<Label x:Name="labText"
Text="(Wert)"
VerticalOptions="Center"
VerticalTextAlignment="Center"
HorizontalOptions="FillAndExpand"
HorizontalTextAlignment="End">
</Label>
</StackLayout>
</Frame>
</Grid>
</ContentView.Content>
</ContentView>
Again - if i comment out the Grid and the StackLayout, it works again… of course this is not a solution as i don't need a CustomControl if i cannot combine multiple elements in it ;) (it just works in this small example as there is only one frame with one label)
So… I don't WHY but it's obvious that the calculation of the CellView-Height has a problem with nested elements that each can change it's size.
It SEEMS that at some point in a Loop the calculated Size is reseted or ignored …
I don't have a solution :(
I cannot strip out every StackLayout in my Controls and Grids that used inside a ViewCell…
Because i like to go on, i think i have to set a fixed Row-Height, for example enough to fit two text rows, and hope for the best … Or i don't use WordWrap but trimming instead to fix it to one row :(
… oh and another Problem:
UnevenRows doesn't work for the Group-Cells! If ListView has Grouping enabled, all Group-Rows are of the same height - and automatic Height-Calculation doesn't work at all… i have to set a fixed height in the CellView
(at least on iOS - not testet on Android yet)
But maybe this a completely different topic.
Is there any update or workarounds?
If you are able to, please try migrating your ListView to CollectionView to workaround this issue. Thank you!
The cheapest/easiest workaround I found, is to call Device.BeginInvokeOnMainThread(() => ListView.IsRefreshing = true)
and reset it after some milliseconds in OnAppearing.
If you are able to, please try migrating your ListView to CollectionView to workaround this issue. Thank you!
Ironically, we only ran into this issue since we had to fallback to using the ListView on iOS. CollectionView had an issue wherein it was not applying the correct binding context to all of the controls in our item template. Admittedly, it is a non-trivial item template.
@chrisstaley Oooh, that sounds interesting. Did you open an issue for the binding issue?
@samhouts It's been on my list of things to do. I know that a repro would be (understandably) requested, and it would take a bit of effort to pull out the code into a sample project, so that _magically_ keeps getting pushed to the bottom of my TODO list. ;)
@chrisstaley 😆 you know us well! I'm sorry to hear that you had to move away from CollectionView so quickly, though, so I hope we can get that resolved for you.
@samhouts
If you are able to, please try migrating your ListView to CollectionView to workaround this issue. Thank you!
I followed this advice and converted to a CollectionView. Unfortunately this bug in CollectionView causes basically the same issue:
https://github.com/xamarin/Xamarin.Forms/issues/9520
Any chance that one of those fixes could get prioritized sometime soon?
Still waiting on this one to be fixed. Please fix this one asap. This one is really high priority and high impact.
Not having a functioning ListView (or CollectionView) on iOS except for basic uniform height rows vastly reduces the value of Xamarin.Forms. After all, if we only want to target our apps on Android, we'll go develop directly on that platform.
Most helpful comment
@LucasJordan, my custom control is already inside a
ContentView
and yet this bug is occurring in my app.Honestly, at this point I just cannot believe that we are already in the version 3.x of this framework (with the version 4.0 about to be released) and something as basic as creating a list with uneven rows is still misbehaving and causing issues. Plus, this is a blocking bug labeled as "high impact", but after several months we still have no solution for it.
Sorry for the rant, but this problem is just driving me crazy. I really hope we can get either a solution or a functioning workaround soon.