Freeze a Grid upon scrolling

Jassim Al Rahma 1,521 Reputation points
2022-03-22T20:37:00.32+00:00

Hi,

I have below XAML in my Xamarin app to show the post details. I have kept the Grid inside a ScrollView because the LabelPostDetailsFull has long text but I am ok to move the ScollView somewhere else if needed.

My requirment here is when the user scroll up the content and the GridButtons reaches the top of the page then the GridButtons show be always visible and the scrollable content is what's inside the LabelPostDetailsFull

so in a simple language, the user scroll up, the GridTitle will go to the top until it disappears and when the GridButtons reaches the top then GridButtons will be fixed and user can continue reading the content of LabelPostDetailsFull

Then when the user scroll down until he reaches the end then the GridButtons will move and go back to its original location and the GridTitle wil show again.

Hope I was clear in describing what I want.. Thanks..

<ScrollView Grid.Row="1" HorizontalScrollBarVisibility="Never" VerticalScrollBarVisibility="Never">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Grid x:Name="GridTitle" Grid.Row="0" Margin="10">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>

            <BoxView x:Name="BoxViewName1" Grid.Column="0" Grid.RowSpan="2" WidthRequest="5" VerticalOptions="FillAndExpand" Margin="5,0,0,0" />
            <Label x:Name="LabelPostName" Grid.Column="1" Grid.Row="0" />
            <Label x:Name="LabelPostArea" Grid.Column="1" Grid.Row="1" FontSize="Small" />
            <BoxView x:Name="BoxViewName2" Grid.Column="2" Grid.RowSpan="2" WidthRequest="5" VerticalOptions="FillAndExpand" Margin="0,0,0,5" />
        </Grid>

        <Grid x:Name="GridButtons" Grid.Row="1" Margin="10">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>

            <Image Margin="10" Grid.Column="0" HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="45" HeightRequest="45" />
            <Image Margin="10" Grid.Column="1" HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="45" HeightRequest="45" />
            <Image Margin="10" Grid.Column="2" HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="45" HeightRequest="45" />
        </Grid>

        <Label x:Name="LabelPostDetailsFull" Grid.Row="2" Margin="20,0,20,20" TextType="Html" />
    </Grid>
</ScrollView>
Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,294 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,239 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Yonglun Liu (Shanghai Wicresoft Co,.Ltd.) 35,471 Reputation points Microsoft Vendor
    2022-03-23T05:19:15.263+00:00

    Hello,

    I've made a code test for your issue.

    Here are steps of the solution that you can try:

    Step1: Use multiple ScrollViews to control views for freezing:

       <ScrollView x:Name="name">  
                   <Grid x:Name="GridTitle" Grid.Row="0" Margin="10">  
       		//your grid code  
       		</Grid>  
       </ScrollView>  
         
       <ScrollView x:Name="buttons">  
                   <Grid x:Name="GridButtons"  Margin="10">  
       		//your grid code  
       		</Grid>  
       </ScrollView>  
         
       <ScrollView x:Name="dataView">  
                   <Label x:Name="LabelPostDetailsFull" etc./>  
       </ScrollView>  
    

    Step2: Add the Scrolled event to the constructor of the corresponding ContentPage

       dataView.Scrolled += DataScrollView_Scrolled;  
         
       private async void DataScrollView_Scrolled(object sender, ScrolledEventArgs e)  
               {  
                   await buttons.ScrollToAsync(e.ScrollX, e.ScrollY, false);  
                   ScrollView scrollView = sender as ScrollView;  
                   double scrollingSpace = scrollView.ContentSize.Height - scrollView.Height;  
                     
       		  
                   if (e.ScrollY==0|| scrollingSpace <=  e.ScrollY)  
                       name.IsVisible = true;  
                   else  
                       name.IsVisible = false;  
         
               }  
    

    If you use spacing in the outermost StackLayout, you need to modify scrollingSpace <= e.ScrollY to scrollingSpace <= e.ScrollY+layout.Spacing.

    In addition, If you have many elements in your GridView, the performance will be poor. You can use ListView instead.

    Best Regards,

    Alec Liu.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.