summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamantha Houts <samantha@teamredwall.com>2017-03-14 03:30:22 -0700
committerRui Marinho <me@ruimarinho.net>2017-03-14 10:30:22 +0000
commite7f5a4188d2c102a3eada30b2d55a5e7ee481f1d (patch)
tree810a387a1b03ba5d63fc130fd566be80225665b5
parentb23e40a2010f93164e36c90e411c2cc0d5d4e60e (diff)
downloadxamarin-forms-e7f5a4188d2c102a3eada30b2d55a5e7ee481f1d.tar.gz
xamarin-forms-e7f5a4188d2c102a3eada30b2d55a5e7ee481f1d.tar.bz2
xamarin-forms-e7f5a4188d2c102a3eada30b2d55a5e7ee481f1d.zip
[iOS] ViewCells will respond to ForceUpdateSize in RecycleElement mode (#809)
* Add reproduction for 44525 * Clean up gallery page * [iOS] Get index path from Cell in RecycleElement * Fix obsolete code
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla44525.cs104
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems1
-rw-r--r--Xamarin.Forms.Controls/ControlGalleryPages/CellForceUpdateSizeGalleryPage.cs282
-rw-r--r--Xamarin.Forms.Platform.iOS/Cells/CellRenderer.cs4
4 files changed, 252 insertions, 139 deletions
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla44525.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla44525.cs
new file mode 100644
index 00000000..e159aa71
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla44525.cs
@@ -0,0 +1,104 @@
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.Forms.Internals;
+using System.ComponentModel;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve(AllMembers = true)]
+ [Issue(IssueTracker.Bugzilla, 44525, "Listview Row Height Does Not Adapt In iOS")]
+ public class Bugzilla44525 : TestContentPage
+ {
+ List<Person> _DataSource;
+
+ [Preserve(AllMembers = true)]
+ class CustomCell : ViewCell
+ {
+ public CustomCell()
+ {
+ Label age = new Label();
+ Label name = new Label();
+ StackLayout cellWrapper = new StackLayout();
+
+ age.SetBinding(Label.TextProperty, "Age");
+ name.SetBinding(Label.TextProperty, "Name");
+
+ age.PropertyChanged += UpdateCell;
+ name.PropertyChanged += UpdateCell;
+
+ cellWrapper.Children.Add(age);
+ cellWrapper.Children.Add(name);
+
+ View = cellWrapper;
+ }
+
+ void UpdateCell(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == Label.TextProperty.PropertyName)
+ {
+ ForceUpdateSize();
+ }
+ }
+ }
+
+ class Person : ViewModelBase
+ {
+ private string _Name;
+ public string Name
+ {
+ get
+ {
+ return _Name;
+ }
+ set
+ {
+ if (_Name == value)
+ return;
+
+ _Name = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private string _Age;
+ public string Age
+ {
+ get
+ {
+ return _Age;
+ }
+ set
+ {
+ if (_Age == value)
+ return;
+
+ _Age = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+
+ protected override void Init()
+ {
+ _DataSource = Enumerable.Range(1, 100).Select(c => new Person { Name = $"Person {c}", Age = $"{c} year(s) old" }).ToList();
+
+ var listView = new ListView(ListViewCachingStrategy.RecycleElement)
+ {
+ ItemTemplate = new DataTemplate(typeof(CustomCell)),
+ ItemsSource = _DataSource,
+ HasUnevenRows = true
+ };
+
+ var button = new Button { Text = "Click me" };
+ button.Clicked += (sender, e) =>
+ {
+ var target = _DataSource[1];
+ target.Name = "I am an exceptionally long string that should cause the label to wrap, thus increasing the size of the ViewCell such that the entirety of the string is readable by human eyes. Hurrah.";
+ };
+
+ Content = new StackLayout { Children = { button, listView } };
+ }
+ }
+}
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 99f2bf81..38fc48a0 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
@@ -247,6 +247,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla40722.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla41153.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla44129.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla44525.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla28650.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla37431.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla44777.cs" />
diff --git a/Xamarin.Forms.Controls/ControlGalleryPages/CellForceUpdateSizeGalleryPage.cs b/Xamarin.Forms.Controls/ControlGalleryPages/CellForceUpdateSizeGalleryPage.cs
index 6e64b0d7..5d8b3fe8 100644
--- a/Xamarin.Forms.Controls/ControlGalleryPages/CellForceUpdateSizeGalleryPage.cs
+++ b/Xamarin.Forms.Controls/ControlGalleryPages/CellForceUpdateSizeGalleryPage.cs
@@ -1,194 +1,202 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel;
using System.Linq;
+using System.Threading.Tasks;
using Xamarin.Forms.Internals;
namespace Xamarin.Forms.Controls
{
- [Preserve (AllMembers = true)]
- public class CellForceUpdateSizeGalleryPage : TabbedPage
+ [Preserve(AllMembers = true)]
+ public class CellForceUpdateSizeGalleryPage : NavigationPage
{
- public class ViewCellPage : ContentPage
+ [Preserve(AllMembers = true)]
+ public class MyViewCell : ViewCell
{
- [Preserve (AllMembers = true)]
- public class MyViewCell : ViewCell
- {
- public MyViewCell ()
- {
- var image = new Image {
- Source = ImageSource.FromFile ("crimson.jpg"),
- BackgroundColor = Color.Gray,
- HeightRequest = 50,
- VerticalOptions = LayoutOptions.Fill,
- HorizontalOptions = LayoutOptions.Fill
- };
-
- var button = new Button { Text = "+" };
- button.Clicked += (object sender, EventArgs e) =>
- {
- image.HeightRequest = image.Height + 100;
- ForceUpdateSize ();
- };
+ Label _Label = new Label();
+ VariableHeightItem _DataItem => BindingContext as VariableHeightItem;
- Tapped += (object sender, EventArgs e) =>
- {
- image.HeightRequest = image.Height - 100;
- ForceUpdateSize ();
- };
+ public MyViewCell()
+ {
+ _Label.SetBinding(Label.TextProperty, nameof(_DataItem.Text));
+ _Label.PropertyChanged += UpdateCell;
- View = new StackLayout { Orientation = StackOrientation.Horizontal, Children = { image, button } };
- }
+ View = new StackLayout { Children = { _Label } };
}
- public ViewCellPage ()
+ void UpdateCell(object sender, PropertyChangedEventArgs e)
{
- var listview = new ListView {
- HasUnevenRows = true,
- };
- var items = Enumerable.Range (0, 10);
- listview.ItemsSource = items;
- listview.ItemTemplate = new DataTemplate (typeof (MyViewCell));
- Content = listview;
- Title = "View Cell";
+ if (e.PropertyName == Label.TextProperty.PropertyName)
+ {
+ ForceUpdateSize();
+ }
}
}
- public class ImageCellPage : ContentPage
+ [Preserve(AllMembers = true)]
+ public class MyImageCell : ImageCell
{
- [Preserve (AllMembers = true)]
- public class MyImageCell : ImageCell
+ VariableHeightItem _DataItem => BindingContext as VariableHeightItem;
+
+ public MyImageCell()
{
- public MyImageCell ()
- {
- ImageSource = ImageSource.FromFile ("crimson.jpg");
- Height = 20;
- Command = new Command (() =>
- {
- Height += 20;
- ForceUpdateSize ();
- });
- }
+ SetBinding(TextProperty, new Binding(nameof(_DataItem.Text)));
+ PropertyChanged += UpdateCell;
}
- public ImageCellPage ()
+
+ void UpdateCell(object sender, PropertyChangedEventArgs e)
{
- var listview = new ListView {
- HasUnevenRows = true,
- };
- var items = Enumerable.Range (0, 10);
- listview.ItemsSource = items;
- listview.ItemTemplate = new DataTemplate (typeof (MyImageCell));
- Content = listview;
- Title = "Image Cell";
+ if (e.PropertyName == ImageCell.TextProperty.PropertyName)
+ {
+ (sender as ImageCell).Height += 100;
+ ForceUpdateSize();
+ }
}
}
- public class TextCellPage : ContentPage
+ [Preserve(AllMembers = true)]
+ public class MyTextCell : TextCell
{
- [Preserve (AllMembers = true)]
- public class MyTextCell : TextCell
+ VariableHeightItem _DataItem => BindingContext as VariableHeightItem;
+
+ public MyTextCell()
+ {
+ SetBinding(TextProperty, new Binding(nameof(_DataItem.Text)));
+ PropertyChanged += UpdateCell;
+ }
+
+ void UpdateCell(object sender, PropertyChangedEventArgs e)
{
- public MyTextCell ()
+ if (e.PropertyName == TextCell.TextProperty.PropertyName)
{
- Text = "I am a TextCell, short and stout.";
- Height = 20;
- Command = new Command (() =>
- {
- Height += 20;
- ForceUpdateSize ();
- });
+ (sender as TextCell).Height += 100;
+ ForceUpdateSize();
}
}
+ }
+
+ [Preserve(AllMembers = true)]
+ public class MyEntryCell : EntryCell
+ {
+ VariableHeightItem _DataItem => BindingContext as VariableHeightItem;
- public TextCellPage ()
+ public MyEntryCell()
{
- var listview = new ListView {
- HasUnevenRows = true,
- };
- var items = Enumerable.Range (0, 10);
- listview.ItemsSource = items;
- listview.ItemTemplate = new DataTemplate (typeof (MyTextCell));
- Content = listview;
- Title = "Text Cell";
+ SetBinding(TextProperty, new Binding(nameof(_DataItem.Text)));
+ PropertyChanged += UpdateCell;
+ }
+
+ void UpdateCell(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == EntryCell.TextProperty.PropertyName)
+ {
+ (sender as EntryCell).Height += 100;
+ ForceUpdateSize();
+ }
}
}
- public class EntryCellPage : ContentPage
+ [Preserve(AllMembers = true)]
+ public class MySwitchCell : SwitchCell
{
- [Preserve (AllMembers = true)]
- public class MyEntryCell : EntryCell
+ VariableHeightItem _DataItem => BindingContext as VariableHeightItem;
+
+ public MySwitchCell()
+ {
+ SetBinding(TextProperty, new Binding(nameof(_DataItem.Text)));
+ PropertyChanged += UpdateCell;
+ }
+
+ void UpdateCell(object sender, PropertyChangedEventArgs e)
{
- public MyEntryCell ()
+ if (e.PropertyName == SwitchCell.TextProperty.PropertyName)
{
- Text = "I am an EntryCell, short and stout.";
- Height = 20;
- Tapped += (object sender, EventArgs e) =>
- {
- Height += 20;
- ForceUpdateSize ();
- };
- Completed += (object sender, EventArgs e) =>
- {
- Height -= 20;
- ForceUpdateSize ();
- };
+ (sender as SwitchCell).Height += 100;
+ ForceUpdateSize();
}
}
+ }
- public EntryCellPage ()
+ public class MyPage<T> : ContentPage where T : Cell
+ {
+ private List<VariableHeightItem> _DataSource;
+ public MyPage(ListViewCachingStrategy strategy)
{
- var listview = new ListView {
- HasUnevenRows = true,
+ _DataSource = Enumerable.Range(0, 10).Select(n => new VariableHeightItem()).ToList();
+ var listView = new ListView(strategy) { HasUnevenRows = true, ItemsSource = _DataSource, ItemTemplate = new DataTemplate(typeof(T)) };
+ var button = new Button { Text = "Click me" };
+ button.Clicked += async (sender, e) =>
+ {
+ for (int i = 0; i < _DataSource.Count; i++)
+ {
+ var target = _DataSource[i];
+
+ if (Device.RuntimePlatform == Device.iOS)
+ {
+ if (typeof(T) == typeof(MyViewCell))
+ target.Text = "I am an exceptionally long string that should cause the label to wrap, thus increasing the size of the cell such that the entirety of the string is readable by human eyes. Hurrah.";
+ else if (strategy == ListViewCachingStrategy.RetainElement)
+ target.Text = "Look, I'm taller!";
+ else
+ target.Text = $"I'm only taller in {ListViewCachingStrategy.RetainElement} mode. :(";
+ }
+ else
+ {
+ if (typeof(T) == typeof(MyViewCell))
+ target.Text = "I am an exceptionally long string that should cause the label to wrap, thus increasing the size of the cell such that the entirety of the string is readable by human eyes. Hurrah.";
+ else
+ target.Text = "Look, I'm taller!";
+ }
+
+ await Task.Delay(1000);
+ }
};
- var items = Enumerable.Range (0, 10);
- listview.ItemsSource = items;
- listview.ItemTemplate = new DataTemplate (typeof (MyEntryCell));
- Content = listview;
- Title = "Entry Cell";
+
+ Content = new StackLayout { Children = { button, listView } };
+ Title = $"{typeof(T).Name} {strategy}";
}
}
- public class SwitchCellPage : ContentPage
+ class VariableHeightItem : ViewModelBase
{
- [Preserve (AllMembers = true)]
- public class MySwitchCell : SwitchCell
+ public VariableHeightItem()
{
- public MySwitchCell ()
- {
- Text = "I am a SwitchCell, short and stout.";
- Height = 20;
- Tapped += (object sender, EventArgs e) =>
- {
- Height += 20;
- ForceUpdateSize ();
- };
- OnChanged += (object sender, ToggledEventArgs e) =>
- {
- Height -= 20;
- ForceUpdateSize ();
- };
- }
+ Text = "This is a line of text.";
}
- public SwitchCellPage ()
+ public string Text
{
- var listview = new ListView {
- HasUnevenRows = true,
- };
- var items = Enumerable.Range (0, 10);
- listview.ItemsSource = items;
- listview.ItemTemplate = new DataTemplate (typeof (MySwitchCell));
- Content = listview;
- Title = "Switch Cell";
+ get { return GetProperty<string>(); }
+ set { SetProperty(value); }
}
}
- public CellForceUpdateSizeGalleryPage ()
+ public CellForceUpdateSizeGalleryPage()
{
- Children.Add (new ViewCellPage ());
- Children.Add (new ImageCellPage ());
- Children.Add (new TextCellPage ());
- Children.Add (new EntryCellPage ());
- Children.Add (new SwitchCellPage ());
+ var stackLayout = new StackLayout();
+
+ stackLayout.Children.Add(GetButton<MyViewCell>(ListViewCachingStrategy.RetainElement));
+ stackLayout.Children.Add(GetButton<MyImageCell>(ListViewCachingStrategy.RetainElement));
+ stackLayout.Children.Add(GetButton<MyEntryCell>(ListViewCachingStrategy.RetainElement));
+ stackLayout.Children.Add(GetButton<MyTextCell>(ListViewCachingStrategy.RetainElement));
+ stackLayout.Children.Add(GetButton<MySwitchCell>(ListViewCachingStrategy.RetainElement));
+
+ stackLayout.Children.Add(GetButton<MyViewCell>(ListViewCachingStrategy.RecycleElement));
+ stackLayout.Children.Add(GetButton<MyImageCell>(ListViewCachingStrategy.RecycleElement));
+ stackLayout.Children.Add(GetButton<MyEntryCell>(ListViewCachingStrategy.RecycleElement));
+ stackLayout.Children.Add(GetButton<MyTextCell>(ListViewCachingStrategy.RecycleElement));
+ stackLayout.Children.Add(GetButton<MySwitchCell>(ListViewCachingStrategy.RecycleElement));
+
+ Navigation.PushAsync(new ContentPage { Content = stackLayout });
+ }
+
+ Button GetButton<T>(ListViewCachingStrategy strategy) where T : Cell
+ {
+ return new Button
+ {
+ Text = $"{typeof(T).Name} {strategy}",
+ Command = new Command(async () => await Navigation.PushAsync(new MyPage<T>(strategy)))
+ };
}
}
}
diff --git a/Xamarin.Forms.Platform.iOS/Cells/CellRenderer.cs b/Xamarin.Forms.Platform.iOS/Cells/CellRenderer.cs
index ea0e8d3f..0abf7f80 100644
--- a/Xamarin.Forms.Platform.iOS/Cells/CellRenderer.cs
+++ b/Xamarin.Forms.Platform.iOS/Cells/CellRenderer.cs
@@ -48,9 +48,9 @@ namespace Xamarin.Forms.Platform.iOS
{
cell.ForceUpdateSizeRequested -= _onForceUpdateSizeRequested;
- _onForceUpdateSizeRequested = (sender, e) =>
+ _onForceUpdateSizeRequested = (sender, e) =>
{
- var index = tableView.IndexPathForCell(nativeCell);
+ var index = tableView?.IndexPathForCell(nativeCell) ?? (sender as Cell)?.GetIndexPath();
if (index != null)
tableView.ReloadRows(new[] { index }, UITableViewRowAnimation.None);
};