Remove extra properties from CarouselView API (#7456)

* Remove Header/Footer properties from CarouselView

* Limit CarouselView to LinearItemsLayout

* Rework inheritance for UWP

* Split files by class

* Fix up Tizen renderer
This commit is contained in:
E.Z. Hart 2019-09-13 03:55:27 -06:00 коммит произвёл Rui Marinho
Родитель 24fec62cdd
Коммит a68dd21dc0
53 изменённых файлов: 777 добавлений и 549 удалений

Просмотреть файл

@ -53,7 +53,7 @@ namespace Xamarin.Forms.Controls.Issues
};
CV.BindingContext = this;
CV.ItemsLayout = new ListItemsLayout(ItemsLayoutOrientation.Vertical); // Vertical is default
CV.ItemsLayout = new LinearItemsLayout(ItemsLayoutOrientation.Vertical); // Vertical is default
#endif
}

Просмотреть файл

@ -62,9 +62,9 @@ namespace Xamarin.Forms.Controls
return items;
}
internal ListItemsLayout GetCarouselLayout(ItemsLayoutOrientation orientation)
internal LinearItemsLayout GetCarouselLayout(ItemsLayoutOrientation orientation)
{
return new ListItemsLayout(orientation)
return new LinearItemsLayout(orientation)
{
SnapPointsType = SnapPointsType.MandatorySingle,
SnapPointsAlignment = SnapPointsAlignment.Center

Просмотреть файл

@ -20,7 +20,7 @@ namespace Xamarin.Forms.Controls
element.HeightRequest = 250;
element.ItemsLayout = ListItemsLayout.Vertical;
element.ItemsLayout = LinearItemsLayout.Vertical;
}
}
}

Просмотреть файл

@ -34,7 +34,7 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.CarouselVi
}
};
var itemsLayout =
new ListItemsLayout(orientation)
new LinearItemsLayout(orientation)
{
SnapPointsType = SnapPointsType.MandatorySingle,
SnapPointsAlignment = SnapPointsAlignment.Center
@ -71,7 +71,7 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.CarouselVi
var positionControl = new PositionControl(carouselView, nItems);
layout.Children.Add(positionControl);
var spacingModifier = new SpacingModifier(carouselView, "Update Spacing");
var spacingModifier = new SpacingModifier(carouselView.ItemsLayout, "Update Spacing");
layout.Children.Add(spacingModifier);

Просмотреть файл

@ -24,7 +24,7 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.CarouselVi
};
var itemsLayout =
new ListItemsLayout(ItemsLayoutOrientation.Horizontal)
new LinearItemsLayout(ItemsLayoutOrientation.Horizontal)
{
SnapPointsType = SnapPointsType.MandatorySingle,
SnapPointsAlignment = SnapPointsAlignment.Center

Просмотреть файл

@ -17,9 +17,9 @@
{
descriptionLabel,
GalleryBuilder.NavButton("Vertical List (Code)", () =>
new TemplateCodeCollectionViewGallery(ListItemsLayout.Vertical), Navigation),
new TemplateCodeCollectionViewGallery(LinearItemsLayout.Vertical), Navigation),
GalleryBuilder.NavButton("Horizontal List (Code)", () =>
new TemplateCodeCollectionViewGallery(ListItemsLayout.Horizontal), Navigation),
new TemplateCodeCollectionViewGallery(LinearItemsLayout.Horizontal), Navigation),
GalleryBuilder.NavButton("Vertical Grid (Code)", () =>
new TemplateCodeCollectionViewGridGallery (), Navigation),
GalleryBuilder.NavButton("Horizontal Grid (Code)", () =>

Просмотреть файл

@ -22,9 +22,9 @@
// so we can demonstrate switching between them
descriptionLabel,
GalleryBuilder.NavButton("Vertical List (Code)", () =>
new TextCodeCollectionViewGallery(ListItemsLayout.Vertical), Navigation),
new TextCodeCollectionViewGallery(LinearItemsLayout.Vertical), Navigation),
GalleryBuilder.NavButton("Horizontal List (Code)", () =>
new TextCodeCollectionViewGallery(ListItemsLayout.Horizontal), Navigation),
new TextCodeCollectionViewGallery(LinearItemsLayout.Horizontal), Navigation),
GalleryBuilder.NavButton("Vertical Grid (Code)", () =>
new TextCodeCollectionViewGridGallery(), Navigation),
GalleryBuilder.NavButton("Horizontal Grid (Code)", () =>

Просмотреть файл

@ -17,9 +17,9 @@
{
descriptionLabel,
GalleryBuilder.NavButton("Expanding Text (Vertical List)", () =>
new DynamicItemSizeGallery(ListItemsLayout.Vertical), Navigation),
new DynamicItemSizeGallery(LinearItemsLayout.Vertical), Navigation),
GalleryBuilder.NavButton("Expanding Text (Horizontal List)", () =>
new DynamicItemSizeGallery(ListItemsLayout.Horizontal), Navigation),
new DynamicItemSizeGallery(LinearItemsLayout.Horizontal), Navigation),
GalleryBuilder.NavButton("ItemSizing Strategy", () =>
new VariableSizeTemplateGridGallery (ItemsLayoutOrientation.Horizontal), Navigation)
}

Просмотреть файл

@ -21,7 +21,7 @@
IItemsLayout itemsLayout = grid
? new GridItemsLayout(3, orientation)
: new ListItemsLayout(orientation) as IItemsLayout;
: new LinearItemsLayout(orientation) as IItemsLayout;
var itemTemplate = ExampleTemplates.PhotoTemplate();

Просмотреть файл

@ -20,7 +20,7 @@
var itemsLayout = grid
? new GridItemsLayout(3, orientation)
: new ListItemsLayout(orientation) as IItemsLayout;
: new LinearItemsLayout(orientation) as IItemsLayout;
var itemTemplate = ExampleTemplates.PhotoTemplate();

Просмотреть файл

@ -17,10 +17,10 @@
{
descriptionLabel,
GalleryBuilder.NavButton("Propagate FlowDirection", () =>
new PropagateCodeGallery(ListItemsLayout.Vertical), Navigation),
new PropagateCodeGallery(LinearItemsLayout.Vertical), Navigation),
GalleryBuilder.NavButton("Propagate FlowDirection in EmptyView", () =>
new PropagateCodeGallery(ListItemsLayout.Vertical, 0), Navigation),
new PropagateCodeGallery(LinearItemsLayout.Vertical, 0), Navigation),
}
}
};

Просмотреть файл

@ -20,7 +20,7 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.ScrollMode
InitializeComponent();
_collectionView = createCollectionView == null ? new CollectionView() : createCollectionView();
_collectionView.ItemsLayout = itemsLayout ?? ListItemsLayout.Vertical;
_collectionView.ItemsLayout = itemsLayout ?? LinearItemsLayout.Vertical;
var scrollModeSelector = new EnumSelector<ItemsUpdatingScrollMode>(() => _collectionView.ItemsUpdatingScrollMode,
mode => _collectionView.ItemsUpdatingScrollMode = mode, "SelectScrollMode");

Просмотреть файл

