Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
70 views
in Technique[技术] by (71.8m points)

c# - Bind object to scollevent and scroll with up and down movement

So I have tried to achieve the following affect:

imagine you have a long list with items and a header that is constantly visible to you when you scroll through the list. This header just takes up space. Some apps handle it with the header only being visible, when the user scrolls back up. When the user scroll down the header just moves itself out of the view. I was close with getting this effect done:

 private void listview_allAds_Scrolled(object sender, ScrolledEventArgs e)
        {
            double heightOfScrollView = scrollview_header.Height;
           
            if (e.ScrollY < oldValue)
            {
                isScrollingUp = true;
                oldValue = e.ScrollY;
            }
            else
            {
                isScrollingUp = false;
                oldValue = e.ScrollY;
            }
           
            if (isScrollingUp)
            {
                Debug.WriteLine("Up");
           
                if (!isHeaderBack)
                {
                    if (scrollview_header.TranslationY <= 0)
                    {
                        scrollview_header.TranslationY = -e.ScrollY - scrollview_header.TranslationY;
                        isHeaderBack = false;
                    }
                    else
                    {
                        isHeaderBack = true;
                        scrollview_header.TranslationY = 0;
                        //stop
                    }
                }
                               
            }
            else
            {
                Debug.WriteLine("Down");
           
                if (e.ScrollY <= heightOfScrollView)
                {
                    scrollview_header.TranslationY = -e.ScrollY;
                    isHeaderBack = false;
                }
                else
                {
                    isHeaderBack = false;
                    // stop
                }
            }
        }

So, I have two elements a ListView that is calling this function whenever it is scrolled and a header scrollview_header.

But the result seems glitchy:

https://im5.ezgif.com/tmp/ezgif-5-144e3fbffbaa.gif

You see, the header is bugging out a bit, but only on the part where i scroll up again.

Can you fix this issue? it is probably my math...

question from:https://stackoverflow.com/questions/65907284/bind-object-to-scollevent-and-scroll-with-up-and-down-movement

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If the header View is a StackLayout as follows:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="35" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <StackLayout x:Name="stackLayout"
                 Grid.Row="0">
        ...
    </StackLayout>
    <ListView x:Name="listView"
              ItemsSource="{Binding Items}" 
              Grid.Row="1">
        <ListView.ItemTemplate>
            ...
        </ListView.ItemTemplate>
    </ListView>
</Grid>

Xamarin.Forms ListView provides an OnItemAppearing event you can subscribe to. With this you can track your scroll direction by finding the index of the item that appeared and comparing it to the last item that appeared. Try something like this:

public partial class MainPage : ContentPage
{
    public ObservableCollection<MyItemType> Items { get; set; } = new ObservableCollection<MyItemType>();
    int lastItemIndex;
    int currentItemIndex;

    public MainPage()
    {
        ...
        listView.ItemAppearing += ListView_ItemAppearing;
    }

    async void ListView_ItemAppearing(object sender, ItemVisibilityEventArgs e)
    {
        MyItemType item = e.Item as MyItemType;

        currentItemIndex = Items.IndexOf(item);
        if (currentItemIndex > lastItemIndex)
        {
            await stackLayout.FadeTo(0, 1000);
            stackLayout.IsVisible = false;
        }
        else
        {
            stackLayout.IsVisible = true;
            await stackLayout.FadeTo(1, 1000);
        }
        lastItemIndex = currentItemIndex;
    }
}

Note: Flickering is really due to ListView being resized when the StackLayout shows and hides, so make sure that the ListView is not getting resized. Perhaps put the ListView and the StackLayout in a grid so that when you show and hide the StackLayout the ListView does not get resized


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...