예제 #1
0
        public static async Task AnimateToItemAsync(ListViewBase list, object targetItem, ScrollToPosition scrollToPosition)
        {
            var scrollViewer = list.GetFirstDescendant <ScrollViewer>();

            if (scrollViewer == null)
            {
                // If ScrollViewer is not found, do nothing.
                return;
            }

            // ScrollToItemAsync will only scroll to the item if it actually exists in the list (that is, it has been
            // been realized and isn't just a virtual item)
            if (await ScrollToItemAsync(list, targetItem, scrollViewer, scrollToPosition))
            {
                // Happy path; the item was already realized and we could just scroll to it
                return;
            }

            // This is the unhappy path. Because of virtualization, the item has not actually been created yet.
            // So we make our best guess about the location of the item
            var targetPoint = await GetApproximateTargetAsync(list, scrollViewer, targetItem);

            // And then we scroll toward that position. The interruptCheck parameter will be run as we're scrolling
            // to see if the item exists yet; if it does, AnimateToOffsetAsync will be canceled and we'll finish
            // off with a smooth scroll to the item
            await AnimateToOffsetAsync(scrollViewer, targetPoint.X, targetPoint.Y,
                                       async() => await ScrollToItemAsync(list, targetItem, scrollViewer, scrollToPosition));
        }
        public static (int firstVisibleItemIndex, int lastVisibleItemIndex, int centerItemIndex) GetVisibleIndexes(ListViewBase listViewBase, ItemsLayoutOrientation itemsLayoutOrientation)
        {
            int firstVisibleItemIndex = -1;
            int lastVisibleItemIndex  = -1;
            int centerItemIndex       = -1;

            var scrollViewer = listViewBase.GetFirstDescendant <ScrollViewer>();
            var presenters   = listViewBase.GetChildren <ListViewItemPresenter>();

            if (presenters != null || scrollViewer == null)
            {
                int count = 0;
                foreach (ListViewItemPresenter presenter in presenters)
                {
                    if (CollectionViewExtensions.IsListViewItemVisible(presenter, scrollViewer, itemsLayoutOrientation))
                    {
                        if (firstVisibleItemIndex == -1)
                        {
                            firstVisibleItemIndex = count;
                        }

                        lastVisibleItemIndex = count;
                    }

                    count++;
                }

                centerItemIndex = (lastVisibleItemIndex + firstVisibleItemIndex) / 2;
            }

            return(firstVisibleItemIndex, lastVisibleItemIndex, centerItemIndex);
        }
예제 #3
0
        async Task JumpTo(ListViewBase list, object targetItem, ScrollToPosition scrollToPosition)
        {
            var tcs = new TaskCompletionSource <object>();

            void ViewChanged(object s, ScrollViewerViewChangedEventArgs e) => tcs.TrySetResult(null);

            var scrollViewer = list.GetFirstDescendant <ScrollViewer>();

            try
            {
                scrollViewer.ViewChanged += ViewChanged;

                if (scrollToPosition == ScrollToPosition.Start)
                {
                    list.ScrollIntoView(targetItem, ScrollIntoViewAlignment.Leading);
                }
                else if (scrollToPosition == ScrollToPosition.MakeVisible)
                {
                    list.ScrollIntoView(targetItem, ScrollIntoViewAlignment.Default);
                }
                else
                {
                    // Center and End are going to be more complicated.
                }

                await tcs.Task;
            }
            finally
            {
                scrollViewer.ViewChanged -= ViewChanged;
            }
        }
