Skip to content

Commit

Permalink
Implement CollectionView grouping on Android (xamarin#7199)
Browse files Browse the repository at this point in the history
* Move all the header/footer adjustment to IItemsViewSource
fixes xamarin#7121
fixes xamarin#7102
partially implements xamarin#3172
fixes xamarin#7243

* Fix selection bugs introduced by header/footer on Android

* Implement grouping for CollectionView on Android

* Enable grouping tests for Android

* Naming and comment cleanup

* Update Xamarin.Forms.Platform.Android/CollectionView/ListSource.cs

Co-Authored-By: Gerald Versluis <gerald.versluis@microsoft.com>

* Update Xamarin.Forms.Platform.Android/CollectionView/ObservableGroupedSource.cs
  • Loading branch information
hartez authored and felipebaltazar committed Oct 16, 2019
1 parent 8aa0fd3 commit f2dcc9a
Showing 46 changed files with 1,202 additions and 175 deletions.
Original file line number Diff line number Diff line change
@@ -29,7 +29,7 @@ protected override void Init()
#endif
}

#if UITEST && __IOS__ // Grouping is not implemented on Android yet
#if UITEST
[Test]
public void RemoveSelectedItem()
{
@@ -88,8 +88,6 @@ public void MoveGroup()
RunningApp.WaitForElement("MoveGroup");
RunningApp.Tap("MoveGroup");
}


#endif
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;

#if UITEST
using Xamarin.Forms.Core.UITests;
using Xamarin.UITest;
using NUnit.Framework;
#endif

namespace Xamarin.Forms.Controls.Issues
{
#if UITEST
[Category(UITestCategories.CollectionView)]
#endif
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 7102, "[Bug] CollectionView Header cause delay to adding items.",
PlatformAffected.Android)]
public class Issue7102 : TestNavigationPage
{
protected override void Init()
{
#if APP
FlagTestHelpers.SetCollectionViewTestFlag();

PushAsync(new GalleryPages.CollectionViewGalleries.ObservableCodeCollectionViewGallery(grid: false));
#endif
}

#if UITEST
[Test]
public void HeaderDoesNotBreakIndexes()
{
RunningApp.WaitForElement("entryInsert");
RunningApp.Tap("entryInsert");
RunningApp.ClearText();
RunningApp.EnterText("1");
RunningApp.Tap("Insert");

// If the bug is still present, then there will be
// two "Item: 0" items instead of the newly inserted item
// Or the header will have disappeared
RunningApp.WaitForElement("Inserted");
RunningApp.WaitForElement("This is the header");
}
#endif
}
}
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@
<Compile Include="$(MSBuildThisFileDirectory)NestedCollectionViews.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ShellGestures.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ShellBackButtonBehavior.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue7102.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ShellInsets.cs" />
<Compile Include="$(MSBuildThisFileDirectory)CollectionViewGrouping.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue5412.cs" />
Original file line number Diff line number Diff line change
@@ -17,10 +17,10 @@ protected CollectionModifier(CollectionView cv, string buttonText)
HorizontalOptions = LayoutOptions.Fill
};

var button = new Button { Text = buttonText, AutomationId = $"btn{buttonText}" };
var label = new Label { Text = LabelText, VerticalTextAlignment = TextAlignment.Center };
var button = new Button { Text = buttonText, AutomationId = $"btn{buttonText}", HeightRequest = 20, FontSize = 10 };
var label = new Label { Text = LabelText, VerticalTextAlignment = TextAlignment.Center, FontSize = 10 };

Entry = new Entry { Keyboard = Keyboard.Numeric, Text = InitialEntryText, WidthRequest = 100, AutomationId = $"entry{buttonText}" };
Entry = new Entry { Keyboard = Keyboard.Numeric, Text = InitialEntryText, WidthRequest = 100, FontSize = 10, AutomationId = $"entry{buttonText}" };

layout.Children.Add(label);
layout.Children.Add(Entry);
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.GroupingGalleries.BasicGrouping">
<ContentPage.Content>
<CollectionView x:Name="CollectionView" IsGrouped="True">
<CollectionView x:Name="CollectionView" IsGrouped="True" Header="This is a header" Footer="Hey, a footer.">

