question

SreejithSree-2948 avatar image
0 Votes"
SreejithSree-2948 asked SreejithSree-2948 commented

Xamarin forms: Expansion and collapse is not working for list view in iOS

I am listing some items on the UI. If I tap on an item it will expand and show its details. I set everything on the UI including details initially and hide the details part. When I tap on the item I change the visibility of the details and showing it on UI. This feature is working fine on android and breaking in ios. I have uploaded a sample project here for reference.

Screenshot:

123068-processed.jpeg

Xaml.cs

 private void ItemTapped(object sender, ItemTappedEventArgs e)
 {
     var selectedItem = (Contact)e.Item;
     if (selectedItem != null)
     {
         if (phoneId == selectedItem.phoneOne)
         {
             Hide(selectedItem);
             phoneId = "";
         }
         else
         {
             Open(selectedItem);
         }
     }
     addressbook_listview.SelectedItem = null;
 }

 private void Open(Contact selectedItem)
 {
        
     foreach (var item in contactsList)
     {
         item.PhoneVisibility = false;
     }
     selectedItem.PhoneVisibility = true;
     phoneId = selectedItem.phoneOne;
 }
    
 private void Hide(Contact selectedItem)
 {
     selectedItem.PhoneVisibility = false;
 }

Xaml

 <ListView   
     x:Name="addressbook_listview"
     Grid.Row="1"
     BackgroundColor="Black"
     ItemTapped="addressbook_listview_ItemTapped"
     SelectionMode="None"
     HasUnevenRows="True">
     <ListView.ItemTemplate>
         <DataTemplate>
             <ViewCell>
                 <StackLayout 
                     Padding="10"
                     Orientation="Vertical">

                     <StackLayout
                             Grid.Column="1"
                             VerticalOptions="CenterAndExpand"
                             Margin="5,0,0,0">

                         <Label 
                                 Text="{Binding contactName}"
                                 TextColor="White">
                             <Label.FontSize>
                                 <OnIdiom x:TypeArguments="x:Double">
                                     <OnIdiom.Phone>15</OnIdiom.Phone>
                                     <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                     <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                 </OnIdiom>
                             </Label.FontSize>
                         </Label>

                         <Label 
                                 Text="{Binding phoneOne}"
                                 TextColor="White">
                             <Label.FontSize>
                                 <OnIdiom x:TypeArguments="x:Double">
                                     <OnIdiom.Phone>15</OnIdiom.Phone>
                                     <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                     <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                 </OnIdiom>
                             </Label.FontSize>
                         </Label>
                     </StackLayout>

                     <StackLayout 
                         HorizontalOptions="CenterAndExpand"
                         Margin="0,10,0,0"
                         IsVisible="{Binding PhoneVisibility}"
                         Orientation="Vertical">

                         <StackLayout 
                             Orientation="Horizontal">

                             <Label 
                                 Text="Phone 1"
                                 TextColor="White">
                                 <Label.FontSize>
                                     <OnIdiom x:TypeArguments="x:Double">
                                         <OnIdiom.Phone>15</OnIdiom.Phone>
                                         <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                         <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                     </OnIdiom>
                                 </Label.FontSize>
                             </Label>

                                 <Label 
                                 Text="{Binding phoneOne}"
                                 TextColor="White">
                                 <Label.FontSize>
                                     <OnIdiom x:TypeArguments="x:Double">
                                         <OnIdiom.Phone>15</OnIdiom.Phone>
                                         <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                         <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                     </OnIdiom>
                                 </Label.FontSize>
                             </Label>

                         </StackLayout>

                         <BoxView HeightRequest="0.5"
                                  HorizontalOptions="FillAndExpand"/>

                         <StackLayout
                             Orientation="Horizontal">

                             <Label 
                                 Text="Phone 2"
                                  TextColor="White">
                                 <Label.FontSize>
                                     <OnIdiom x:TypeArguments="x:Double">
                                         <OnIdiom.Phone>15</OnIdiom.Phone>
                                         <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                         <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                     </OnIdiom>
                                 </Label.FontSize>
                             </Label>

                             <Label 
                                 Text="{Binding phoneTwo}"
                                 TextColor="White">
                                 <Label.FontSize>
                                     <OnIdiom x:TypeArguments="x:Double">
                                         <OnIdiom.Phone>15</OnIdiom.Phone>
                                         <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                         <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                     </OnIdiom>
                                 </Label.FontSize>
                             </Label>
                         </StackLayout>
                     </StackLayout>
                 </StackLayout>
             </ViewCell>
         </DataTemplate>
     </ListView.ItemTemplate>
     <ListView.Footer>
         <Label/>
     </ListView.Footer>
 </ListView>


