ScrollView appears scrolled down initially

jstuardojstuardo ✭✭Member ✭✭

Hello,

I have a scrollview that contains a listview and a videoview.

When the page is shown, the scrollview is scroll down to bottom, so that the video appears. I need to scroll manually up to show the firs listview item. How can I solve it?

This is the XAML file:

`<?xml version="1.0" encoding="utf-8" ?>

<ScrollView>
    <StackLayout Orientation="Vertical" Padding="15">
        <Image x:Name="ImageFin" ></Image>
        <ListView 
            x:Name="PropertiesFin"
            ItemsSource="{Binding Item.Properties}"
            HasUnevenRows="true" 
            VerticalOptions="Start" 
            HorizontalOptions="FillAndExpand">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="auto" />
                            </Grid.RowDefinitions>
                            <StackLayout Padding="10">
                                <Label Text="{Binding .}" 
                                    LineBreakMode="NoWrap"
                                    Style="{DynamicResource ListItemTextStyle}" 
                                    FontSize="16" />
                            </StackLayout>
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        <mm:VideoView x:Name="VideoFin" VerticalOptions="Start" HeightRequest="190" HorizontalOptions="FillAndExpand" />
        <Button x:Name="BtnPlayStop" VerticalOptions="Start" HorizontalOptions="FillAndExpand" Text="Iniciar Video" Clicked="PlayStop_Clicked" BackgroundColor="Silver" TextColor="White"/>
    </StackLayout>
</ScrollView>

`

Any help, please?

Thanks

Jaime

Best Answers

Answers

  • JohnHardmanJohnHardman mod GBUniversity mod

    @jstuardo

    That's unexpected. Most questions similar to this are asking the opposite - how to scroll to the bottom of a ListView or ScrollView rather than the top.

    Anyway, first things first - you shouldn't put a ListView inside a ScrollView. If you search the forum, you will find many threads about this.

    As to how to scroll the ScrollView, use the following code and call ScrollOnceInLayoutAsync from your OnAppearing() override.

            private static bool _inUse;
    
            // Based on https://github.com/xamarin/Xamarin.Forms/pull/988
            public static async Task ScrollOnceInLayoutAsync(
                ScrollView scrollView,
                View view,
                bool animated = false,
                ScrollToPosition scrollToPosition = ScrollToPosition.End,
                int millisecondDelay = 1,
                int maxCycles = 10)
            {
                if ((scrollView != null) && (view != null))
                {
                    if (!_inUse)
                    {
                        _inUse = true;
    
                        await WaitForViewToBeInNativeLayout(view, millisecondDelay, maxCycles);
    
                        try
                        {
                            await scrollView.ScrollToAsync(view, scrollToPosition, animated);
                        }
                        catch (Exception ex)
                        {
                            // call your own error reporting code here
                        }
    
                        _inUse = false;
                    }
                }
            }
    
            public static async Task WaitForViewToBeInNativeLayout(
                View view,
                int millisecondDelay = 1,
                int maxCycles = 10) // TODO - consider adding CancellationToken handling to Delay?
            {
                if (view != null)
                {
                    // Note that IsInNativeLayout is currently marked for Xamarin internal use only.
                    // If Xamarin ever remove IsInNativeLayout, an alternative might be to wait for
                    // the view.Height property to be non-zero (or wait for a PropertyChanged event
                    // for the Height property)
                    int cycle = 0;
                    while ((!view.IsInNativeLayout) && (++cycle <= maxCycles))
                    {
                        await Task.Delay(TimeSpan.FromMilliseconds(millisecondDelay));
                    }
                }
            }
    
  • jstuardojstuardo ✭✭ Member ✭✭

    Hello @JohnHardman , by placing the ListView inside a Scrollview works except by this initial scroll problem.

    If I don't use scrollview, how can I create a view that allows to scroll if it contains more elements that fits in the screen?

    If you give me a clue I will be very thankful :)

    Regards
    Jaime

  • Amar_BaitAmar_Bait ✭✭✭✭✭ DZMember ✭✭✭✭✭
    edited July 10

    A ListView has already a scroll. If you want to put views before/After the ListView that need to scroll with the ListView, then add them in the ListView Header/Footer

  • JohnHardmanJohnHardman mod GBUniversity mod

    @jstuardo said:
    If I don't use scrollview, how can I create a view that allows to scroll if it contains more elements that fits in the screen?

    I typically design each page to contain just one scrollable view, typically one of ScrollView, WebView or ListView.
    That might mean splitting content across more than one page. It might mean using ListView's Header and/or Footer. It might mean using a DataTemplateSelector and putting things into ViewCells. It might mean (where the number of items is low) using a Layout other than ListView (e.g. StackLayout) and putting that in a ScrollView. It really depends on what the desired result is.

  • jstuardojstuardo ✭✭ Member ✭✭
    edited July 10

    @Amar_Bait ,

    Finally this is the full XAML:

    `<?xml version="1.0" encoding="utf-8" ?>

    <StackLayout Orientation="Vertical" Padding="15">
        <ListView 
            x:Name="PropertiesFin"
            ItemsSource="{Binding Item.Properties}"
            HasUnevenRows="true" 
            VerticalOptions="Start" 
            HorizontalOptions="FillAndExpand">
            <ListView.Header>
                <Image x:Name="ImageFin" />
            </ListView.Header>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="auto" />
                            </Grid.RowDefinitions>
                            <StackLayout Padding="10">
                                <Label Text="{Binding .}" 
                                    LineBreakMode="NoWrap"
                                    Style="{DynamicResource ListItemTextStyle}" 
                                    FontSize="16" />
                            </StackLayout>
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
            <ListView.Footer>
                <mm:VideoView x:Name="VideoFin" VerticalOptions="Start" HeightRequest="190" HorizontalOptions="FillAndExpand" />
                <Button x:Name="BtnPlayStop" VerticalOptions="Start" HorizontalOptions="FillAndExpand" Text="Iniciar Video" Clicked="PlayStop_Clicked" BackgroundColor="Silver" TextColor="White"/>
            </ListView.Footer>
        </ListView>
    </StackLayout>
    

    `

    However, Button element is underlined by Visual Studio and compiler shows the followinng error:

    "The property 'Footer' is set more than once"

    I thought it was due because I have 2 controls inside the footer, so that the system will try to create 2 footers. I changed it to be:

           `<ListView.Footer>
                <Grid>
                    <mm:VideoView x:Name="VideoFin" VerticalOptions="Start" HeightRequest="190" HorizontalOptions="FillAndExpand" />
                    <Button x:Name="BtnPlayStop" VerticalOptions="Start" HorizontalOptions="FillAndExpand" Text="Iniciar Video" Clicked="PlayStop_Clicked" BackgroundColor="Silver" TextColor="White"/>
                </Grid>
            </ListView.Footer>`
    

    That way works, but button appears on top of the video and it seems video appear smaller than the original height.

    What other view can I use instead of Grid?

    Regards
    Jaime

  • JohnHardmanJohnHardman mod GBUniversity mod

    @jstuardo said:
    If you give me a clue I will be very thankful :)

    I gave you a clue (actually, more than one clue) ;-)

Sign In or Register to comment.