diff options
author | Rui Marinho <me@ruimarinho.net> | 2016-06-09 18:59:26 +0100 |
---|---|---|
committer | Samantha Houts <samantha@teamredwall.com> | 2016-06-09 10:59:26 -0700 |
commit | e2e303654e76eaf79fa4b1629df1f2b351fa9fcd (patch) | |
tree | 8c51b29c5511dece0bf28794a8f225e8c563d6b1 | |
parent | 67511ed858719ce8906929f7900e9c1080cd48d9 (diff) | |
download | xamarin-forms-e2e303654e76eaf79fa4b1629df1f2b351fa9fcd.tar.gz xamarin-forms-e2e303654e76eaf79fa4b1629df1f2b351fa9fcd.tar.bz2 xamarin-forms-e2e303654e76eaf79fa4b1629df1f2b351fa9fcd.zip |
[Android] Always create a new cell for GroupHeader when using Recycling (#206)
* [Android] Always create a new cell for GroupHeader when using RecycleElement
* [iOS] Fix uitest iOS
* [Android] Fix test on android
3 files changed, 246 insertions, 1 deletions
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla40704.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla40704.cs new file mode 100644 index 00000000..dcae4617 --- /dev/null +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla40704.cs @@ -0,0 +1,231 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using Xamarin.Forms.CustomAttributes; +using Xamarin.Forms.Internals; +using System.Text; + +#if UITEST +using Xamarin.UITest; +using NUnit.Framework; +#endif + +namespace Xamarin.Forms.Controls +{ + [Preserve(AllMembers = true)] + [Issue(IssueTracker.Bugzilla, 40704, "Strange duplication of listview headers when collapsing/expanding sections")] + public class Bugzilla40704 : TestContentPage // or TestMasterDetailPage, etc ... + { + ListView listview; + int count = 2; + + protected override void Init() + { + listview = new ListView(ListViewCachingStrategy.RecycleElement) + { + AutomationId = "lstMain", + IsGroupingEnabled = true, + HasUnevenRows = true, + GroupHeaderTemplate = new DataTemplate(typeof(GroupHeaderViewCell)), + ItemTemplate = new DataTemplate(typeof(ItemTestViewCell)) + }; + + FillPatientsList(); + + var button = new Button() + { + Text = "Collapse", + AutomationId = "btnCollappse" + }; + listview.Footer = button; + button.Clicked += Button_Clicked; + Content = listview; + } + + void Button_Clicked(object sender, EventArgs e) + { + var source = listview.ItemsSource as List<PatientsGroupViewModel>; + source[count].Toggle(); + count--; + if (count < 0) + count = 2; + } + + private void FillPatientsList() + { + const int groupsNumber = 3; + const int patientsNumber = 10; + + var patientGroups = new List<PatientsGroupViewModel>(); + var random = new Random(); + + for (var i = 0; i < groupsNumber; i++) + { + var patients = new List<PatientViewModel>(); + for (var j = 0; j < patientsNumber; j++) + { + var code = string.Format("{0}-{1}", i, j); + var length = random.Next(5, 100); + var strBuilder = new StringBuilder(); + for (int z = 0; z < length; z++) + { + strBuilder.Append(code); + if (z % 7 == 0) + { + strBuilder.Append(' '); + } + } + + patients.Add(new PatientViewModel(code) { Description = strBuilder.ToString() }); + } + + patientGroups.Add(new PatientsGroupViewModel(patients) + { + Title = "Menu - " + i.ToString() + }); + + } + + listview.ItemsSource = patientGroups; + } + + [Preserve(AllMembers = true)] + public class GroupHeaderViewCell : ViewCell + { + TapGestureRecognizer tapGesture; + + public GroupHeaderViewCell() + { + Height = 40; + var grd = new Grid { BackgroundColor = Color.Aqua, Padding = new Thickness(5, 10) }; + tapGesture = new TapGestureRecognizer(); + tapGesture.Tapped += HeaderCell_OnTapped; + grd.GestureRecognizers.Add(tapGesture); + var lbl = new Label { HorizontalOptions = LayoutOptions.FillAndExpand, TextColor = Color.Black, FontSize = 16 }; + lbl.SetBinding(Label.TextProperty, new Binding("Title")); + + grd.Children.Add(lbl); + View = grd; + } + + void HeaderCell_OnTapped(object sender, EventArgs e) + { + var cell = (Layout)sender; + var vm = cell.BindingContext as PatientsGroupViewModel; + + if (vm != null) + { + vm.Toggle(); + } + } + } + + [Preserve(AllMembers = true)] + public class ItemTestViewCell : ViewCell + { + public ItemTestViewCell() + { + + var grd = new Grid { BackgroundColor = Color.Yellow }; + var lbl = new Label { HorizontalOptions = LayoutOptions.FillAndExpand, TextColor = Color.Black, FontSize = 16, LineBreakMode = LineBreakMode.WordWrap }; + lbl.SetBinding(Label.TextProperty, new Binding("Description")); + grd.Children.Add(lbl); + View = grd; + } + } + + [Preserve(AllMembers = true)] + public class RangeObservableCollection<T> : ObservableCollection<T> + { + private bool _suppressNotification = false; + + protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) + { + if (!_suppressNotification) + base.OnCollectionChanged(e); + } + + public void AddRange(IEnumerable<T> list) + { + if (list == null) + throw new ArgumentNullException("list"); + + _suppressNotification = true; + + foreach (var item in list) + { + Add(item); + } + _suppressNotification = false; + OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); + } + } + + [Preserve(AllMembers = true)] + public class PatientsGroupViewModel : RangeObservableCollection<PatientViewModel> + { + public bool IsCollapsed { get; private set; } + + public string Title { get; set; } + + private readonly List<PatientViewModel> _patients; + + public PatientsGroupViewModel(List<PatientViewModel> patients) + { + _patients = patients; + + UpdateCollection(); + } + + public void Toggle() + { + IsCollapsed = !IsCollapsed; + + UpdateCollection(); + } + + private void UpdateCollection() + { + if (!IsCollapsed) + { + AddRange(_patients); + } + else + { + Clear(); + } + } + } + + [Preserve(AllMembers = true)] + public class PatientViewModel + { + public PatientViewModel(string code) + { + Code = code; + } + + public string Code { get; set; } + + public string Description { get; set; } + } + + + #if UITEST + [Test] + public void Bugzilla40704Test() + { + RunningApp.ScrollDownTo("btnCollappse", "lstMain", ScrollStrategy.Gesture, 0.8, timeout: TimeSpan.FromMinutes(2)); + RunningApp.Tap("btnCollappse"); + RunningApp.ScrollDownTo("btnCollappse", "lstMain", ScrollStrategy.Gesture, 0.8, timeout: TimeSpan.FromMinutes(2)); + RunningApp.Tap("btnCollappse"); + RunningApp.ScrollDownTo("btnCollappse", "lstMain", ScrollStrategy.Gesture, 0.8, timeout: TimeSpan.FromMinutes(2)); + RunningApp.Tap("btnCollappse"); + RunningApp.WaitForElement("Menu - 2"); + RunningApp.WaitForElement("Menu - 1"); + RunningApp.WaitForElement("Menu - 0"); + } +#endif + } +} diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems index 991270b6..00fad875 100644 --- a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems @@ -403,6 +403,7 @@ </Compile> <Compile Include="$(MSBuildThisFileDirectory)Bugzilla39963.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Bugzilla39987.cs" /> + <Compile Include="$(MSBuildThisFileDirectory)Bugzilla40704.cs" /> </ItemGroup> <ItemGroup> <EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla22229.xaml"> diff --git a/Xamarin.Forms.Platform.Android/Renderers/ListViewAdapter.cs b/Xamarin.Forms.Platform.Android/Renderers/ListViewAdapter.cs index 81214957..522ff4b2 100644 --- a/Xamarin.Forms.Platform.Android/Renderers/ListViewAdapter.cs +++ b/Xamarin.Forms.Platform.Android/Renderers/ListViewAdapter.cs @@ -421,7 +421,20 @@ namespace Xamarin.Forms.Platform.Android if (global == position || cells.Count > 0) { - cells.Add(group.HeaderContent); + if (_listView.CachingStrategy == ListViewCachingStrategy.RecycleElement) + { + var groupContent = _listView.TemplatedItems.GroupHeaderTemplate.CreateContent(group.ItemsSource, _listView) as Cell; + if (groupContent != null) + { + groupContent.BindingContext = group.ItemsSource; + cells.Add(groupContent); + } + } + else + { + cells.Add(group.HeaderContent); + } + if (cells.Count == take) return cells; } |