dotnet-xamarin
processed.jpeg (32.7 KiB)
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

LeonLu-MSFT avatar image
1 Vote"
LeonLu-MSFT answered SreejithSree-2948 commented

Hello,​

Welcome to our Microsoft Q&A platform!

It is a known issue in Xamarin.iOS, please refer to this thread:

https://github.com/xamarin/Xamarin.Forms/issues/2735

In this thread, I find a workaround to forceupdate UI.

Here is running screenshot in iOS.

123359-image.png

You can create custom Listivew.

public class EnhancedListView : ListView
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="EnhancedListView"/> class.
        /// </summary>
        /// <param name="strategy">The strategy.</param>
        public EnhancedListView()
        {
        }

        public void ForceNativeTableUpdate()
        {
            ViewCellSizeChangedEvent?.Invoke();
        }

        public event Action ViewCellSizeChangedEvent;
    }


Then achieve a custom renderer in the xamarin.iOS.

using ExpanderDemo;
using ExpanderDemo.iOS;
using Foundation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(EnhancedListView), typeof(EnhancedListViewRenderer))]
namespace ExpanderDemo.iOS
{
    public class EnhancedListViewRenderer : ListViewRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
        {
            base.OnElementChanged(e);

            if (e.NewElement is EnhancedListView enhancedListView)
            {
                enhancedListView.ViewCellSizeChangedEvent += UpdateTableView;
            }
        }

        private void UpdateTableView()
        {
            if (!(Control is UITableView tv)) return;
            tv.BeginUpdates();
            tv.EndUpdates();
        }
    }
}


Then use it in your xaml.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             xmlns:expanderdemo="clr-namespace:ExpanderDemo"
             x:Class="ExpanderDemo.MainPage">

    <StackLayout>

      
        <expanderdemo:EnhancedListView   
           
            x:Name="addressbook_listview"
            Grid.Row="1"
            BackgroundColor="Black"
            ItemTapped="addressbook_listview_ItemTapped"
            SelectionMode="None"
            HasUnevenRows="True">
          
            <expanderdemo:EnhancedListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout 
                            Padding="10"
                            Orientation="Vertical">

                            <StackLayout
                                    Grid.Column="1"
                                    VerticalOptions="CenterAndExpand"
                                    Margin="5,0,0,0">

                                <Label 
                                        Text="{Binding contactName}"
                                        TextColor="White">
                                    <Label.FontSize>
                                        <OnIdiom x:TypeArguments="x:Double">
                                            <OnIdiom.Phone>15</OnIdiom.Phone>
                                            <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                            <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                        </OnIdiom>
                                    </Label.FontSize>
                                </Label>

                                <Label 
                                        Text="{Binding phoneOne}"
                                        TextColor="White">
                                    <Label.FontSize>
                                        <OnIdiom x:TypeArguments="x:Double">
                                            <OnIdiom.Phone>15</OnIdiom.Phone>
                                            <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                            <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                        </OnIdiom>
                                    </Label.FontSize>
                                </Label>
                            </StackLayout>

                            <StackLayout 
                                HorizontalOptions="CenterAndExpand"
                                Margin="0,10,0,0"
                                IsVisible="{Binding PhoneVisibility}"
                                Orientation="Vertical">

                                <StackLayout 
                                    Orientation="Horizontal">

                                    <Label 
                                        Text="Phone 1"
                                        TextColor="White">
                                        <Label.FontSize>
                                            <OnIdiom x:TypeArguments="x:Double">
                                                <OnIdiom.Phone>15</OnIdiom.Phone>
                                                <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                                <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                            </OnIdiom>
                                        </Label.FontSize>
                                    </Label>

                                        <Label 
                                        Text="{Binding phoneOne}"
                                        TextColor="White">
                                        <Label.FontSize>
                                            <OnIdiom x:TypeArguments="x:Double">
                                                <OnIdiom.Phone>15</OnIdiom.Phone>
                                                <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                                <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                            </OnIdiom>
                                        </Label.FontSize>
                                    </Label>

                                </StackLayout>

                                <BoxView HeightRequest="0.5"
                                         HorizontalOptions="FillAndExpand"/>

                                <StackLayout
                                    Orientation="Horizontal">

                                    <Label 
                                        Text="Phone 2"
                                         TextColor="White">
                                        <Label.FontSize>
                                            <OnIdiom x:TypeArguments="x:Double">
                                                <OnIdiom.Phone>15</OnIdiom.Phone>
                                                <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                                <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                            </OnIdiom>
                                        </Label.FontSize>
                                    </Label>

                                    <Label 
                                        Text="{Binding phoneTwo}"
                                        TextColor="White">
                                        <Label.FontSize>
                                            <OnIdiom x:TypeArguments="x:Double">
                                                <OnIdiom.Phone>15</OnIdiom.Phone>
                                                <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                                <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                            </OnIdiom>
                                        </Label.FontSize>
                                    </Label>
                                </StackLayout>
                            </StackLayout>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </expanderdemo:EnhancedListView.ItemTemplate>
            <expanderdemo:EnhancedListView.Footer>
                <Label/>
            </expanderdemo:EnhancedListView.Footer>
        </expanderdemo:EnhancedListView>
    </StackLayout>