<CollectionView.ItemTemplate>
<DataTemplate>
Original file line number Diff line number Diff line change
@@ -11,12 +11,12 @@
namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.GroupingGalleries
{
[XamlCompilation(XamlCompilationOptions.Compile)]
[Preserve (AllMembers = true)]
[Preserve(AllMembers = true)]
public partial class BasicGrouping : ContentPage
{
public BasicGrouping ()
public BasicGrouping()
{
InitializeComponent ();
InitializeComponent();

CollectionView.ItemsSource = new SuperTeams();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?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:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.GroupingGalleries.GridGrouping">
<ContentPage.Content>
<CollectionView x:Name="CollectionView" IsGrouped="True" Header="This is a header" Footer="This is a footer.">

<CollectionView.ItemsLayout>
<GridItemsLayout Span="2" Orientation="Vertical"></GridItemsLayout>
</CollectionView.ItemsLayout>

<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding Name}" Margin="5,0,0,0"/>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>

<CollectionView.GroupHeaderTemplate>
<DataTemplate>

<Label Text="{Binding Name}" BackgroundColor="LightGreen" FontSize="16" FontAttributes="Bold"/>

</DataTemplate>
</CollectionView.GroupHeaderTemplate>

<CollectionView.GroupFooterTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding Count, StringFormat='{}Total members: {0:D}'}" BackgroundColor="Orange"
Margin="0,0,0,15"/>
</StackLayout>
</DataTemplate>
</CollectionView.GroupFooterTemplate>

</CollectionView>
</ContentPage.Content>
</ContentPage>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Xamarin.Forms.Xaml;

namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.GroupingGalleries
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class GridGrouping : ContentPage
{
public GridGrouping()
{
InitializeComponent();
CollectionView.ItemsSource = new SuperTeams();
}
}
}
Original file line number Diff line number Diff line change
@@ -32,6 +32,8 @@ public GroupingGallery()
new SwitchGrouping(), Navigation),
GalleryBuilder.NavButton("Grouping, Observable", () =>
new ObservableGrouping(), Navigation),
GalleryBuilder.NavButton("Grouping, Grid", () =>
new GridGrouping(), Navigation),
}
}
};
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ public ObservableGrouping()
Title = "Observable Grouped List";

var buttonStyle = new Style(typeof(Button)) { };
buttonStyle.Setters.Add(new Setter() { Property = Button.HeightRequestProperty, Value = 20 });
buttonStyle.Setters.Add(new Setter() { Property = Button.HeightRequestProperty, Value = 30 });
buttonStyle.Setters.Add(new Setter() { Property = Button.FontSizeProperty, Value = 10 });

var layout = new Grid
@@ -34,6 +34,8 @@ public ObservableGrouping()

var collectionView = new CollectionView
{
Header = "This is a header",
Footer = "Hey, I'm a footer. Look at me!",
ItemTemplate = ItemTemplate(),
GroupFooterTemplate = GroupFooterTemplate(),
GroupHeaderTemplate = GroupHeaderTemplate(),
@@ -102,7 +104,15 @@ public ObservableGrouping()
Style = buttonStyle };
groupRemover.Clicked += (obj, args) => {
itemsSource?.Remove(itemsSource[0]);
groupRemover.Text = $"Remove {itemsSource[0].Name}";
if (itemsSource.Count > 0)
{
groupRemover.Text = $"Remove {itemsSource[0].Name}";
}
else
{
groupRemover.Text = "";
groupRemover.IsEnabled = false;
}
mover.Text = $"Move Selected To {itemsSource[0].Name}";
};

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?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:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.HeaderFooterGalleries.FooterOnlyString">
<ContentPage.Content>
<CollectionView x:Name="CollectionView" Footer="This is a footer">