예제 #4
0
        public static async Task JumpToItemAsync(ListViewBase list, object targetItem, ScrollToPosition scrollToPosition)
        {
            var scrollViewer = list.GetFirstDescendant <ScrollViewer>();

            var         tcs    = new TaskCompletionSource <object>();
            Func <Task> adjust = null;

            async void ViewChanged(object s, ScrollViewerViewChangedEventArgs e)
            {
                if (e.IsIntermediate)
                {
                    return;
                }

                scrollViewer.ViewChanged -= ViewChanged;

                if (adjust != null)
                {
                    // Handle adjustments for non-natively supported scroll positions
                    await adjust();
                }

                tcs.TrySetResult(null);
            }

            try
            {
                scrollViewer.ViewChanged += ViewChanged;

                switch (scrollToPosition)
                {
                case ScrollToPosition.MakeVisible:
                    list.ScrollIntoView(targetItem, ScrollIntoViewAlignment.Default);
                    break;

                case ScrollToPosition.Start:
                    list.ScrollIntoView(targetItem, ScrollIntoViewAlignment.Leading);
                    break;

                case ScrollToPosition.Center:
                    list.ScrollIntoView(targetItem, ScrollIntoViewAlignment.Leading);
                    adjust = () => AdjustToCenterAsync(list, scrollViewer, targetItem);
                    break;

                case ScrollToPosition.End:
                    list.ScrollIntoView(targetItem, ScrollIntoViewAlignment.Leading);
                    adjust = () => AdjustToEndAsync(list, scrollViewer, targetItem);
                    break;
                }

                await tcs.Task;
            }
            finally
            {
                scrollViewer.ViewChanged -= ViewChanged;
            }
        }
예제 #5
0
        async Task AnimateTo(ListViewBase list, object targetItem, ScrollToPosition scrollToPosition)
        {
            var scrollViewer = list.GetFirstDescendant <ScrollViewer>();

            var targetContainer = list.ContainerFromItem(targetItem) as UIElement;

            if (targetContainer == null)
            {
                var horizontalOffset = scrollViewer.HorizontalOffset;
                var verticalOffset   = scrollViewer.VerticalOffset;

                await JumpTo(list, targetItem, scrollToPosition);

                targetContainer = list.ContainerFromItem(targetItem) as UIElement;
                await ChangeViewAsync(scrollViewer, horizontalOffset, verticalOffset, true);
            }

            if (targetContainer == null)
            {
                // Did not find the target item anywhere
                return;
            }

            // TODO hartez 2018/10/04 16:37:35 Okay, this sort of works for vertical lists but fails totally on horizontal lists.
            var transform = targetContainer.TransformToVisual(scrollViewer.Content as UIElement);
            var position  = transform?.TransformPoint(new Windows.Foundation.Point(0, 0));

            if (!position.HasValue)
            {
                return;
            }

            // TODO hartez 2018/10/05 17:23:23 The animated scroll works fine vertically if we are scrolling to a greater Y offset.
            // If we're scrolling back up to a lower Y offset, it just gives up and sends us to 0 (first item)
            // Works fine if we disable animation, but that's not very helpful

            scrollViewer.ChangeView(position.Value.X, position.Value.Y, null, false);

            //if (scrollToPosition == ScrollToPosition.End)
            //{
            //	// Modify position
            //}
            //else if (scrollToPosition == ScrollToPosition.Center)
            //{
            //	// Modify position
            //}
            //else
            //{

            //}
        }
예제 #6
0
        internal static void JumpToIndexAsync(ListViewBase list, int index, ScrollToPosition scrollToPosition)
        {
            var scrollViewer = list.GetFirstDescendant <ScrollViewer>();
            var con          = list.ContainerFromIndex(index);

            if (con is UIElement uIElement)
            {
                var width = uIElement.DesiredSize.Width;

                var current = scrollViewer.HorizontalOffset;
                var delta   = (index * width) - current;

                scrollViewer.ChangeView(current + delta, scrollViewer.VerticalOffset, scrollViewer.ZoomFactor, true);
            }
        }
