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

Sreejith Sree 1,251 Reputation points
2021-08-13T09:30:28.123+00:00

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>  
Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,305 questions
0 comments No comments
{count} votes

Accepted answer
  1. Leon Lu (Shanghai Wicresoft Co,.Ltd.) 69,691 Reputation points Microsoft Vendor
    2021-08-16T05:52:19.517+00:00

    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.

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful