CollectionView inside ScrollView

About the topic:

Contenido

Learn how to use the CollectionView within a ScrollView in Xamarin.Forms. Sometimes we want to develop some functionalities that need different data contexts to be displayed within the same page and this can be achieved with a TemplateSelector if the data source is the same, but if it is not the same how we can do it?.

In this article, I will share with you custom control of the CollectionView that you can use directly in your projects or simply adapt it to your needs if that’s what you want.

🚨 Note: This article and all the information presented here are for educational purposes. It is not recommended to use a CollectionView or ListView within a ScrollView with the techniques that I share in this post.

More information here.

CollectionView inside a ScrollView

Before showing you the control and how it works I need you to understand that it is not always highly recommended to put a CollectionView inside a ScrollView simply because both controls have scrolling and when using them together you can have unwanted User Experiences (UX).

Here’s an example of how a CollectionView behaves within a ScrollView:

CollectionView within a ScrollVIew.

Note: The displayed header does not belong to the CollectionView.

If you look good, until the CollectionView reaches the bottom of the list of items it handles, the ScrollView does not scroll unless you scroll from the header which does not belong to the CollectionView.

Why use a CollectionView within a ScrollView?

I’ll show you a particular and very popular case for you to understand. This is the Instagram user page. Let’s go see it:

@luismatosluna

If you look, below the stories, are the TabsViews that allow us to visualize different types of data and contexts.

💡 Note: Previously, Instagram displayed in tabsView the type of view you wanted to see on the page either Grid or List. This behavior in Xamarin.Forms can be achieved with a TemplateSelector as long as the data context is the same.

Here the challenge is that the CollectionView is not very extensible to say, and does not allow you to achieve this functionality in a natural way, at least in what you can investigate.

That’s why I decided to create the next control.

Custom CollectionView

Control really is a very simple thing but it applies some powerful concepts. What we will do will be disable the scroll of the in order to use only the scroll of the . For this we only have to calculate the total height of all items and set that height to .CollectionView ScrollViewCollectionView

To achieve this we have defined some default parameters as:

  • ScrollView, of type ScroolView, receives the instance of the ScrollView parent and has a default value of null.
  • RowHeigt, of type int, receives the predefined height of the rows that it is using the control, default 0.


With these parameters we can have one CustomCollactionView as follows:

    public class CustomCollectionView : CollectionView
    {
...
        [TypeConverter(typeof(ReferenceTypeConverter))]
        public ScrollView ScrollView
        {
            set
            {
                _scrollView = value;
                _scrollView.Scrolled += _scrollView_Scrolled;
            }
        }
...
        private void _scrollView_Scrolled(object sender, ScrolledEventArgs e)
        {
            double scrollingSpace = _scrollView.ContentSize.Height - _scrollView.Height;
            if (scrollingSpace <= e.ScrollY)
            {
                // Touched bottom view
                RemainingItemsThresholdReachedCommand?.Execute(RemainingItemsThresholdReachedCommandParameter);
            }
        }

        private void UpdateHeight()
        {
            if(_columns  == 0)
            {
                if (ItemsLayout is GridItemsLayout layout)                
                    _columns = layout.Span;
                else
                    _columns = 1;
            }

            if (_rowHeigt > 0)            
                HeightRequest = (_rowHeigt * _rowCount) / _columns;
        }

        protected override void OnChildAdded(Element child)
        {
            base.OnChildAdded(child);
            UpdateHeight();
        }
        
        protected override void OnChildRemoved(Element child, int oldLogicalIndex)
        {
            base.OnChildRemoved(child, oldLogicalIndex);
            UpdateHeight();
        }
    }

Each time it is added or deleted, an item will update the height of the CollectionView. Similarly, if we touch the bottom of the ScrollView we will execute the RemainingItemsThresholdReachedCommand of the CollectinView to make sure that the behavior is the same in every way.

Once we have control, we can use it in our Xamarin Forms projects. Here’s an example in XAML:

...
    <ScrollView x:Name="myScrollView">
        <StackLayout>

            <!-- YOURS CONTROLS GOES HERE -->

            <ctrls:CustomCollectionView
                ItemSizingStrategy="MeasureFirstItem"
                ItemsLayout="VerticalGrid, 3"
                ItemsSource="{Binding Items}"
                RowHeigt="120"
                ScrollView="myScrollView">

                <CollectionView.ItemTemplate>
                    <DataTemplate>
                        ...
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </ctrls:CustomCollectionView>

        </StackLayout>
    </ScrollView>
...

With this, we can get behavior similar to that of the Instagram profile page. Let’s look at an example:

CollectionView within a ScrollVIew.

Note: The displayed header does not belong to the CollectionView.

Conclusion

As you can see this is very simple but powerful control, which I bet more than one can help. The implementation is quite simple and very simple to understand.

Note: There is a limitation. The control does not work with rows that have dynamic heights, because we are calculating predefined fields.

I hope this article is useful, and nothing let me know on the networks that they really like these kinds of articles and I will do my best to give them the best of the best.

Help us grow our community and unlock the content below to access the sample repo. ⬇⬇⬇

With nothing else to add, see you next time!

What do you think of this content?
 
Luis Matos

Luis Matos

I help professionals and companies to create value solutions. I am a Systems Engineer, blockchain executive, and international mobile application speaker. Founder of the Malla Consulting Agency and several international technology communities.
Subscribe
Notify of
1 Comment
Oldest
Newest
Inline Feedbacks
View all comments
1
0
Would love your thoughts, please comment.x
()
x

Search in the site