</CollectionView>
</ContentPage.Content>
</ContentPage>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.HeaderFooterGalleries
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class FooterOnlyString : ContentPage
{
readonly DemoFilteredItemSource _demoFilteredItemSource = new DemoFilteredItemSource(20);

public FooterOnlyString()
{
InitializeComponent();

CollectionView.ItemTemplate = ExampleTemplates.PhotoTemplate();
CollectionView.ItemsSource = _demoFilteredItemSource.Items;
}
}
}
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ public HeaderFooterGallery()
GalleryBuilder.NavButton("Header/Footer (Forms View)", () => new HeaderFooterView(), Navigation),
GalleryBuilder.NavButton("Header/Footer (Template)", () => new HeaderFooterTemplate(), Navigation),
GalleryBuilder.NavButton("Header/Footer (Grid)", () => new HeaderFooterGrid(), Navigation),
GalleryBuilder.NavButton("Header/Footer (Grid Horizontal)", () => new HeaderFooterGridHorizontal(), Navigation),
GalleryBuilder.NavButton("Footer Only (String)", () => new FooterOnlyString(), Navigation),
}
}
};
Original file line number Diff line number Diff line change
@@ -25,7 +25,8 @@ public ObservableCodeCollectionViewGallery(ItemsLayoutOrientation orientation =

var itemTemplate = ExampleTemplates.PhotoTemplate();

var collectionView = new CollectionView {ItemsLayout = itemsLayout, ItemTemplate = itemTemplate, AutomationId = "collectionview" };
var collectionView = new CollectionView {ItemsLayout = itemsLayout, ItemTemplate = itemTemplate,
AutomationId = "collectionview", Header = "This is the header" };

var generator = new ItemsSourceGenerator(collectionView, initialItems, ItemsSourceType.ObservableCollection);

Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@

<Button AutomationId="DirectUpdate" HeightRequest="35" FontSize="10" Text="Clear CV selection and add Items 0 and 3" Clicked="DirectUpdateClicked" />

<CollectionView x:Name="CollectionView" ItemsSource="{Binding Items}"
<CollectionView x:Name="CollectionView" ItemsSource="{Binding Items}" Header="This is the header"
SelectionMode="Multiple" SelectedItems="{Binding SelectedItems}">
<CollectionView.ItemTemplate>
<DataTemplate>
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@

<Label x:Name="SelectedItemsCommand" Grid.Row="2"/>

<CollectionView x:Name="CollectionView" Grid.Row="3" />
<CollectionView x:Name="CollectionView" Grid.Row="3" Header="This is the header" />

</Grid>
</ContentPage.Content>
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@

<Label Text="The CollectionView below should have several items already selected."/>

<CollectionView x:Name="CollectionView" Grid.Row="3">
<CollectionView x:Name="CollectionView" Grid.Row="3" Header="This is the header">
<CollectionView.ItemsLayout>
<GridItemsLayout Span="4" Orientation="Vertical"></GridItemsLayout>
</CollectionView.ItemsLayout>
Original file line number Diff line number Diff line change
@@ -9,8 +9,8 @@
<StackLayout>

<Label x:Name="Result" Text="Pending..."></Label>
<CollectionView ItemsSource="{Binding Items}"

<CollectionView ItemsSource="{Binding Items}" Header="This is the header"
SelectionMode="Single"
SelectionChangedCommandParameter="{Binding SelectedItem,Source={x:Reference MyCollectionView}}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
Original file line number Diff line number Diff line change
@@ -41,7 +41,7 @@

<Label x:Name="SelectedItemsCommand" Grid.Row="3" HeightRequest="50" Margin="2" />

<CollectionView x:Name="CollectionView" Grid.Row="4">
<CollectionView x:Name="CollectionView" Grid.Row="4" Header="This is the header">
<CollectionView.ItemsLayout>
<GridItemsLayout Span="3" Orientation="Vertical"></GridItemsLayout>
</CollectionView.ItemsLayout>
8 changes: 7 additions & 1 deletion Xamarin.Forms.Controls/Xamarin.Forms.Controls.csproj
Original file line number Diff line number Diff line change
@@ -56,11 +56,17 @@
<EmbeddedResource Update="GalleryPages\BindableLayoutGalleryPage.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Update="GalleryPages\CollectionViewGalleries\GroupingGalleries\GridGrouping.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Update="GalleryPages\CollectionViewGalleries\HeaderFooterGalleries\FooterOnlyString.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Update="GalleryPages\CharacterSpacingGallery.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Update="GalleryPages\CollectionViewGalleries\EmptyViewGalleries\EmptyViewSwapGallery.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Update="GalleryPages\CollectionViewGalleries\NestedGalleries\NestedCollectionViewGallery.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
Loading

0 comments on commit f2dcc9a

Please sign in to comment.