</ContentPage>


Here is xaml's background code. when you need to update your UI(hide or open message body ), please execute addressbook_listview.ForceNativeTableUpdate();

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using static ExpanderDemo.LoginResponse;

namespace ExpanderDemo
{
    public partial class MainPage : ContentPage
    {
        public ObservableCollection<Contact> contactsList;
        string phoneId;
        public MainPage()
        {
            InitializeComponent();
            contactsList = new ObservableCollection<Contact>();
            AddNumber();
        }

        private void AddNumber()
        {
            contactsList.Add(new Contact() {contactName="Smith", phoneOne="+1 1234567952", phoneTwo="1478523690",PhoneVisibility=false});
            contactsList.Add(new Contact() {contactName="Brent", phoneOne="+1 1234568852", phoneTwo="1478577690",PhoneVisibility=false});
            contactsList.Add(new Contact() {contactName="Finch", phoneOne="+1 1234560052", phoneTwo="1478529690",PhoneVisibility=false});
         
            addressbook_listview.ItemsSource = contactsList;
        }

        private void addressbook_listview_ItemTapped(object sender, ItemTappedEventArgs e)
        {
            var selectedItem = (Contact)e.Item;
            if (selectedItem != null)
            {
                if (phoneId == selectedItem.phoneOne)
                {
                    HideMessageBody(selectedItem);
                    phoneId = "";
                }
                else
                {
                    OpenMessageBody(selectedItem);
                }
            }
            addressbook_listview.SelectedItem = null;
        }

        private void OpenMessageBody(Contact selectedItem)
        {
            
                foreach (var item in contactsList)
                {
                    item.PhoneVisibility = false;
                }
                selectedItem.PhoneVisibility = true;
                phoneId = selectedItem.phoneOne;

            addressbook_listview.ForceNativeTableUpdate();
        }
        //YourListView.ForceNativeTableUpdate();
        private void HideMessageBody(Contact selectedItem)
        {
            selectedItem.PhoneVisibility = false;
            addressbook_listview.ForceNativeTableUpdate();
        }
    }
}



Best Regards,

Leon Lu



If the response is helpful, please click "Accept Answer" and upvote it.

Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.



image.png (31.2 KiB)
· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@SreejithSree-2948 May I know if you have got any chance to check my answer? I am glad to help if you have any other questions

0 Votes 0 ·

It is working fine, thanks for your support and sorry for the late response.

0 Votes 0 ·