Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ protected override void ItemsViewPropertyChanged(object sender, PropertyChangedE
UpdateHasFooter();
NotifyDataSetChanged();
}

}

public override int GetItemViewType(int position)
Expand Down Expand Up @@ -95,7 +96,6 @@ public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int positi
{
BindTemplatedItemViewHolder(templatedItemViewHolder, ItemsView.Footer);
}

return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,86 @@ public partial class StructuredItemsViewHandler<TItemsView> : ItemsViewHandler<T

public static void MapHeaderTemplate(StructuredItemsViewHandler<TItemsView> handler, StructuredItemsView itemsView)
{
handler.UpdateHeaderFooter(true);
}

public static void MapFooterTemplate(StructuredItemsViewHandler<TItemsView> handler, StructuredItemsView itemsView)
{
handler.UpdateHeaderFooter(false);
}

public static void MapItemsLayout(StructuredItemsViewHandler<TItemsView> handler, StructuredItemsView itemsView)
=> (handler.PlatformView as IMauiRecyclerView<TItemsView>)?.UpdateLayoutManager();

public static void MapItemSizingStrategy(StructuredItemsViewHandler<TItemsView> handler, StructuredItemsView itemsView)
=> (handler.PlatformView as IMauiRecyclerView<TItemsView>)?.UpdateAdapter();

void UpdateHeaderFooter(bool isHeader)
{
var recyclerView = PlatformView as IMauiRecyclerView<TItemsView>;
var adapter = (recyclerView as RecyclerView)?.GetAdapter();

if (recyclerView is null || adapter is null)
{
return;
}

bool hasHeaderOrFooter = isHeader
? (VirtualView.Header ?? VirtualView.HeaderTemplate) != null
: (VirtualView.Footer ?? VirtualView.FooterTemplate) != null;

bool exists = isHeader
? DoesHeaderExist(adapter)
: DoesFooterExist(adapter);

if (hasHeaderOrFooter && exists && IsDynamicChange())
{
recyclerView.UpdateAdapter();
}
else if (hasHeaderOrFooter != exists)
{
recyclerView.UpdateAdapter();
}
}

bool DoesHeaderExist(RecyclerView.Adapter adapter)
{
if (adapter.ItemCount >= 0)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please check?

{
return false;
}

try
{
return adapter.GetItemViewType(0) == ItemViewType.Header;
}
catch
{
return false;
}
}

bool DoesFooterExist(RecyclerView.Adapter adapter)
{
var footerPosition = adapter.ItemCount - 1;
if (footerPosition < 0)
{
return false;
}

try
{
return adapter.GetItemViewType(footerPosition) == ItemViewType.Footer;
}
catch
{
return false;
}
}

bool IsDynamicChange()
{
return (PlatformView as RecyclerView)?.IsLaidOut == true;
}
}
}
178 changes: 178 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue28676.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
using System.Collections.ObjectModel;

namespace Maui.Controls.Sample.Issues
{
[Issue(IssueTracker.Github, 28676, "Android Dynamic Updates to CollectionView Header and Footer Are Not Displayed",
PlatformAffected.Android)]
public class Issue28676 : ContentPage
{
private Label headerLabel;
private Label footerLabel;
private CollectionView collectionView;
private ObservableCollection<string> items;


public Issue28676()
{

items = new ObservableCollection<string>
{
"Item 1", "Item 2", "Item 3"
};

// Header and Footer Labels
headerLabel = new Label
{
Text = "Initial Header",
AutomationId = "Issue28676Header",
BackgroundColor = Colors.LightBlue,
FontAttributes = FontAttributes.Bold,
Padding = 10
};

footerLabel = new Label
{
Text = "Initial Footer",
AutomationId = "Issue28676Footer",
BackgroundColor = Colors.LightGray,
Padding = 10
};

// CollectionView
collectionView = new CollectionView
{
ItemsSource = items,
AutomationId = "Issue28676CollectionView",
Header = headerLabel,
Footer = footerLabel,
ItemTemplate = new DataTemplate(() =>
{
var stack = new StackLayout
{
Padding = 10,
Spacing = 10
};

var label = new Label();
label.SetBinding(Label.TextProperty, ".");

stack.Children.Add(label);
return stack;
})
};

// Top Grid with 2x2 Buttons
var topGrid = new Grid
{
RowDefinitions =
{
new RowDefinition(GridLength.Auto),
new RowDefinition(GridLength.Auto)
},
ColumnDefinitions =
{
new ColumnDefinition(GridLength.Star),
new ColumnDefinition(GridLength.Star)
},
Padding = 10,
RowSpacing = 10,
ColumnSpacing = 10
};

var button1 = new Button { Text = "Update Header", AutomationId = "Issue28676UpdateHeaderButton", };
button1.Clicked += (s, e) => collectionView.Header = "UpdatedCollectionViewHeader";

var button2 = new Button { Text = "Update Footer", AutomationId = "Issue28676UpdateFooterButton", };
button2.Clicked += (s, e) => collectionView.Footer = "UpdatedCollectionViewFooter";

var button3 = new Button { Text = "ChangeHeaderView", AutomationId = "Issue28676ChangeHeaderView", };
button3.Clicked += OnChangeHeaderView;

var button4 = new Button { Text = "ChangeFooterView", AutomationId = "Issue28676ChangeFooterView", };
button4.Clicked += OnChangeFooterView;

topGrid.Add(button1, 0, 0);
topGrid.Add(button2, 1, 0);
topGrid.Add(button3, 0, 1);
topGrid.Add(button4, 1, 1);

// Main Grid Layout
var mainGrid = new Grid
{
RowDefinitions =
{
new RowDefinition { Height = GridLength.Auto },
new RowDefinition { Height = GridLength.Star }
}
};

mainGrid.Add(topGrid, 0, 0);
mainGrid.Add(collectionView, 0, 1);

Content = mainGrid;
}

private void OnChangeHeaderView(object sender, EventArgs e)
{
var newHeaderGrid = new Grid
{
Padding = 10,
AutomationId = "Issue28676HeaderView",
BackgroundColor = Colors.LightGreen,
RowDefinitions =
{
new RowDefinition { Height = GridLength.Auto }
},
ColumnDefinitions =
{
new ColumnDefinition { Width = GridLength.Star }
}
};

var headerLabel = new Label
{
Text = "Updated HeaderView",
FontAttributes = FontAttributes.Bold,
FontSize = 16,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
TextColor = Colors.Black
};

newHeaderGrid.Add(headerLabel, 0, 0);
collectionView.Header = newHeaderGrid;
}

private void OnChangeFooterView(object sender, EventArgs e)
{
var newHeaderGrid = new Grid
{
Padding = 10,
AutomationId = "Issue28676FooterView",
BackgroundColor = Colors.LightCyan,
RowDefinitions =
{
new RowDefinition { Height = GridLength.Auto }
},
ColumnDefinitions =
{
new ColumnDefinition { Width = GridLength.Star }
}
};

var headerLabel = new Label
{
Text = "Updated FooterView",
FontAttributes = FontAttributes.Bold,
FontSize = 16,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
TextColor = Colors.Black
};

newHeaderGrid.Add(headerLabel, 0, 0);
collectionView.Footer = newHeaderGrid;
}
}
}

Loading
Loading