CollectionView

VelocityVelocity NZMember ✭✭✭
edited March 13 in Xamarin.Forms Evolution

Summary

A virtualized collection view that utilizes native layout controls to present an ordered set of data items using a flexible and changeable layout. The portable control must be bindable, support item templating and (optionally) support section headers.

Platform renderers would be based on the following native controls:

  • iOS: UICollectionView
  • Android: RecyclerView
  • UWP: GridView

UI virtualization is achieved in each of the native controls ensuring fast performance with large datasets.

API Changes

/// <summary>
/// A grid-like view to present an ordered set of data items using a flexible and changeable layout.
/// </summary>
public class CollectionView : View
{
    #region Bindable Properties

    /// <summary>
    /// The property bound to <see cref="Padding"/>.
    /// </summary>
    public static readonly BindableProperty PaddingProperty =
       BindableProperty.Create(
           propertyName: nameof(Padding),
           returnType: typeof(Thickness),
           declaringType: typeof(CollectionView),
           defaultValue: default(Thickness));

    /// <summary>
    /// The property bound to <see cref="RowSpacing"/>.
    /// </summary>
    public static readonly BindableProperty RowSpacingProperty =
       BindableProperty.Create(
           propertyName: nameof(RowSpacing),
           returnType: typeof(double),
           declaringType: typeof(CollectionView),
           defaultValue: default(double));

    /// <summary>
    /// The property bound to <see cref="ColumnSpacing"/>.
    /// </summary>
    public static readonly BindableProperty ColumnSpacingProperty =
       BindableProperty.Create(
           propertyName: nameof(ColumnSpacing),
           returnType: typeof(double),
           declaringType: typeof(CollectionView),
           defaultValue: default(double));

    /// <summary>
    /// Property bound to <see cref="MaxItemWidth"/>
    /// </summary>
    public static readonly BindableProperty MaxItemWidthProperty =
       BindableProperty.Create(
           propertyName: nameof(MaxItemWidth),
           returnType: typeof(double),
           declaringType: typeof(CollectionView),
           defaultValue: default(double));

    /// <summary>
    /// Property bound to <see cref="MinItemWidth"/>
    /// </summary>
    public static readonly BindableProperty MinItemWidthProperty =
       BindableProperty.Create(
           propertyName: nameof(MinItemWidth),
           returnType: typeof(double),
           declaringType: typeof(CollectionView),
           defaultValue: default(double));

    /// <summary>
    /// Property bound to <see cref="RowHeight"/>
    /// </summary>
    public static readonly BindableProperty RowHeightProperty =
       BindableProperty.Create(
           propertyName: nameof(RowHeight),
           returnType: typeof(double),
           declaringType: typeof(CollectionView),
           defaultValue: default(double));

    /// <summary>
    /// The property bound to <see cref="ItemsSource"/>.
    /// </summary>
    public static readonly BindableProperty ItemsSourceProperty =
       BindableProperty.Create(
           propertyName: nameof(ItemsSource),
           returnType: typeof(IEnumerable),
           declaringType: typeof(CollectionView),
           defaultValue: default(IEnumerable));

    /// <summary>
    /// Property bound to <see cref="ItemTemplate"/>
    /// </summary>
    public static readonly BindableProperty ItemTemplateProperty =
       BindableProperty.Create(
           propertyName: nameof(ItemTemplate),
           returnType: typeof(DataTemplate),
           declaringType: typeof(CollectionView),
           defaultValue: default(DataTemplate));

    /// <summary>
    /// Property bound to <see cref="SectionHeaderTemplate"/>
    /// </summary>
    public static readonly BindableProperty SectionHeaderTemplateProperty =
       BindableProperty.Create(
           propertyName: nameof(SectionHeaderTemplate),
           returnType: typeof(DataTemplate),
           declaringType: typeof(CollectionView),
           defaultValue: default(DataTemplate));

    /// <summary>
    /// Property bound to <see cref="SectionHeaderHeight"/>
    /// </summary>
    public static readonly BindableProperty SectionHeaderHeightProperty =
       BindableProperty.Create(
           propertyName: nameof(SectionHeaderHeight),
           returnType: typeof(double),
           declaringType: typeof(CollectionView),
           defaultValue: default(double));

    /// <summary>
    /// Property bound to <see cref="Direction"/>
    /// </summary>
    public static readonly BindableProperty DirectionProperty =
       BindableProperty.Create(
           propertyName: nameof(Direction),
           returnType: typeof(CollectionViewDirection),
           declaringType: typeof(CollectionView),
           defaultValue: CollectionViewDirection.Vertical);

    #endregion
}

Intended Use Case

