Xamarin Forms CollectionView - Hide SearchBar on Scroll

Fade away!

Adding a little animation to your mobile applications can help imbue them with a bit of personality, as well as, allowing the content to take centre stage by hiding UI elements when they are not required. A great example of this is letting the search bar above a list of items fade away when scrolling, then bringing it back into view when the scroll changes direction.

Animation showing SearchBar hiding/appearing on scroll

This effect is really simple to achieve in Xamarin Forms using in-built animations.

Since we want to layer the search bar on top of a collection view this is good use case for an AbsoluteLayout which gives us control over element positions. I used frames to give the search bar some depth, if you want something a little more fancy I suggest PancakeView (it’s awesome 🥞).

<AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
    <CollectionView
        x:Name="SearchCollectionView"
        AbsoluteLayout.LayoutBounds="0,0,1,1"
        AbsoluteLayout.LayoutFlags="All"
        Scrolled="PackagesScrolled">
        <CollectionView.Header>
            <ContentView>
                <StackLayout x:Name="SearchCollectionHeaderView" />
            </ContentView>
        </CollectionView.Header>
        <CollectionView.ItemTemplate>
            <DataTemplate>
                <!-- Your awesome data template -->
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>

    <Frame
        x:Name="SearchBarView"
        Margin="16,8,16,8"
        Padding="3"
        AbsoluteLayout.LayoutBounds="0.5, 0, AutoSize, AutoSize"
        AbsoluteLayout.LayoutFlags="PositionProportional"
        CornerRadius="6"
        HasShadow="True">
        <SearchBar HorizontalOptions="FillAndExpand" />
    </Frame>
</AbsoluteLayout>

To get our animations responding to collection view scrolls we can leverage the Scrolled event. Inside the handler it’s a matter of calculating the scroll direction and Y axis translation. Finally, we queue up two animation events to occur concurrently, one to reduce the opacity and the other to move the search bar off screen.

private void PackagesScrolled(object sender, ItemsViewScrolledEventArgs e)
{
    var transY = Convert.ToInt32(SearchBarView.TranslationY);
    if (transY == 0 &&
        e.VerticalDelta > 15)
    {
        var trans = SearchBarView.Height + SearchBarView.Margin.Top;
        var safeInsets = On<Xamarin.Forms.PlatformConfiguration.iOS>().SafeAreaInsets();

        // Start both animations concurrently
        Task.WhenAll(
            SearchBarView.TranslateTo(0, -(trans + safeInsets.Top), 200, Easing.CubicIn),
            SearchBarView.FadeTo(0.25, 200));
    }
    else if (transY != 0 &&
             e.VerticalDelta < 0 &&
             Math.Abs(e.VerticalDelta) > 10)
    {
        Task.WhenAll(
            SearchBarView.TranslateTo(0, 0, 200, Easing.CubicOut),
            SearchBarView.FadeTo(1, 200));
    }
}

I really love the simplicity of this example and best of all, besides working out the safe insets on iOS, no platform specific code!

Sample code on GitHub here.

comments powered by Disqus