예제 #7
0
        public static (int firstVisibleItemIndex, int lastVisibleItemIndex, int centerItemIndex) GetVisibleIndexes(this ListViewBase listViewBase, ItemsLayoutOrientation itemsLayoutOrientation, bool goingNext)
        {
            int firstVisibleItemIndex = -1;
            int lastVisibleItemIndex  = -1;

            var itemsPanel = (listViewBase.ItemsPanelRoot as ItemsStackPanel);

            if (itemsPanel != null)
            {
                firstVisibleItemIndex = itemsPanel.FirstVisibleIndex;
                lastVisibleItemIndex  = itemsPanel.LastVisibleIndex;
            }
            else
            {
                var scrollViewer = listViewBase.GetFirstDescendant <ScrollViewer>();
                var presenters   = listViewBase.GetChildren <ListViewItemPresenter>();

                if (presenters != null || scrollViewer == null)
                {
                    int count = 0;
                    foreach (ListViewItemPresenter presenter in presenters)
                    {
                        if (IsListViewItemVisible(presenter, scrollViewer, itemsLayoutOrientation))
                        {
                            if (firstVisibleItemIndex == -1)
                            {
                                firstVisibleItemIndex = count;
                            }

                            lastVisibleItemIndex = count;
                        }

                        count++;
                    }
                }
            }

            double center          = (lastVisibleItemIndex + firstVisibleItemIndex) / 2.0;
            int    centerItemIndex = goingNext ? (int)Math.Ceiling(center) : (int)Math.Floor(center);

            return(firstVisibleItemIndex, lastVisibleItemIndex, centerItemIndex);
        }
예제 #8
0
        void FindScrollViewer(ListViewBase listView)
        {
            var scrollViewer = listView.GetFirstDescendant <ScrollViewer>();

            if (scrollViewer != null)
            {
                OnScrollViewerFound(scrollViewer);
                return;
            }

            void ListViewLoaded(object sender, RoutedEventArgs e)
            {
                var lv = (ListViewBase)sender;

                lv.Loaded -= ListViewLoaded;
                FindScrollViewer(listView);
            }

            listView.Loaded += ListViewLoaded;
        }
예제 #9
0
        protected virtual void FindScrollViewer(ListViewBase listView)
        {
            var scrollViewer = listView.GetFirstDescendant <ScrollViewer>();

            if (scrollViewer != null)
            {
                _scrollViewer              = scrollViewer;
                _scrollViewer.ViewChanged += OnScrollViewChanged;
                return;
            }

            void ListViewLoaded(object sender, RoutedEventArgs e)
            {
                var lv = (ListViewBase)sender;

                lv.Loaded -= ListViewLoaded;
                FindScrollViewer(listView);
            }

            listView.Loaded += ListViewLoaded;
        }
예제 #10
0
        void OnListSizeChanged(object sender, Windows.UI.Xaml.SizeChangedEventArgs e)
        {
            var newSize = e.NewSize;

            _carouselHeight = newSize.Height;
            _carouselWidth  = newSize.Width;

            _scrollViewer = ListViewBase.GetFirstDescendant <ScrollViewer>();

            if (_scrollViewer != null)
            {
                // TODO: jsuarezruiz This breaks the ScrollTo override. Review it.
                _scrollViewer.ViewChanging += OnScrollViewChanging;
                _scrollViewer.ViewChanged  += OnScrollViewChanged;
            }

            UpdateItemsSource();
            UpdateItemTemplate();
            UpdateIsSwipeEnabled();
            UpdateIsBounceEnabled();
        }
예제 #11
0
        protected override void FindScrollViewer(ListViewBase listView)
        {
            var scrollViewer = listView.GetFirstDescendant <ScrollViewer>();

            if (scrollViewer != null)
            {
                _scrollViewer = scrollViewer;
                // TODO: jsuarezruiz This breaks the ScrollTo override. Review it.
                _scrollViewer.ViewChanging += OnScrollViewChanging;
                _scrollViewer.ViewChanged  += OnScrollViewChanged;
                return;
            }

            void ListViewLoaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
            {
                var lv = (ListViewBase)sender;

                lv.Loaded -= ListViewLoaded;
                FindScrollViewer(listView);
            }

            listView.Loaded += ListViewLoaded;
        }