The most common use would be to present items in a grid arrangement, although the control could be configurable to present items as a vertical or horizontal list. The control is intended for applications where a bindable, virtualized collection view layout is required that is not served by any of the existing Xamarin.Forms controls.

Applications:

  • Responsive, grid-based layout eg. Photo album, search results
  • Horizontal layouts
  • Custom layouts ie. Circle, flow.
0
0 votes

Open · Last Updated

Posts

  • DanSiegelDanSiegel USUniversity ✭✭

    This is exactly the type of new control I'd like to see in Xamarin Forms

  • AdrianKnightAdrianKnight USMember ✭✭✭✭

    The implementation is probably going to be a huge challenge. CarouselView took months and months of development. Not sure how long this would take - not to mention it should work with CarouselView.

    If this gets accepted, then there won't be a need for Leverage RecyclerView on Android.

  • DH80DH80 USMember ✭✭

    the CarouselView code would be a good place to start. It is both backed by UICollectionView(iOS) and RecyclerView(Android)

  • DavidDancyDavidDancy AUMember ✭✭✭✭

    I'm intrigued about the MaxItemWidth, MinItemWidth and RowHeight proposed properties. I wonder if they might not be better provided by the ItemTemplate, a la CollectionView in iOS? Likewise I would prefer SectionHeaderHeight to come from the SectionHeaderTemplate.

  • VelocityVelocity NZMember ✭✭✭

    @DavidDancy Thanks for your comments, heres a few notes below.

    MinItemWidth, MaxItemWidth: Define the min/max size for a collection view item. These values determine how the content should flow based on available width and the total number of columns. The CollectionView will use these values to determine how many columns to display (for a vertical collection)

    RowHeight: Define the (row) height for a collection view item. The portable view will be inflated and sized to fit the calculated width and the set row height. The same will apply for section headers using the SectionHeaderTemplate and SectionHeaderHeight.

    Similar to ListView it could be an option to provide automatic calculation of row height for content and/or headers. However, no doubt this would incur a performance hit. I do like the suggestion though.

  • DavidDancyDavidDancy AUMember ✭✭✭✭

    @Velocity The reason I raised the issue was that I think having those properties in the CollectionView will constrain it to only "regular"-type collections. If I ever need to display an "irregular" collection (where items are different sizes and need to flow in non-linear flows) I'm stuck. At that point we need some kind of UICollectionViewFlowLayout-type object to help out with the flow calculations - and then the properties in the CollectionView are not only redundant but actively misleading. I think the design of UICollectionView is spot-on, so I would very much prefer to copy it rather than try to invent something that should be able to do as much (because it's backed by UICollectionView internally but can't. Hence I'd prefer to see a CollectionViewLayout object that does the flow / size calculation for each item in the collection.

  • https://github.com/NobsterTheLobster/Xamarin.Forms.GridView

    Supports UWP (ItemsPanelTemplate set to ItemsWrapGrid), Android (Recycler) and IOS (UICollectionView)

    This grid is uniform though as this was the main intention of the control! so not what David is requesting.

    The width of each item I think has to be uniform however I don't think the height necessarily has to be; In the android and ios Renderers I took a design decision to use the RowHeight property and to always scale the cells to fill but It should be possible to change this behaviour.

    And If your targeting UWP only then simply don't set the rowheight property and make sure that has uneven rows is false.

  • veryhumbleveryhumble USMember ✭✭

    I'll just drop this here: https://gist.github.com/veryhumble/0648d7f367a5a808633361ed2e31260e

    It's quite specific to the use case I had, but some code might be usable for a generic implementation.

    Most obvious drawback is that layouting is done on updating the ViewHolder instead at creation time (because of DataTemplateSelector usage) wich does impact performance.

    I have the same with iOS UiCollectionView

  • DevaPalanisamyDevaPalanisamy GBUniversity ✭✭

    cant we achieve same with Flex Layout?

  • ShimmyWeitzhandlerShimmyWeitzhandler USMember ✭✭✭

    Very compelling to me!

  • DanielLDanielL PLInsider ✭✭✭✭

    https://github.com/daniel-luberda/DLToolkit.Forms.Controls/tree/master/FlowListView

    This is a ListView derivative, so it means that cells are also virtualised.

  • RyanDixonRyanDixon USMember ✭✭✭

    Already halfway through implementing something like this myself... (Got UWP and Android working)
    Ideally speaking, would it need to support columns as well? I would say that once you have a good starting point (i.e no grouping, no columns, etc). Then it wouldn't be hard to get the rest working after.

    +1 from me though, this is a huge missing piece in forms imo

Sign In or Register to comment.