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

[iOS] Xamarin.Forms Listview Row Height Does Not Update When Changing Content Size (such as label) #2383

Open
samhouts opened this Issue Apr 7, 2018 · 15 comments

Comments

Projects
@samhouts
Copy link
Member

samhouts commented Apr 7, 2018

Description

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.

  • Missing Preserve attribute
  • Test needs to be automated
  • Manual test needs instructions

Steps to Reproduce

1.) 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.
4. Bug: scrolling up and down becomes jittery, cells overlap.

Basic Information

  • Version with issue: 2.5.0+ (last tested with 3.3.0.967583)
  • Last known good version:

Issue2383.zip

@pauldipietro pauldipietro added this to New in Triage Apr 7, 2018

@jassmith jassmith moved this from New to Ready For Work in Triage Apr 7, 2018

@LeeCenY

This comment has been minimized.

Copy link

LeeCenY commented Apr 27, 2018

Hidden controls also do not update height!

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

@aabc123

This comment has been minimized.

Copy link

aabc123 commented Aug 22, 2018

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.

@LJordanCoCo

This comment has been minimized.

Copy link

LJordanCoCo commented Aug 24, 2018

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.

@LJordanCoCo

This comment has been minimized.

Copy link

LJordanCoCo commented Sep 5, 2018

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.

@LJordanCoCo

This comment has been minimized.

Copy link

LJordanCoCo commented Sep 5, 2018

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.

@swasti29

This comment has been minimized.

Copy link

swasti29 commented Sep 10, 2018

Any one find the solution of it?

@adrianknight89

This comment has been minimized.

Copy link
Contributor

adrianknight89 commented Sep 22, 2018

@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.

@samhouts samhouts added this to To do in iOS Ready For Work Oct 15, 2018

@samhouts samhouts removed this from Ready For Work in Triage Oct 15, 2018

@samhouts samhouts added the i/high label Nov 2, 2018

@ederbond

This comment has been minimized.

Copy link

ederbond commented Nov 6, 2018

Any time frame to fix this blocking issue ?

@LucasJordan

This comment has been minimized.

Copy link

LucasJordan commented Nov 6, 2018

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.

@ernestoyaquello

This comment has been minimized.

Copy link

ernestoyaquello commented Dec 4, 2018

@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.

@biozal

This comment has been minimized.

Copy link

biozal commented Dec 6, 2018

@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.

@ernestoyaquello

This comment has been minimized.

Copy link

ernestoyaquello commented Dec 6, 2018

@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.

@ernestoyaquello

This comment has been minimized.

Copy link

ernestoyaquello commented Dec 6, 2018

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.

@samhouts samhouts added this to To do in Sprint 146 Dec 15, 2018

@vlkam

This comment has been minimized.

Copy link

vlkam commented Dec 31, 2018

I've worked around this with cell.ForceUpdateSize()

@samhouts samhouts moved this from To do to Returned to backlog in Sprint 146 Jan 9, 2019

@hagronnestad

This comment has been minimized.

Copy link

hagronnestad commented Mar 18, 2019

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:
image

Screenshot Android:
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.