@ -19,9 +19,9 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries
{
descriptionLabel,
GalleryBuilder.NavButton("ScrollTo Index (Code, Horizontal List)", () =>
new ScrollToCodeGallery(ListItemsLayout.Horizontal), Navigation),
new ScrollToCodeGallery(LinearItemsLayout.Horizontal), Navigation),
GalleryBuilder.NavButton("ScrollTo Index (Code, Vertical List)", () =>
new ScrollToCodeGallery(ListItemsLayout.Vertical), Navigation),
new ScrollToCodeGallery(LinearItemsLayout.Vertical), Navigation),
GalleryBuilder.NavButton("ScrollTo Index (Code, Horizontal Grid)", () =>
new ScrollToCodeGallery(new GridItemsLayout(3, ItemsLayoutOrientation.Horizontal)),
Navigation),
@ -30,10 +30,10 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries
Navigation),
GalleryBuilder.NavButton("ScrollTo Item (Code, Horizontal List)", () =>
new ScrollToCodeGallery(ListItemsLayout.Horizontal, ScrollToMode.Element,
new ScrollToCodeGallery(LinearItemsLayout.Horizontal, ScrollToMode.Element,
ExampleTemplates.ScrollToItemTemplate), Navigation),
GalleryBuilder.NavButton("ScrollTo Item (Code, Vertical List)", () =>
new ScrollToCodeGallery(ListItemsLayout.Vertical, ScrollToMode.Element,
new ScrollToCodeGallery(LinearItemsLayout.Vertical, ScrollToMode.Element,
ExampleTemplates.ScrollToItemTemplate), Navigation),
GalleryBuilder.NavButton("ScrollTo Item (Code, Horizontal Grid)", () =>
new ScrollToCodeGallery(new GridItemsLayout(3, ItemsLayoutOrientation.Horizontal),

Просмотреть файл

@ -19,9 +19,9 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries
{
descriptionLabel,
GalleryBuilder.NavButton("Snap Points (Code, Horizontal List)", () =>
new SnapPointsCodeGallery(ListItemsLayout.Horizontal as ItemsLayout), Navigation),
new SnapPointsCodeGallery(LinearItemsLayout.Horizontal as ItemsLayout), Navigation),
GalleryBuilder.NavButton("Snap Points (Code, Vertical List)", () =>
new SnapPointsCodeGallery(ListItemsLayout.Vertical as ItemsLayout), Navigation),
new SnapPointsCodeGallery(LinearItemsLayout.Vertical as ItemsLayout), Navigation),
GalleryBuilder.NavButton("Snap Points (Code, Horizontal Grid)", () =>
new SnapPointsCodeGallery(new GridItemsLayout(2, ItemsLayoutOrientation.Horizontal)), Navigation),
GalleryBuilder.NavButton("Snap Points (Code, Vertical Grid)", () =>

Просмотреть файл

@ -17,9 +17,9 @@
{
descriptionLabel,
GalleryBuilder.NavButton("Vertical List Spacing", () =>
new SpacingGallery (ListItemsLayout.Vertical), Navigation),
new SpacingGallery (LinearItemsLayout.Vertical), Navigation),
GalleryBuilder.NavButton("Horizontal List Spacing", () =>
new SpacingGallery (ListItemsLayout.Horizontal), Navigation),
new SpacingGallery (LinearItemsLayout.Horizontal), Navigation),
GalleryBuilder.NavButton("Vertical Grid Spacing", () =>
new SpacingGallery (new GridItemsLayout(3, ItemsLayoutOrientation.Vertical)), Navigation),
GalleryBuilder.NavButton("Horizontal Grid Spacing", () =>

Просмотреть файл

@ -36,7 +36,7 @@
};
var generator = new ItemsSourceGenerator(collectionView, initialItems: 20);
var spacingModifier = new SpacingModifier(collectionView, "Update Spacing");
var spacingModifier = new SpacingModifier(collectionView.ItemsLayout, "Update Spacing");
layout.Children.Add(generator);
layout.Children.Add(instructions);

Просмотреть файл

@ -4,12 +4,12 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.SpacingGal
{
internal class SpacingModifier : ContentView
{
protected readonly ItemsView _cv;
protected readonly Entry Entry;
protected readonly IItemsLayout ItemsLayout;
public SpacingModifier(ItemsView cv, string buttonText)
public SpacingModifier(IItemsLayout itemsLayout, string buttonText)
{
_cv = cv;
ItemsLayout = itemsLayout;
var layout = new StackLayout
{
@ -38,7 +38,7 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.SpacingGal
protected virtual string LabelText => "Spacing:";
protected virtual string InitialEntryText => _cv.ItemsLayout is GridItemsLayout ? "0, 0" : "0";
protected virtual string InitialEntryText => ItemsLayout is GridItemsLayout ? "0, 0" : "0";
protected virtual void OnButtonClicked()
{
@ -47,11 +47,11 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.SpacingGal
return;
}
if (_cv.ItemsLayout is ListItemsLayout listItemsLayout)
if (ItemsLayout is LinearItemsLayout listItemsLayout)
{
listItemsLayout.ItemSpacing = indexes[0];
}
else if (_cv.ItemsLayout is GridItemsLayout gridItemsLayout)
else if (ItemsLayout is GridItemsLayout gridItemsLayout)
{
gridItemsLayout.VerticalItemSpacing = indexes[0];
gridItemsLayout.HorizontalItemSpacing = indexes[1];
@ -60,7 +60,7 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.SpacingGal
protected virtual bool ParseIndexes(out int[] indexes)
{
if (_cv.ItemsLayout is ListItemsLayout listItemsLayout)
if (ItemsLayout is LinearItemsLayout listItemsLayout)
{
return IndexParser.ParseIndexes(Entry.Text, 1, out indexes);
}

Просмотреть файл

@ -26,7 +26,7 @@ namespace Xamarin.Forms.Core.UnitTests
[Test]
public void VerticalListMeasurement()
{
var itemsView = new ItemsView();
var itemsView = new StructuredItemsView();
var sizeRequest = itemsView.Measure(double.PositiveInfinity, double.PositiveInfinity);
@ -37,9 +37,9 @@ namespace Xamarin.Forms.Core.UnitTests
[Test]
public void HorizontalListMeasurement()
{
var itemsView = new ItemsView();
var itemsView = new StructuredItemsView();
itemsView.ItemsLayout = new ListItemsLayout(ItemsLayoutOrientation.Horizontal);
itemsView.ItemsLayout = new LinearItemsLayout(ItemsLayoutOrientation.Horizontal);
var sizeRequest = itemsView.Measure(double.PositiveInfinity, double.PositiveInfinity);

Просмотреть файл

@ -154,13 +154,23 @@ namespace Xamarin.Forms
set => SetValue(PositionChangedCommandParameterProperty, value);
}
public static readonly BindableProperty ItemsLayoutProperty =
BindableProperty.Create(nameof(ItemsLayout), typeof(LinearItemsLayout), typeof(ItemsView),
LinearItemsLayout.Horizontal);
public LinearItemsLayout ItemsLayout
{
get => (LinearItemsLayout)InternalItemsLayout;
set => InternalItemsLayout = value;
}
public event EventHandler<CurrentItemChangedEventArgs> CurrentItemChanged;
public event EventHandler<PositionChangedEventArgs> PositionChanged;
public CarouselView()
{
CollectionView.VerifyCollectionViewFlagEnabled(constructorHint: nameof(CarouselView));
ItemsLayout = new ListItemsLayout(ItemsLayoutOrientation.Horizontal)
ItemsLayout = new LinearItemsLayout(ItemsLayoutOrientation.Horizontal)
{
SnapPointsType = SnapPointsType.MandatorySingle,
SnapPointsAlignment = SnapPointsAlignment.Center

Просмотреть файл

@ -9,12 +9,12 @@ namespace Xamarin.Forms
{
if (value == "HorizontalList")
{
return ListItemsLayout.Horizontal;
return LinearItemsLayout.Horizontal;
}
if (value == "VerticalList")
{
return ListItemsLayout.Vertical;
return LinearItemsLayout.Vertical;
}
throw new InvalidOperationException($"Cannot convert \"{value}\" into {typeof(IItemsLayout)}");

Просмотреть файл

@ -7,7 +7,7 @@ using Xamarin.Forms.Internals;
namespace Xamarin.Forms
{
public class ItemsView : View
public abstract class ItemsView : View
{
List<Element> _logicalChildren = new List<Element>();
@ -37,13 +37,13 @@ namespace Xamarin.Forms
public static readonly BindableProperty ItemsSourceProperty =
BindableProperty.Create(nameof(ItemsSource), typeof(IEnumerable), typeof(ItemsView), null);
public IEnumerable ItemsSource
public IEnumerable ItemsSource
{
get => (IEnumerable)GetValue(ItemsSourceProperty);
set => SetValue(ItemsSourceProperty, value);
}
public static readonly BindableProperty RemainingItemsThresholdReachedCommandProperty =
public static readonly BindableProperty RemainingItemsThresholdReachedCommandProperty =
BindableProperty.Create(nameof(RemainingItemsThresholdReachedCommand), typeof(ICommand), typeof(ItemsView), null);
public ICommand RemainingItemsThresholdReachedCommand
@ -93,47 +93,11 @@ namespace Xamarin.Forms
set => SetValue(RemainingItemsThresholdProperty, value);
}
public static readonly BindableProperty HeaderProperty =
BindableProperty.Create(nameof(Header), typeof(object), typeof(ItemsView), null);
public object Header
{
get => GetValue(HeaderProperty);
set => SetValue(HeaderProperty, value);
}
public static readonly BindableProperty HeaderTemplateProperty =
BindableProperty.Create(nameof(HeaderTemplate), typeof(DataTemplate), typeof(ItemsView), null);
public DataTemplate HeaderTemplate
{
get => (DataTemplate)GetValue(HeaderTemplateProperty);
set => SetValue(HeaderTemplateProperty, value);
}
public static readonly BindableProperty FooterProperty =
BindableProperty.Create(nameof(Footer), typeof(object), typeof(ItemsView), null);
public object Footer
{
get => GetValue(FooterProperty);
set => SetValue(FooterProperty, value);
}
public static readonly BindableProperty FooterTemplateProperty =
BindableProperty.Create(nameof(FooterTemplate), typeof(DataTemplate), typeof(ItemsView), null);
public DataTemplate FooterTemplate
{
get => (DataTemplate)GetValue(FooterTemplateProperty);
set => SetValue(FooterTemplateProperty, value);
}
public void AddLogicalChild(Element element)
{
if(element == null)
if (element == null)
{
return;
return;
}
_logicalChildren.Add(element);
@ -162,23 +126,18 @@ namespace Xamarin.Forms
internal override ReadOnlyCollection<Element> LogicalChildrenInternal => _logicalChildren.AsReadOnly();
#endif
public static readonly BindableProperty ItemsLayoutProperty =
BindableProperty.Create(nameof(ItemsLayout), typeof(IItemsLayout), typeof(ItemsView),
ListItemsLayout.Vertical);
internal static readonly BindableProperty InternalItemsLayoutProperty =
BindableProperty.Create(nameof(ItemsLayout), typeof(IItemsLayout), typeof(ItemsView),
LinearItemsLayout.Vertical);
public IItemsLayout ItemsLayout
// public abstract IItemsLayout ItemsLayout { get; }
protected IItemsLayout InternalItemsLayout
{
get => (IItemsLayout)GetValue(ItemsLayoutProperty);
set => SetValue(ItemsLayoutProperty, value);
}
public static readonly BindableProperty ItemTemplateProperty =
BindableProperty.Create(nameof(ItemTemplate), typeof(DataTemplate), typeof(ItemsView));
public DataTemplate ItemTemplate
{
get => (DataTemplate)GetValue(ItemTemplateProperty);
set => SetValue(ItemTemplateProperty, value);
get => (IItemsLayout)GetValue(InternalItemsLayoutProperty);
set => SetValue(InternalItemsLayoutProperty, value);
}
public static readonly BindableProperty ItemSizingStrategyProperty =
@ -190,6 +149,16 @@ namespace Xamarin.Forms
set => SetValue(ItemSizingStrategyProperty, value);
}
public static readonly BindableProperty ItemTemplateProperty =
BindableProperty.Create(nameof(ItemTemplate), typeof(DataTemplate), typeof(ItemsView));
public DataTemplate ItemTemplate
{
get => (DataTemplate)GetValue(ItemTemplateProperty);
set => SetValue(ItemTemplateProperty, value);
}
public static readonly BindableProperty ItemsUpdatingScrollModeProperty =
BindableProperty.Create(nameof(ItemsUpdatingScrollMode), typeof(ItemsUpdatingScrollMode), typeof(ItemsView),
default(ItemsUpdatingScrollMode));

Просмотреть файл

@ -2,19 +2,19 @@
namespace Xamarin.Forms
{
public class ListItemsLayout : ItemsLayout
public class LinearItemsLayout : ItemsLayout
{
public ListItemsLayout([Parameter("Orientation")] ItemsLayoutOrientation orientation) : base(orientation)
public LinearItemsLayout([Parameter("Orientation")] ItemsLayoutOrientation orientation) : base(orientation)
{
}
public static readonly IItemsLayout Vertical = new ListItemsLayout(ItemsLayoutOrientation.Vertical);
public static readonly IItemsLayout Horizontal = new ListItemsLayout(ItemsLayoutOrientation.Horizontal);
public static readonly IItemsLayout Vertical = new LinearItemsLayout(ItemsLayoutOrientation.Vertical);
public static readonly IItemsLayout Horizontal = new LinearItemsLayout(ItemsLayoutOrientation.Horizontal);
// TODO hartez 2018/08/29 20:31:54 Need something like these previous two, but as a carousel default
public static readonly BindableProperty ItemSpacingProperty =
BindableProperty.Create(nameof(ItemSpacing), typeof(double), typeof(ListItemsLayout), default(double),
BindableProperty.Create(nameof(ItemSpacing), typeof(double), typeof(LinearItemsLayout), default(double),
validateValue: (bindable, value) => (double)value >= 0);
public double ItemSpacing

Просмотреть файл

@ -4,7 +4,7 @@ using System.Windows.Input;
namespace Xamarin.Forms
{
public class SelectableItemsView : ItemsView
public class SelectableItemsView : StructuredItemsView
{
public static readonly BindableProperty SelectionModeProperty =
BindableProperty.Create(nameof(SelectionMode), typeof(SelectionMode), typeof(SelectableItemsView),

Просмотреть файл

@ -0,0 +1,51 @@
namespace Xamarin.Forms
{
public class StructuredItemsView : ItemsView
{
public static readonly BindableProperty HeaderProperty =
BindableProperty.Create(nameof(Header), typeof(object), typeof(ItemsView), null);
public object Header
{
get => GetValue(HeaderProperty);
set => SetValue(HeaderProperty, value);
}
public static readonly BindableProperty HeaderTemplateProperty =
BindableProperty.Create(nameof(HeaderTemplate), typeof(DataTemplate), typeof(ItemsView), null);
public DataTemplate HeaderTemplate
{
get => (DataTemplate)GetValue(HeaderTemplateProperty);
set => SetValue(HeaderTemplateProperty, value);
}
public static readonly BindableProperty FooterProperty =
BindableProperty.Create(nameof(Footer), typeof(object), typeof(ItemsView), null);
public object Footer
{
get => GetValue(FooterProperty);
set => SetValue(FooterProperty, value);
}
public static readonly BindableProperty FooterTemplateProperty =
BindableProperty.Create(nameof(FooterTemplate), typeof(DataTemplate), typeof(ItemsView), null);
public DataTemplate FooterTemplate
{
get => (DataTemplate)GetValue(FooterTemplateProperty);
set => SetValue(FooterTemplateProperty, value);
}
public static readonly BindableProperty ItemsLayoutProperty =
BindableProperty.Create(nameof(ItemsLayout), typeof(IItemsLayout), typeof(ItemsView),
LinearItemsLayout.Vertical);
public IItemsLayout ItemsLayout
{
get => InternalItemsLayout;
set => InternalItemsLayout = value;
}
}
}

Просмотреть файл

@ -24,7 +24,7 @@ namespace Xamarin.Forms.Platform.Android
_horizontalSpacing = gridItemsLayout.HorizontalItemSpacing;
_verticalSpacing = gridItemsLayout.VerticalItemSpacing;
break;
case ListItemsLayout listItemsLayout:
case LinearItemsLayout listItemsLayout:
_orientation = listItemsLayout.Orientation;
if (_orientation == ItemsLayoutOrientation.Horizontal)
_horizontalSpacing = listItemsLayout.ItemSpacing;

Просмотреть файл

@ -39,16 +39,16 @@ namespace Xamarin.Forms.Platform.Android
protected override void SetUpNewElement(ItemsView newElement)
{
Carousel = newElement as CarouselView;
base.SetUpNewElement(newElement);
if (newElement == null)
{
Carousel = null;
return;
}
Carousel = newElement as CarouselView;
_layout = ItemsView.ItemsLayout;
_layout = Carousel.ItemsLayout;
UpdateIsSwipeEnabled();
UpdateInitialPosition();
@ -68,7 +68,7 @@ namespace Xamarin.Forms.Platform.Android
UpdateIsSwipeEnabled();
else if (changedProperty.Is(CarouselView.IsBounceEnabledProperty))
UpdateIsBounceEnabled();
else if (changedProperty.Is(ListItemsLayout.ItemSpacingProperty))
else if (changedProperty.Is(LinearItemsLayout.ItemSpacingProperty))
UpdateItemSpacing();
}
@ -131,11 +131,17 @@ namespace Xamarin.Forms.Platform.Android
base.UpdateItemSpacing();
}
protected override IItemsLayout GetItemsLayout()
{
return Carousel.ItemsLayout;
}
int GetItemWidth()
{
var itemWidth = Width;
if (_layout is ListItemsLayout listItemsLayout && listItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal)
if (_layout is LinearItemsLayout listItemsLayout && listItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal)
{
var numberOfVisibleItems = Carousel.NumberOfSideItems * 2 + 1;
itemWidth = (int)(Width - Carousel.PeekAreaInsets.Left - Carousel.PeekAreaInsets.Right - Context?.ToPixels(listItemsLayout.ItemSpacing)) / numberOfVisibleItems;
@ -148,7 +154,7 @@ namespace Xamarin.Forms.Platform.Android
{
var itemHeight = Height;
if (_layout is ListItemsLayout listItemsLayout && listItemsLayout.Orientation == ItemsLayoutOrientation.Vertical)
if (_layout is LinearItemsLayout listItemsLayout && listItemsLayout.Orientation == ItemsLayoutOrientation.Vertical)
{
var numberOfVisibleItems = Carousel.NumberOfSideItems * 2 + 1;
itemHeight = (int)(Height - Carousel.PeekAreaInsets.Top - Carousel.PeekAreaInsets.Bottom - Context?.ToPixels(listItemsLayout.ItemSpacing)) / numberOfVisibleItems;

Просмотреть файл

@ -33,9 +33,6 @@ namespace Xamarin.Forms.Platform.Android
_createItemContentView = createItemContentView;
ItemsSource = CreateItemsSource();
UpdateHasHeader();
UpdateHasFooter();
if (_createItemContentView == null)
{
_createItemContentView = (view, context) => new ItemContentView(context);
@ -53,18 +50,10 @@ namespace Xamarin.Forms.Platform.Android
{
UpdateItemsSource();
}
else if (property.Is(Xamarin.Forms.ItemsView.HeaderProperty))
{
UpdateHasHeader();
}
else if (property.Is(Xamarin.Forms.ItemsView.ItemTemplateProperty))
{
UpdateUsingItemTemplate();
}
else if (property.Is(Xamarin.Forms.ItemsView.FooterProperty))
{
UpdateHasFooter();
}
}
public override void OnViewRecycled(Object holder)
@ -79,26 +68,6 @@ namespace Xamarin.Forms.Platform.Android
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
if (IsHeader(position))
{
if (holder is TemplatedItemViewHolder templatedItemViewHolder)
{
BindTemplatedItemViewHolder(templatedItemViewHolder, ItemsView.Header);
}
return;
}
if (IsFooter(position))
{
if (holder is TemplatedItemViewHolder templatedItemViewHolder)
{
BindTemplatedItemViewHolder(templatedItemViewHolder, ItemsView.Footer);
}
return;
}
switch (holder)
{
case TextViewHolder textViewHolder:
@ -114,16 +83,6 @@ namespace Xamarin.Forms.Platform.Android
{
var context = parent.Context;
if (viewType == ItemViewType.Header)
{
return CreateHeaderFooterViewHolder(ItemsView.Header, ItemsView.HeaderTemplate, context);
}
if (viewType == ItemViewType.Footer)
{
return CreateHeaderFooterViewHolder(ItemsView.Footer, ItemsView.FooterTemplate, context);
}
if (viewType == ItemViewType.TextItem)
{
var view = new TextView(context);
@ -139,16 +98,6 @@ namespace Xamarin.Forms.Platform.Android
public override int GetItemViewType(int position)
{
if (IsHeader(position))
{
return ItemViewType.Header;
}
if (IsFooter(position))
{
return ItemViewType.Footer;
}
if (_usingItemTemplate)
{
return ItemViewType.TemplatedItem;
@ -207,42 +156,5 @@ namespace Xamarin.Forms.Platform.Android
{
_usingItemTemplate = ItemsView.ItemTemplate != null;
}
void UpdateHasHeader()
{
ItemsSource.HasHeader = ItemsView.Header != null;
}
void UpdateHasFooter()
{
ItemsSource.HasFooter = ItemsView.Footer != null;
}
bool IsHeader(int position)
{
return ItemsSource.IsHeader(position);
}
bool IsFooter(int position)
{
return ItemsSource.IsFooter(position);
}
protected RecyclerView.ViewHolder CreateHeaderFooterViewHolder(object content, DataTemplate template, Context context)
{
if (template != null)
{
var footerContentView = new ItemContentView(context);
return new TemplatedItemViewHolder(footerContentView, template, isSelectionEnabled: false);
}
if (content is View formsView)
{
return SimpleViewHolder.FromFormsView(formsView, context);
}
// No template, Footer is not a Forms View, so just display Footer.ToString
return SimpleViewHolder.FromText(content?.ToString(), context, fill: false);
}
}
}

Просмотреть файл

@ -11,7 +11,7 @@ using AViewCompat = Android.Support.V4.View.ViewCompat;
namespace Xamarin.Forms.Platform.Android
{
public class ItemsViewRenderer<TItemsView, TAdapter, TItemsViewSource> : RecyclerView, IVisualElementRenderer, IEffectControlProvider
public abstract class ItemsViewRenderer<TItemsView, TAdapter, TItemsViewSource> : RecyclerView, IVisualElementRenderer, IEffectControlProvider
where TItemsView : ItemsView
where TAdapter : ItemsViewAdapter<TItemsView, TItemsViewSource>
where TItemsViewSource : IItemsViewSource
@ -56,8 +56,6 @@ namespace Xamarin.Forms.Platform.Android
ScrollHelper ScrollHelper => _scrollHelper = _scrollHelper ?? new ScrollHelper(this);
// TODO hartez 2018/10/24 19:27:12 Region all the interface implementations
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
@ -167,7 +165,7 @@ namespace Xamarin.Forms.Platform.Android
{
case GridItemsLayout gridItemsLayout:
return CreateGridLayout(gridItemsLayout);
case ListItemsLayout listItemsLayout:
case LinearItemsLayout listItemsLayout:
var orientation = listItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal
? LinearLayoutManager.Horizontal
: LinearLayoutManager.Vertical;
@ -305,7 +303,7 @@ namespace Xamarin.Forms.Platform.Android
UpdateItemsSource();
_layout = ItemsView.ItemsLayout;
_layout = GetItemsLayout();
SetLayoutManager(SelectLayoutManager(_layout));
UpdateSnapBehavior();
@ -329,6 +327,8 @@ namespace Xamarin.Forms.Platform.Android
AddOnScrollListener(_recyclerViewScrollListener);
}
protected abstract IItemsLayout GetItemsLayout();
protected virtual void UpdateVerticalScrollBarVisibility()
{
if (_defaultVerticalScrollVisibility == ScrollBarVisibility.Default)
@ -420,7 +420,7 @@ namespace Xamarin.Forms.Platform.Android
{
UpdateSnapBehavior();
}
else if (propertyChanged.IsOneOf(ListItemsLayout.ItemSpacingProperty,
else if (propertyChanged.IsOneOf(LinearItemsLayout.ItemSpacingProperty,
GridItemsLayout.HorizontalItemSpacingProperty, GridItemsLayout.VerticalItemSpacingProperty))
{
UpdateItemSpacing();
@ -438,7 +438,7 @@ namespace Xamarin.Forms.Platform.Android
{
if (_snapManager == null)
{
_snapManager = new SnapManager(ItemsView, this);
_snapManager = new SnapManager(_layout, this);
}
return _snapManager;
}

Просмотреть файл

@ -6,7 +6,7 @@ using Object = Java.Lang.Object;
namespace Xamarin.Forms.Platform.Android
{
public class SelectableItemsViewAdapter<TItemsView, TItemsSource> : ItemsViewAdapter<TItemsView, TItemsSource>
public class SelectableItemsViewAdapter<TItemsView, TItemsSource> : StructuredItemsViewAdapter<TItemsView, TItemsSource>
where TItemsView : SelectableItemsView
where TItemsSource : IItemsViewSource
{

Просмотреть файл

@ -4,7 +4,7 @@ using Android.Content;
namespace Xamarin.Forms.Platform.Android
{
public class SelectableItemsViewRenderer<TItemsView, TAdapter, TItemsViewSource> : ItemsViewRenderer<TItemsView, TAdapter, TItemsViewSource>
public class SelectableItemsViewRenderer<TItemsView, TAdapter, TItemsViewSource> : StructuredItemsViewRenderer<TItemsView, TAdapter, TItemsViewSource>
where TItemsView : SelectableItemsView
where TAdapter : SelectableItemsViewAdapter<TItemsView, TItemsViewSource>
where TItemsViewSource : IItemsViewSource

Просмотреть файл

@ -5,20 +5,20 @@ namespace Xamarin.Forms.Platform.Android
{
public class SnapManager : IDisposable
{
readonly IItemsLayout _itemsLayout;
readonly RecyclerView _recyclerView;
readonly ItemsView _itemsView;
SnapHelper _snapHelper;
public SnapManager(ItemsView itemsView, RecyclerView recyclerView)
public SnapManager(IItemsLayout itemsLayout, RecyclerView recyclerView)
{
Xamarin.Forms.CollectionView.VerifyCollectionViewFlagEnabled(nameof(SnapManager));
_itemsLayout = itemsLayout;
_recyclerView = recyclerView;
_itemsView = itemsView;
}
internal void UpdateSnapBehavior()
{
if (!(_itemsView.ItemsLayout is ItemsLayout itemsLayout))
if (!(_itemsLayout is ItemsLayout itemsLayout))
{
return;
}

Просмотреть файл

@ -27,7 +27,7 @@ namespace Xamarin.Forms.Platform.Android
_horizontalSpacing = gridItemsLayout.HorizontalItemSpacing;
_verticalSpacing = gridItemsLayout.VerticalItemSpacing;
break;
case ListItemsLayout listItemsLayout:
case LinearItemsLayout listItemsLayout:
_orientation = listItemsLayout.Orientation;
if (_orientation == ItemsLayoutOrientation.Horizontal)
_horizontalSpacing = listItemsLayout.ItemSpacing;

Просмотреть файл

@ -0,0 +1,128 @@
using System;
using System.ComponentModel;
using Android.Content;
using Android.Support.V7.Widget;
using ViewGroup = Android.Views.ViewGroup;
namespace Xamarin.Forms.Platform.Android
{
public class StructuredItemsViewAdapter<TItemsView, TItemsViewSource> : ItemsViewAdapter<TItemsView, TItemsViewSource>
where TItemsView : StructuredItemsView
where TItemsViewSource : IItemsViewSource
{
internal StructuredItemsViewAdapter(TItemsView itemsView,
Func<View, Context, ItemContentView> createItemContentView = null) : base(itemsView, createItemContentView)
{
UpdateHasHeader();
UpdateHasFooter();
}
protected override void ItemsViewPropertyChanged(object sender, PropertyChangedEventArgs property)
{
base.ItemsViewPropertyChanged(sender, property);
if (property.Is(Xamarin.Forms.StructuredItemsView.HeaderProperty))
{
UpdateHasHeader();
}
else if (property.Is(Xamarin.Forms.StructuredItemsView.FooterProperty))
{
UpdateHasFooter();
}
}
public override int GetItemViewType(int position)
{
if (IsHeader(position))
{
return ItemViewType.Header;
}
if (IsFooter(position))
{
return ItemViewType.Footer;
}
return base.GetItemViewType(position);
}
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
var context = parent.Context;
if (viewType == ItemViewType.Header)
{
return CreateHeaderFooterViewHolder(ItemsView.Header, ItemsView.HeaderTemplate, context);
}
if (viewType == ItemViewType.Footer)
{
return CreateHeaderFooterViewHolder(ItemsView.Footer, ItemsView.FooterTemplate, context);
}
return base.OnCreateViewHolder(parent, viewType);
}
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
if (IsHeader(position))
{
if (holder is TemplatedItemViewHolder templatedItemViewHolder)
{
BindTemplatedItemViewHolder(templatedItemViewHolder, ItemsView.Header);
}
return;
}
if (IsFooter(position))
{
if (holder is TemplatedItemViewHolder templatedItemViewHolder)
{
BindTemplatedItemViewHolder(templatedItemViewHolder, ItemsView.Footer);
}
return;
}
base.OnBindViewHolder(holder, position);
}
void UpdateHasHeader()
{
ItemsSource.HasHeader = ItemsView.Header != null;
}
void UpdateHasFooter()
{
ItemsSource.HasFooter = ItemsView.Footer != null;
}
bool IsHeader(int position)
{
return ItemsSource.IsHeader(position);
}
bool IsFooter(int position)
{
return ItemsSource.IsFooter(position);
}
protected RecyclerView.ViewHolder CreateHeaderFooterViewHolder(object content, DataTemplate template, Context context)
{
if (template != null)
{
var footerContentView = new ItemContentView(context);
return new TemplatedItemViewHolder(footerContentView, template, isSelectionEnabled: false);
}
if (content is View formsView)
{
return SimpleViewHolder.FromFormsView(formsView, context);
}
// No template, Footer is not a Forms View, so just display Footer.ToString
return SimpleViewHolder.FromText(content?.ToString(), context, fill: false);
}
}
}

Просмотреть файл

@ -0,0 +1,33 @@
using Android.Content;
namespace Xamarin.Forms.Platform.Android
{
public class StructuredItemsViewRenderer<TItemsView, TAdapter, TItemsViewSource> : ItemsViewRenderer<TItemsView, TAdapter, TItemsViewSource>
where TItemsView : StructuredItemsView
where TAdapter : StructuredItemsViewAdapter<TItemsView, TItemsViewSource>
where TItemsViewSource : IItemsViewSource
{
StructuredItemsView _itemsView;
public StructuredItemsViewRenderer(Context context) : base(context)
{
}
protected override TAdapter CreateAdapter()
{
return (TAdapter)new StructuredItemsViewAdapter<TItemsView, TItemsViewSource>(ItemsView);
}
protected override void SetUpNewElement(TItemsView newElement)
{
_itemsView = newElement;
base.SetUpNewElement(newElement);
}
protected override IItemsLayout GetItemsLayout()
{
return _itemsView.ItemsLayout;
}
}
}

Просмотреть файл

@ -102,6 +102,8 @@
<Compile Include="CollectionView\SpacingItemDecoration.cs" />
<Compile Include="CollectionView\StartSingleSnapHelper.cs" />
<Compile Include="CollectionView\StartSnapHelper.cs" />
<Compile Include="CollectionView\StructuredItemsViewAdapter.cs" />
<Compile Include="CollectionView\StructuredItemsViewRenderer.cs" />
<Compile Include="CollectionView\TemplatedItemViewHolder.cs" />
<Compile Include="CollectionView\TextViewHolder.cs" />
<Compile Include="CollectionView\ItemViewType.cs" />

Просмотреть файл

@ -5,7 +5,7 @@ using Xamarin.Forms.Platform.Tizen.Native;
namespace Xamarin.Forms.Platform.Tizen
{
public class ItemsViewRenderer : ViewRenderer<ItemsView, Native.CollectionView>
public class ItemsViewRenderer : ViewRenderer<StructuredItemsView, Native.CollectionView>
{
INotifyCollectionChanged _observableSource;
@ -13,13 +13,13 @@ namespace Xamarin.Forms.Platform.Tizen
{
RegisterPropertyHandler(ItemsView.ItemsSourceProperty, UpdateItemsSource);
RegisterPropertyHandler(ItemsView.ItemTemplateProperty, UpdateAdaptor);
RegisterPropertyHandler(ItemsView.ItemsLayoutProperty, UpdateItemsLayout);
RegisterPropertyHandler(StructuredItemsView.ItemsLayoutProperty, UpdateItemsLayout);
RegisterPropertyHandler(ItemsView.ItemSizingStrategyProperty, UpdateSizingStrategy);
RegisterPropertyHandler(SelectableItemsView.SelectedItemProperty, UpdateSelectedItem);
RegisterPropertyHandler(SelectableItemsView.SelectionModeProperty, UpdateSelectionMode);
}
protected override void OnElementChanged(ElementChangedEventArgs<ItemsView> e)
protected override void OnElementChanged(ElementChangedEventArgs<StructuredItemsView> e)
{
if (Control == null)
{
@ -178,7 +178,7 @@ namespace Xamarin.Forms.Platform.Tizen
{
switch (layout)
{
case ListItemsLayout listItemsLayout:
case LinearItemsLayout listItemsLayout:
return new LinearLayoutManager(listItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal, sizing);
case GridItemsLayout gridItemsLayout:
return new GridLayoutManager(gridItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal, gridItemsLayout.Span, sizing);

Просмотреть файл

@ -17,20 +17,16 @@ using UWPDataTemplate = Windows.UI.Xaml.DataTemplate;
namespace Xamarin.Forms.Platform.UWP
{
public class ItemsViewRenderer : ViewRenderer<ItemsView, ListViewBase>
public abstract class ItemsViewRenderer : ViewRenderer<ItemsView, ListViewBase>
{
IItemsLayout _layout;
CollectionViewSource _collectionViewSource;
protected ListViewBase ListViewBase { get; private set; }
UwpScrollBarVisibility? _defaultHorizontalScrollVisibility;
UwpScrollBarVisibility? _defaultVerticalScrollVisibility;
UWPDataTemplate ViewTemplate => (UWPDataTemplate)UWPApp.Current.Resources["View"];
UWPDataTemplate ItemsViewTemplate => (UWPDataTemplate)UWPApp.Current.Resources["ItemsViewDefaultTemplate"];
View _currentHeader;
View _currentFooter;
protected UWPDataTemplate ViewTemplate => (UWPDataTemplate)UWPApp.Current.Resources["View"];
protected UWPDataTemplate ItemsViewTemplate => (UWPDataTemplate)UWPApp.Current.Resources["ItemsViewDefaultTemplate"];
protected ItemsControl ItemsControl { get; private set; }
@ -53,7 +49,7 @@ namespace Xamarin.Forms.Platform.UWP
{
UpdateItemTemplate();
}
else if(changedProperty.Is(ItemsView.HorizontalScrollBarVisibilityProperty))
else if (changedProperty.Is(ItemsView.HorizontalScrollBarVisibilityProperty))
{
UpdateHorizontalScrollBarVisibility();
}
@ -61,30 +57,11 @@ namespace Xamarin.Forms.Platform.UWP
{
UpdateVerticalScrollBarVisibility();
}
else if (changedProperty.IsOneOf(ItemsView.HeaderProperty, ItemsView.HeaderTemplateProperty))
{
UpdateHeader();
}
else if (changedProperty.IsOneOf(ItemsView.FooterProperty, ItemsView.FooterTemplateProperty))
{
UpdateFooter();
}
}
protected virtual ListViewBase SelectLayout(IItemsLayout layoutSpecification)
{
switch (layoutSpecification)
{
case GridItemsLayout gridItemsLayout:
return CreateGridView(gridItemsLayout);
case ListItemsLayout listItemsLayout
when listItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal:
return CreateHorizontalListView();
}
// Default to a plain old vertical ListView
return new Windows.UI.Xaml.Controls.ListView();
}
protected abstract ListViewBase SelectListViewBase();
protected abstract void HandleLayoutPropertyChange(PropertyChangedEventArgs property);
protected abstract IItemsLayout Layout { get; }
protected virtual void UpdateItemsSource()
{
@ -145,153 +122,9 @@ namespace Xamarin.Forms.Platform.UWP
UpdateItemsSource();
}
protected virtual void UpdateHeader()
{
if (ListViewBase == null)
{
return;
}
if (_currentHeader != null)
{
Element.RemoveLogicalChild(_currentHeader);
_currentHeader = null;
}
var header = Element.Header;
switch (header)
{
case null:
ListViewBase.Header = null;
break;
case string text:
ListViewBase.HeaderTemplate = null;
ListViewBase.Header = new TextBlock { Text = text };
break;
case View view:
ListViewBase.HeaderTemplate = ViewTemplate;
_currentHeader = view;
Element.AddLogicalChild(_currentHeader);
ListViewBase.Header = view;
break;
default:
var headerTemplate = Element.HeaderTemplate;
if (headerTemplate != null)
{
ListViewBase.HeaderTemplate = ItemsViewTemplate;
ListViewBase.Header = new ItemTemplateContext(headerTemplate, header, Element);
}
else
{
ListViewBase.HeaderTemplate = null;
ListViewBase.Header = null;
}
break;
}
}
protected virtual void UpdateFooter()
{
if (ListViewBase == null)
{
return;
}
if (_currentFooter != null)
{
Element.RemoveLogicalChild(_currentFooter);
_currentFooter = null;
}
var footer = Element.Footer;
switch (footer)
{
case null:
ListViewBase.Footer = null;
break;
case string text:
ListViewBase.FooterTemplate = null;
ListViewBase.Footer = new TextBlock { Text = text };
break;
case View view:
ListViewBase.FooterTemplate = ViewTemplate;
_currentFooter = view;
Element.AddLogicalChild(_currentFooter);
ListViewBase.Footer = view;
break;
default:
var footerTemplate = Element.FooterTemplate;
if (footerTemplate != null)
{
ListViewBase.FooterTemplate = ItemsViewTemplate;
ListViewBase.Footer = new ItemTemplateContext(footerTemplate, footer, Element);
}
else
{
ListViewBase.FooterTemplate = null;
ListViewBase.Footer = null;
}
break;
}
}
static ListViewBase CreateGridView(GridItemsLayout gridItemsLayout)
{
var gridView = new FormsGridView();
if (gridItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal)
{
gridView.UseHorizontalItemsPanel();
// TODO hartez 2018/06/06 12:13:38 Should this logic just be built into FormsGridView?
ScrollViewer.SetHorizontalScrollMode(gridView, ScrollMode.Auto);
ScrollViewer.SetHorizontalScrollBarVisibility(gridView,
Windows.UI.Xaml.Controls.ScrollBarVisibility.Auto);
}
else
{
gridView.UseVerticalalItemsPanel();
}
gridView.MaximumRowsOrColumns = gridItemsLayout.Span;
return gridView;
}
static ListViewBase CreateHorizontalListView()
{
// TODO hartez 2018/06/05 16:18:57 Is there any performance benefit to caching the ItemsPanelTemplate lookup?
// TODO hartez 2018/05/29 15:38:04 Make sure the ItemsViewStyles.xaml xbf gets into the nuspec
var horizontalListView = new Windows.UI.Xaml.Controls.ListView()
{
ItemsPanel =
(ItemsPanelTemplate)Windows.UI.Xaml.Application.Current.Resources["HorizontalListItemsPanel"]
};
ScrollViewer.SetHorizontalScrollMode(horizontalListView, ScrollMode.Auto);
ScrollViewer.SetHorizontalScrollBarVisibility(horizontalListView,
Windows.UI.Xaml.Controls.ScrollBarVisibility.Auto);
return horizontalListView;
}
void LayoutPropertyChanged(object sender, PropertyChangedEventArgs property)
{
if (property.Is(GridItemsLayout.SpanProperty))
{
if (ListViewBase is FormsGridView formsGridView)
{
formsGridView.MaximumRowsOrColumns = ((GridItemsLayout)_layout).Span;
}
}
HandleLayoutPropertyChange(property);
}
protected virtual void SetUpNewElement(ItemsView newElement)
@ -303,19 +136,16 @@ namespace Xamarin.Forms.Platform.UWP
if (ListViewBase == null)
{
ListViewBase = SelectLayout(newElement.ItemsLayout);
ListViewBase = SelectListViewBase();
ListViewBase.IsSynchronizedWithCurrentItem = false;
_layout = newElement.ItemsLayout;
_layout.PropertyChanged += LayoutPropertyChanged;
Layout.PropertyChanged += LayoutPropertyChanged;
SetNativeControl(ListViewBase);
}
UpdateItemTemplate();
UpdateItemsSource();
UpdateHeader();
UpdateFooter();
UpdateVerticalScrollBarVisibility();
UpdateHorizontalScrollBarVisibility();
@ -330,11 +160,10 @@ namespace Xamarin.Forms.Platform.UWP
return;
}
if (_layout != null)
if (Layout != null)
{
// Stop tracking the old layout
_layout.PropertyChanged -= LayoutPropertyChanged;
_layout = null;
Layout.PropertyChanged -= LayoutPropertyChanged;
}
// Stop listening for ScrollTo requests

Просмотреть файл

@ -1,12 +1,11 @@
using System;
using System.ComponentModel;
using System.Linq;
using Windows.UI.Xaml.Controls;
using UWPListViewSelectionMode = Windows.UI.Xaml.Controls.ListViewSelectionMode;
namespace Xamarin.Forms.Platform.UWP
{
public class SelectableItemsViewRenderer : ItemsViewRenderer
public class SelectableItemsViewRenderer : StructuredItemsViewRenderer
{
SelectableItemsView _selectableItemsView;
bool _ignoreNativeSelectionChange;
@ -219,6 +218,5 @@ namespace Xamarin.Forms.Platform.UWP
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,208 @@
using System.ComponentModel;
using Windows.UI.Xaml.Controls;
using Xamarin.Forms.Platform.UAP;
namespace Xamarin.Forms.Platform.UWP
{
public class StructuredItemsViewRenderer : ItemsViewRenderer
{
StructuredItemsView _structuredItemsView;
View _currentHeader;
View _currentFooter;
protected override IItemsLayout Layout { get => _structuredItemsView.ItemsLayout; }
protected override void SetUpNewElement(ItemsView newElement)
{
_structuredItemsView = newElement as StructuredItemsView;
base.SetUpNewElement(newElement);
if (newElement == null)
{
return;
}
UpdateHeader();
UpdateFooter();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs changedProperty)
{
base.OnElementPropertyChanged(sender, changedProperty);
if (changedProperty.IsOneOf(StructuredItemsView.HeaderProperty, StructuredItemsView.HeaderTemplateProperty))
{
UpdateHeader();
}
else if (changedProperty.IsOneOf(StructuredItemsView.FooterProperty, StructuredItemsView.FooterTemplateProperty))
{
UpdateFooter();
}
}
protected override ListViewBase SelectListViewBase()
{
switch (Layout)
{
case GridItemsLayout gridItemsLayout:
return CreateGridView(gridItemsLayout);
case LinearItemsLayout listItemsLayout
when listItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal:
return CreateHorizontalListView();
}
// Default to a plain old vertical ListView
return new Windows.UI.Xaml.Controls.ListView();
}
protected virtual void UpdateHeader()
{
if (ListViewBase == null)
{
return;
}
if (_currentHeader != null)
{
Element.RemoveLogicalChild(_currentHeader);
_currentHeader = null;
}
var header = _structuredItemsView.Header;
switch (header)
{
case null:
ListViewBase.Header = null;
break;
case string text:
ListViewBase.HeaderTemplate = null;
ListViewBase.Header = new TextBlock { Text = text };
break;
case View view:
ListViewBase.HeaderTemplate = ViewTemplate;
_currentHeader = view;
Element.AddLogicalChild(_currentHeader);
ListViewBase.Header = view;
break;
default:
var headerTemplate = _structuredItemsView.HeaderTemplate;
if (headerTemplate != null)
{
ListViewBase.HeaderTemplate = ItemsViewTemplate;
ListViewBase.Header = new ItemTemplateContext(headerTemplate, header, Element);
}
else
{
ListViewBase.HeaderTemplate = null;
ListViewBase.Header = null;
}
break;
}
}
protected virtual void UpdateFooter()
{
if (ListViewBase == null)
{
return;
}
if (_currentFooter != null)
{
Element.RemoveLogicalChild(_currentFooter);
_currentFooter = null;
}
var footer = _structuredItemsView.Footer;
switch (footer)
{
case null:
ListViewBase.Footer = null;
break;
case string text:
ListViewBase.FooterTemplate = null;
ListViewBase.Footer = new TextBlock { Text = text };
break;
case View view:
ListViewBase.FooterTemplate = ViewTemplate;
_currentFooter = view;
Element.AddLogicalChild(_currentFooter);
ListViewBase.Footer = view;
break;
default:
var footerTemplate = _structuredItemsView.FooterTemplate;
if (footerTemplate != null)
{
ListViewBase.FooterTemplate = ItemsViewTemplate;
ListViewBase.Footer = new ItemTemplateContext(footerTemplate, footer, Element);
}
else
{
ListViewBase.FooterTemplate = null;
ListViewBase.Footer = null;
}
break;
}
}
protected override void HandleLayoutPropertyChange(PropertyChangedEventArgs property)
{
if (property.Is(GridItemsLayout.SpanProperty))
{
if (ListViewBase is FormsGridView formsGridView)
{
formsGridView.MaximumRowsOrColumns = ((GridItemsLayout)Layout).Span;
}
}
}
static ListViewBase CreateGridView(GridItemsLayout gridItemsLayout)
{
var gridView = new FormsGridView();
if (gridItemsLayout.Orientation == ItemsLayoutOrientation.Horizontal)
{
gridView.UseHorizontalItemsPanel();
// TODO hartez 2018/06/06 12:13:38 Should this logic just be built into FormsGridView?
ScrollViewer.SetHorizontalScrollMode(gridView, ScrollMode.Auto);
ScrollViewer.SetHorizontalScrollBarVisibility(gridView,
Windows.UI.Xaml.Controls.ScrollBarVisibility.Auto);
}
else
{
gridView.UseVerticalalItemsPanel();
}
gridView.MaximumRowsOrColumns = gridItemsLayout.Span;
return gridView;
}
static ListViewBase CreateHorizontalListView()
{
// TODO hartez 2018/06/05 16:18:57 Is there any performance benefit to caching the ItemsPanelTemplate lookup?
// TODO hartez 2018/05/29 15:38:04 Make sure the ItemsViewStyles.xaml xbf gets into the nuspec
var horizontalListView = new Windows.UI.Xaml.Controls.ListView()
{
ItemsPanel =
(ItemsPanelTemplate)Windows.UI.Xaml.Application.Current.Resources["HorizontalListItemsPanel"]
};
ScrollViewer.SetHorizontalScrollMode(horizontalListView, ScrollMode.Auto);
ScrollViewer.SetHorizontalScrollBarVisibility(horizontalListView,
Windows.UI.Xaml.Controls.ScrollBarVisibility.Auto);
return horizontalListView;
}
}
}

Просмотреть файл

@ -42,6 +42,7 @@
<Compile Include="AccessibilityExtensions.cs" />
<Compile Include="CollectionView\ItemsViewRenderer.cs" />
<Compile Include="CollectionView\SelectableItemsViewRenderer.cs" />
<Compile Include="CollectionView\StructuredItemsViewRenderer.cs" />
<Compile Include="ColorExtensions.cs" />
<Compile Include="DispatcherProvider.cs" />
<Compile Include="Extensions\ImageExtensions.cs" />

Просмотреть файл

@ -51,6 +51,8 @@ namespace Xamarin.Forms.Platform.iOS
}
}
protected override bool IsHorizontal => (_carouselView?.ItemsLayout as ItemsLayout)?.Orientation == ItemsLayoutOrientation.Horizontal;
protected override string DetermineCellReuseId()
{
if (_carouselView.ItemTemplate != null)

Просмотреть файл

@ -52,8 +52,8 @@ namespace Xamarin.Forms.Platform.iOS
public override nfloat GetMinimumInteritemSpacingForSection(UICollectionView collectionView, UICollectionViewLayout layout, nint section)
{
if (_itemsLayout is ListItemsLayout listItemsLayout)
return (nfloat)listItemsLayout.ItemSpacing;
if (_itemsLayout is LinearItemsLayout linearItemsLayout)
return (nfloat)linearItemsLayout.ItemSpacing;
return base.GetMinimumInteritemSpacingForSection(collectionView, layout, section);
}

Просмотреть файл

@ -33,15 +33,9 @@ namespace Xamarin.Forms.Platform.iOS
UpdateIsBounceEnabled();
}
protected override ItemsViewLayout SelectLayout(IItemsLayout layoutSpecification, ItemSizingStrategy itemSizingStrategy)
protected override ItemsViewLayout SelectLayout()
{
if (layoutSpecification is ListItemsLayout listItemsLayout)
{
return new CarouselViewLayout(listItemsLayout, itemSizingStrategy, CarouselView);
}
// Fall back to horizontal carousel
return new CarouselViewLayout(new ListItemsLayout(ItemsLayoutOrientation.Horizontal), itemSizingStrategy, CarouselView);
return new CarouselViewLayout(CarouselView.ItemsLayout, CarouselView.ItemSizingStrategy, CarouselView);
}
protected override void SetUpNewElement(ItemsView newElement)

Просмотреть файл

@ -6,7 +6,7 @@ using Xamarin.Forms.Internals;
namespace Xamarin.Forms.Platform.iOS
{
// TODO hartez 2018/06/01 14:21:24 Add a method for updating the layout
public class ItemsViewController : UICollectionViewController
public abstract class ItemsViewController : UICollectionViewController
{
public IItemsViewSource ItemsSource { get; protected set; }
public ItemsView ItemsView { get; }
@ -20,12 +20,6 @@ namespace Xamarin.Forms.Platform.iOS
UIView _emptyUIView;
VisualElement _emptyViewFormsElement;
UIView _headerUIView;
VisualElement _headerViewFormsElement;
UIView _footerUIView;
VisualElement _footerViewFormsElement;
protected UICollectionViewDelegator Delegator { get; set; }
public ItemsViewController(ItemsView itemsView, ItemsViewLayout layout) : base(layout)
@ -68,21 +62,8 @@ namespace Xamarin.Forms.Platform.iOS
if (disposing)
{
if (_headerViewFormsElement != null)
_headerViewFormsElement.MeasureInvalidated -= OnFormsElementMeasureInvalidated;
if (_footerViewFormsElement != null)
_footerViewFormsElement.MeasureInvalidated -= OnFormsElementMeasureInvalidated;
ItemsSource?.Dispose();
_emptyUIView?.Dispose();
_headerUIView?.Dispose();
_footerUIView?.Dispose();
_headerUIView = null;
_headerViewFormsElement = null;
_footerUIView = null;
_footerViewFormsElement = null;
_emptyUIView = null;
_emptyViewFormsElement = null;
}
@ -150,22 +131,6 @@ namespace Xamarin.Forms.Platform.iOS
ItemsViewLayout.ConstrainTo(CollectionView.Bounds.Size);
_initialConstraintsSet = true;
}
// This update is only relevant if you have a footer view because it's used to place the footer view
// based on the ContentSize so we just update the positions if the ContentSize has changed
if (_footerUIView != null)
{
if (IsHorizontal)
{
if (_footerUIView.Frame.X != ItemsViewLayout.CollectionViewContentSize.Width)
UpdateHeaderFooterPosition();
}
else
{
if (_footerUIView.Frame.Y != ItemsViewLayout.CollectionViewContentSize.Height)
UpdateHeaderFooterPosition();
}
}
}
protected virtual IItemsViewSource CreateItemsViewSource()
@ -276,55 +241,7 @@ namespace Xamarin.Forms.Platform.iOS
CollectionView.RegisterClassForCell(typeof(VerticalCell), VerticalCell.ReuseId);
}
bool IsHorizontal => (ItemsView?.ItemsLayout as ItemsLayout)?.Orientation == ItemsLayoutOrientation.Horizontal;
void UpdateHeaderFooterPosition()
{
if (IsHorizontal)
{
var currentInset = CollectionView.ContentInset;
nfloat headerWidth = _headerUIView?.Frame.Width ?? 0f;
nfloat footerWidth = _footerUIView?.Frame.Width ?? 0f;
if (_headerUIView != null && _headerUIView.Frame.X != headerWidth)
_headerUIView.Frame = new CoreGraphics.CGRect(-headerWidth, 0, headerWidth, CollectionView.Frame.Height);
if (_footerUIView != null && (_footerUIView.Frame.X != ItemsViewLayout.CollectionViewContentSize.Width))
_footerUIView.Frame = new CoreGraphics.CGRect(ItemsViewLayout.CollectionViewContentSize.Width, 0, footerWidth, CollectionView.Frame.Height);
if (CollectionView.ContentInset.Left != headerWidth || CollectionView.ContentInset.Right != footerWidth)
{
CollectionView.ContentInset = new UIEdgeInsets(0, headerWidth, 0, footerWidth);
// if the header grows it will scroll off the screen because if you change the content inset iOS adjusts the content offset so the list doesn't move
// this changes the offset of the list by however much the header size has changed
CollectionView.ContentOffset = new CoreGraphics.CGPoint(CollectionView.ContentOffset.X + (currentInset.Left - CollectionView.ContentInset.Left), CollectionView.ContentOffset.Y);
}
}
else
{
var currentInset = CollectionView.ContentInset;
nfloat headerHeight = _headerUIView?.Frame.Height ?? 0f;
nfloat footerHeight = _footerUIView?.Frame.Height ?? 0f;
if (_headerUIView != null && _headerUIView.Frame.Y != headerHeight)
_headerUIView.Frame = new CoreGraphics.CGRect(0, -headerHeight, CollectionView.Frame.Width, headerHeight);
if (_footerUIView != null && (_footerUIView.Frame.Y != ItemsViewLayout.CollectionViewContentSize.Height))
_footerUIView.Frame = new CoreGraphics.CGRect(0, ItemsViewLayout.CollectionViewContentSize.Height, CollectionView.Frame.Width, footerHeight);
if (CollectionView.ContentInset.Top != headerHeight || CollectionView.ContentInset.Bottom != footerHeight)
{
CollectionView.ContentInset = new UIEdgeInsets(headerHeight, 0, footerHeight, 0);
// if the header grows it will scroll off the screen because if you change the content inset iOS adjusts the content offset so the list doesn't move
// this changes the offset of the list by however much the header size has changed
CollectionView.ContentOffset = new CoreGraphics.CGPoint(CollectionView.ContentOffset.X, CollectionView.ContentOffset.Y + (currentInset.Top - CollectionView.ContentInset.Top));
}
}
}
protected abstract bool IsHorizontal { get; }
internal void UpdateEmptyView()
{
@ -334,17 +251,7 @@ namespace Xamarin.Forms.Platform.iOS
UpdateEmptyViewVisibility(ItemsSource?.ItemCount == 0);
}
internal void UpdateFooterView()
{
UpdateSubview(ItemsView?.Footer, ItemsView?.FooterTemplate, ref _footerUIView, ref _footerViewFormsElement);
}
internal void UpdateHeaderView()
{
UpdateSubview(ItemsView?.Header, ItemsView?.HeaderTemplate, ref _headerUIView, ref _headerViewFormsElement);
}
internal void UpdateSubview(object view, DataTemplate viewTemplate, ref UIView uiView, ref VisualElement formsElement)
protected void UpdateSubview(object view, DataTemplate viewTemplate, ref UIView uiView, ref VisualElement formsElement)
{
if (uiView != null)
CollectionView.Subviews.Remove(uiView);
@ -388,15 +295,19 @@ namespace Xamarin.Forms.Platform.iOS
}
}
void OnFormsElementMeasureInvalidated(object sender, EventArgs e)
protected void OnFormsElementMeasureInvalidated(object sender, EventArgs e)
{
if (sender is VisualElement formsElement)
{
RemeasureLayout(formsElement);
UpdateHeaderFooterPosition();
HandleFormsElementMeasureInvalidated(formsElement);
}
}
protected virtual void HandleFormsElementMeasureInvalidated(VisualElement formsElement)
{
RemeasureLayout(formsElement);
}
internal void UpdateView(object view, DataTemplate viewTemplate, ref UIView uiView, ref VisualElement formsElement)
{
// Is view set on the ItemsView?

Просмотреть файл

@ -71,7 +71,7 @@ namespace Xamarin.Forms.Platform.iOS
protected virtual void HandlePropertyChanged(PropertyChangedEventArgs propertyChanged)
{
if (propertyChanged.IsOneOf(ListItemsLayout.ItemSpacingProperty,
if (propertyChanged.IsOneOf(LinearItemsLayout.ItemSpacingProperty,
GridItemsLayout.HorizontalItemSpacingProperty, GridItemsLayout.VerticalItemSpacingProperty))
{
UpdateItemSpacing();
@ -111,7 +111,7 @@ namespace Xamarin.Forms.Platform.iOS
public virtual nfloat GetMinimumLineSpacingForSection(UICollectionView collectionView,
UICollectionViewLayout layout, nint section)
{
if (_itemsLayout is ListItemsLayout listViewLayout)
if (_itemsLayout is LinearItemsLayout listViewLayout)
{
return (nfloat)listViewLayout.ItemSpacing;
}

Просмотреть файл

@ -4,7 +4,7 @@ using UIKit;
namespace Xamarin.Forms.Platform.iOS
{
public class ItemsViewRenderer : ViewRenderer<ItemsView, UIView>
public abstract class ItemsViewRenderer : ViewRenderer<ItemsView, UIView>
{
ItemsViewLayout _layout;
bool _disposed;
@ -45,14 +45,6 @@ namespace Xamarin.Forms.Platform.iOS
{
ItemsViewController.UpdateEmptyView();
}
else if (changedProperty.IsOneOf(ItemsView.HeaderProperty, ItemsView.HeaderTemplateProperty))
{
ItemsViewController.UpdateHeaderView();
}
else if (changedProperty.IsOneOf(ItemsView.FooterProperty, ItemsView.FooterTemplateProperty))
{
ItemsViewController.UpdateFooterView();
}
else if (changedProperty.Is(ItemsView.ItemSizingStrategyProperty))
{
UpdateItemSizingStrategy();
@ -71,21 +63,7 @@ namespace Xamarin.Forms.Platform.iOS
}
}
protected virtual ItemsViewLayout SelectLayout(IItemsLayout layoutSpecification, ItemSizingStrategy itemSizingStrategy)
{
if (layoutSpecification is GridItemsLayout gridItemsLayout)
{
return new GridViewLayout(gridItemsLayout, itemSizingStrategy);
}
if (layoutSpecification is ListItemsLayout listItemsLayout)
{
return new ListViewLayout(listItemsLayout, itemSizingStrategy);
}
// Fall back to vertical list
return new ListViewLayout(new ListItemsLayout(ItemsLayoutOrientation.Vertical), itemSizingStrategy);
}
protected abstract ItemsViewLayout SelectLayout();
protected virtual void TearDownOldElement(ItemsView oldElement)
{
@ -120,9 +98,6 @@ namespace Xamarin.Forms.Platform.iOS
SetNativeControl(ItemsViewController.View);
ItemsViewController.CollectionView.BackgroundColor = UIColor.Clear;
ItemsViewController.UpdateEmptyView();
ItemsViewController.UpdateFooterView();
ItemsViewController.UpdateHeaderView();
UpdateHorizontalScrollBarVisibility();
UpdateVerticalScrollBarVisibility();
@ -132,7 +107,7 @@ namespace Xamarin.Forms.Platform.iOS
protected virtual void UpdateLayout()
{
_layout = SelectLayout(Element.ItemsLayout, Element.ItemSizingStrategy);
_layout = SelectLayout();
if (ItemsViewController != null)
{
@ -150,10 +125,7 @@ namespace Xamarin.Forms.Platform.iOS
_layout.ItemsUpdatingScrollMode = Element.ItemsUpdatingScrollMode;
}
protected virtual ItemsViewController CreateController(ItemsView newElement, ItemsViewLayout layout)
{
return new ItemsViewController(newElement, layout);
}
protected abstract ItemsViewController CreateController(ItemsView newElement, ItemsViewLayout layout);
NSIndexPath DetermineIndex(ScrollToRequestEventArgs args)
{

Просмотреть файл

@ -5,7 +5,7 @@ namespace Xamarin.Forms.Platform.iOS
{
internal class ListViewLayout : ItemsViewLayout
{
public ListViewLayout(ListItemsLayout itemsLayout, ItemSizingStrategy itemSizingStrategy) : base(itemsLayout, itemSizingStrategy)
public ListViewLayout(LinearItemsLayout itemsLayout, ItemSizingStrategy itemSizingStrategy) : base(itemsLayout, itemSizingStrategy)
{
}

Просмотреть файл

@ -5,7 +5,7 @@ using UIKit;
namespace Xamarin.Forms.Platform.iOS
{
public class SelectableItemsViewController : ItemsViewController
public class SelectableItemsViewController : StructuredItemsViewController
{
SelectableItemsView SelectableItemsView => (SelectableItemsView)ItemsView;

Просмотреть файл

@ -3,7 +3,7 @@ using System.ComponentModel;
namespace Xamarin.Forms.Platform.iOS
{
public class SelectableItemsViewRenderer : ItemsViewRenderer
public class SelectableItemsViewRenderer : StructuredItemsViewRenderer
{
SelectableItemsView SelectableItemsView => (SelectableItemsView)Element;
SelectableItemsViewController SelectableItemsViewController => (SelectableItemsViewController)ItemsViewController;

Просмотреть файл

@ -0,0 +1,139 @@
using System;
using UIKit;
namespace Xamarin.Forms.Platform.iOS
{
public class StructuredItemsViewController : ItemsViewController
{
bool _disposed;
StructuredItemsView StructuredItemsView => (StructuredItemsView)ItemsView;
UIView _headerUIView;
VisualElement _headerViewFormsElement;
UIView _footerUIView;
VisualElement _footerViewFormsElement;
public StructuredItemsViewController(StructuredItemsView structuredItemsView, ItemsViewLayout layout)
: base(structuredItemsView, layout)
{
}
protected override void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
_disposed = true;
if (disposing)
{
if (_headerViewFormsElement != null)
_headerViewFormsElement.MeasureInvalidated -= OnFormsElementMeasureInvalidated;
if (_footerViewFormsElement != null)
_footerViewFormsElement.MeasureInvalidated -= OnFormsElementMeasureInvalidated;
_headerUIView = null;
_headerViewFormsElement = null;
_footerUIView = null;
_footerViewFormsElement = null;
}
base.Dispose(disposing);
}
protected override bool IsHorizontal => (StructuredItemsView?.ItemsLayout as ItemsLayout)?.Orientation == ItemsLayoutOrientation.Horizontal;
public override void ViewWillLayoutSubviews()
{
base.ViewWillLayoutSubviews();
// This update is only relevant if you have a footer view because it's used to place the footer view
// based on the ContentSize so we just update the positions if the ContentSize has changed
if (_footerUIView != null)
{
if (IsHorizontal)
{
if (_footerUIView.Frame.X != ItemsViewLayout.CollectionViewContentSize.Width)
UpdateHeaderFooterPosition();
}
else
{
if (_footerUIView.Frame.Y != ItemsViewLayout.CollectionViewContentSize.Height)
UpdateHeaderFooterPosition();
}
}
}
internal void UpdateFooterView()
{
UpdateSubview(StructuredItemsView?.Footer, StructuredItemsView?.FooterTemplate,
ref _footerUIView, ref _footerViewFormsElement);
}
internal void UpdateHeaderView()
{
UpdateSubview(StructuredItemsView?.Header, StructuredItemsView?.HeaderTemplate,
ref _headerUIView, ref _headerViewFormsElement);
}
void UpdateHeaderFooterPosition()
{
if (IsHorizontal)
{
var currentInset = CollectionView.ContentInset;
nfloat headerWidth = _headerUIView?.Frame.Width ?? 0f;
nfloat footerWidth = _footerUIView?.Frame.Width ?? 0f;
if (_headerUIView != null && _headerUIView.Frame.X != headerWidth)
_headerUIView.Frame = new CoreGraphics.CGRect(-headerWidth, 0, headerWidth, CollectionView.Frame.Height);
if (_footerUIView != null && (_footerUIView.Frame.X != ItemsViewLayout.CollectionViewContentSize.Width))
_footerUIView.Frame = new CoreGraphics.CGRect(ItemsViewLayout.CollectionViewContentSize.Width, 0, footerWidth, CollectionView.Frame.Height);
if (CollectionView.ContentInset.Left != headerWidth || CollectionView.ContentInset.Right != footerWidth)
{
CollectionView.ContentInset = new UIEdgeInsets(0, headerWidth, 0, footerWidth);
// if the header grows it will scroll off the screen because if you change the content inset iOS adjusts the content offset so the list doesn't move
// this changes the offset of the list by however much the header size has changed
CollectionView.ContentOffset = new CoreGraphics.CGPoint(CollectionView.ContentOffset.X + (currentInset.Left - CollectionView.ContentInset.Left), CollectionView.ContentOffset.Y);
}
}
else
{
var currentInset = CollectionView.ContentInset;
nfloat headerHeight = _headerUIView?.Frame.Height ?? 0f;
nfloat footerHeight = _footerUIView?.Frame.Height ?? 0f;
if (_headerUIView != null && _headerUIView.Frame.Y != headerHeight)
_headerUIView.Frame = new CoreGraphics.CGRect(0, -headerHeight, CollectionView.Frame.Width, headerHeight);
if (_footerUIView != null && (_footerUIView.Frame.Y != ItemsViewLayout.CollectionViewContentSize.Height))
_footerUIView.Frame = new CoreGraphics.CGRect(0, ItemsViewLayout.CollectionViewContentSize.Height, CollectionView.Frame.Width, footerHeight);
if (CollectionView.ContentInset.Top != headerHeight || CollectionView.ContentInset.Bottom != footerHeight)
{
CollectionView.ContentInset = new UIEdgeInsets(headerHeight, 0, footerHeight, 0);
// if the header grows it will scroll off the screen because if you change the content inset iOS adjusts the content offset so the list doesn't move
// this changes the offset of the list by however much the header size has changed
CollectionView.ContentOffset = new CoreGraphics.CGPoint(CollectionView.ContentOffset.X, CollectionView.ContentOffset.Y + (currentInset.Top - CollectionView.ContentInset.Top));
}
}
}
protected override void HandleFormsElementMeasureInvalidated(VisualElement formsElement)
{
base.HandleFormsElementMeasureInvalidated(formsElement);
UpdateHeaderFooterPosition();
}
}
}

Просмотреть файл

@ -0,0 +1,61 @@
using System.ComponentModel;
namespace Xamarin.Forms.Platform.iOS
{
public class StructuredItemsViewRenderer : ItemsViewRenderer
{
StructuredItemsView StructuredItemsView => (StructuredItemsView)Element;
StructuredItemsViewController StructuredItemsViewController => (StructuredItemsViewController)ItemsViewController;
protected override ItemsViewController CreateController(ItemsView itemsView, ItemsViewLayout layout)
{
return new StructuredItemsViewController(itemsView as StructuredItemsView, layout);
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs changedProperty)
{
base.OnElementPropertyChanged(sender, changedProperty);
if (changedProperty.IsOneOf(StructuredItemsView.HeaderProperty, StructuredItemsView.HeaderTemplateProperty))
{
StructuredItemsViewController.UpdateHeaderView();
}
else if (changedProperty.IsOneOf(StructuredItemsView.FooterProperty, StructuredItemsView.FooterTemplateProperty))
{
StructuredItemsViewController.UpdateFooterView();
}
}
protected override void SetUpNewElement(ItemsView newElement)
{
base.SetUpNewElement(newElement);
if (newElement == null)
{
return;
}
StructuredItemsViewController.UpdateFooterView();
StructuredItemsViewController.UpdateHeaderView();
}
protected override ItemsViewLayout SelectLayout()
{
var itemSizingStrategy = StructuredItemsView.ItemSizingStrategy;
var layoutSpecification = StructuredItemsView.ItemsLayout;
if (layoutSpecification is GridItemsLayout gridItemsLayout)
{
return new GridViewLayout(gridItemsLayout, itemSizingStrategy);
}
if (layoutSpecification is LinearItemsLayout listItemsLayout)
{
return new ListViewLayout(listItemsLayout, itemSizingStrategy);
}
// Fall back to vertical list
return new ListViewLayout(new LinearItemsLayout(ItemsLayoutOrientation.Vertical), itemSizingStrategy);
}
}
}

Просмотреть файл

@ -128,6 +128,8 @@
<Compile Include="CollectionView\TemplateHelpers.cs" />
<Compile Include="CollectionView\UICollectionViewDelegator.cs" />
<Compile Include="CollectionView\VerticalCell.cs" />
<Compile Include="CollectionView\StructuredItemsViewController.cs" />
<Compile Include="CollectionView\StructuredItemsViewRenderer.cs" />
<Compile Include="CollectionView\VerticalDefaultCell.cs" />
<Compile Include="CollectionView\GridViewLayout.cs" />
<Compile Include="CollectionView\ItemsViewLayout.cs" />

Просмотреть файл

@ -8,11 +8,11 @@
x:Name="self">
<CollectionView ItemsSource="{Binding Items}" x:Name="collectionview">
<CollectionView.ItemsLayout>
<ListItemsLayout ItemSpacing="4">
<LinearItemsLayout ItemSpacing="4">
<x:Arguments>
<ItemsLayoutOrientation>Vertical</ItemsLayoutOrientation>
</x:Arguments>
</ListItemsLayout>
</LinearItemsLayout>
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>