private (View itemContainer, Rectangle childLocation) GetItemContainerLocationByindex(double width, int index, double yOffset, ref bool doMeasureInvalidation) { View itemContainer = null; if (ItemsGenerator.HasItemViewGenerated(index)) { itemContainer = ItemsGenerator.GetItemViewFromIndex(index); } else { itemContainer = ItemsGenerator.GenerateItemView(index); } // Add child to layout because then style will activate if (Children.Contains(itemContainer) == false) { Children.Add(itemContainer); doMeasureInvalidation = true; } Rectangle childLocation = new Rectangle(); if (IsRecycleEnabled) { SizeRequest itemSize = itemContainer.Measure(width, double.PositiveInfinity, MeasureFlags.IncludeMargins); childLocation = new Rectangle(0, yOffset, width, itemSize.Request.Height); if (_locations.ContainsKey(itemContainer)) { _locations[itemContainer] = childLocation; } else { _locations.Add(itemContainer, childLocation); } } else if (_locations.TryGetValue(itemContainer, out childLocation) == false) { SizeRequest itemSize = itemContainer.Measure(width, double.PositiveInfinity, MeasureFlags.IncludeMargins); childLocation = new Rectangle(0, yOffset, width, itemSize.Request.Height); _locations.Add(itemContainer, childLocation); } else { childLocation = new Rectangle(0, yOffset, width, _locations[itemContainer].Height); _locations[itemContainer] = childLocation; } return(itemContainer, childLocation); }
/// <summary> /// Close all submenus /// </summary> public void CloseSubMenus() { for (int i = 0; i < ItemsGenerator.TotalItemsCount; i++) { if (ItemsGenerator.HasItemViewGenerated(i)) { View itemContainer = ItemsGenerator.GetItemViewFromIndex(i); if (itemContainer is MenuButton menuButton) { menuButton.IsOpen = false; } } } }
protected override void OnSelectionModeChanged(SelectionModes oldValue, SelectionModes newValue) { base.OnSelectionModeChanged(oldValue, newValue); for (int i = 0; i < ItemsGenerator.TotalItemsCount; i++) { if (ItemsGenerator.HasItemViewGenerated(i)) { View item = ItemsGenerator.GetItemViewFromIndex(i); InitializeItem(item); if (_leftPadding != null) { SetLeftPadding(item, _leftPadding.Value); } } } }
/// <summary> /// Do filter with search key string /// </summary> public void DoFilter(string searchKey) { for (int i = 0; i < ItemsGenerator.TotalItemsCount; i++) { if (ItemsGenerator.HasItemViewGenerated(i)) { View itemContainer = ItemsGenerator.GetItemViewFromIndex(i); if ((itemContainer is IFilter filterItem && filterItem.IsFiltered(searchKey) == true) || (itemContainer.BindingContext is IFilter filterItemModel && filterItemModel.IsFiltered(searchKey) == true)) { itemContainer.IsVisible = false; } else { itemContainer.IsVisible = true; } } }
/// <summary> /// Set items left padding /// </summary> /// <param name="padding"></param> public void SetItemsLeftPadding(double padding) { bool wasChanged = _leftPadding != null; _leftPadding = padding; for (int i = 0; i < ItemsGenerator.TotalItemsCount; i++) { if (ItemsGenerator.HasItemViewGenerated(i)) { View item = ItemsGenerator.GetItemViewFromIndex(i); if (_leftPadding != null) { SetLeftPadding(item, padding); } else if (wasChanged && item is Button button) { button.ClearValue(Button.PaddingProperty); } } } }
/// <summary> /// Update visible items based on items measured or estimated size and scroll info. /// </summary> private void UpdateVisibleItems(double width, double scrollDelta) { _ignoreInvalidation = true; bool doMeasureInvalidation = false; double yOffset = _firstVisibleItemOffset; double firstVisibleItemHeight = 0; _visibleItems.Clear(); _currentStickyElement = null; _nextStickyElement = null; if (scrollDelta <= 0) { for (int i = _firstVisibleItemIndex; i < ItemsGenerator.TotalItemsCount; i++) { (View itemContainer, Rectangle childLocation) = GetItemContainerLocationByindex(width, i, yOffset, ref doMeasureInvalidation); // Set current sticky element if (GetIsSticky(itemContainer)) { _currentStickyElement = itemContainer; } _firstVisibleItemIndex = i; yOffset += childLocation.Height; if (yOffset >= VerticalOffset - _viewportOverflowLenght) { _visibleItems.Add(itemContainer); if (Children.Contains(itemContainer) == false) { Children.Add(itemContainer); doMeasureInvalidation = true; } ItemsGenerator.SetRealized(i); LayoutChild(itemContainer, childLocation); firstVisibleItemHeight = childLocation.Height; break; } // Remove container from children if not visible else if (Children.Contains(itemContainer) && itemContainer != _currentStickyElement) { if (IsRecycleEnabled == false) { Children.Remove(itemContainer); } ItemsGenerator.SetVirtualized(i); } _firstVisibleItemOffset = yOffset; } } else { for (int i = _firstVisibleItemIndex; i >= 0; i--) { (View itemContainer, Rectangle childLocation) = GetItemContainerLocationByindex(width, i, yOffset, ref doMeasureInvalidation); // Set current sticky element if (GetIsSticky(itemContainer)) { _currentStickyElement = itemContainer; } _firstVisibleItemIndex = i; yOffset -= childLocation.Height; if (yOffset + childLocation.Height <= VerticalOffset - _viewportOverflowLenght || i == 0) { _visibleItems.Add(itemContainer); if (Children.Contains(itemContainer) == false) { Children.Add(itemContainer); doMeasureInvalidation = true; } ItemsGenerator.SetRealized(i); LayoutChild(itemContainer, childLocation); firstVisibleItemHeight = childLocation.Height; break; } // Remove container from children if not visible else if (Children.Contains(itemContainer) && itemContainer != _currentStickyElement) { if (IsRecycleEnabled == false) { Children.Remove(itemContainer); } ItemsGenerator.SetVirtualized(i); } _firstVisibleItemOffset = yOffset; } _firstVisibleItemOffset = Math.Max(0, _firstVisibleItemOffset); } int lastVisibleItemIndex = _firstVisibleItemIndex; yOffset = _firstVisibleItemOffset + firstVisibleItemHeight; // Set items visible until viewport is ended for (int i = _firstVisibleItemIndex + 1; i < ItemsGenerator.TotalItemsCount; i++) { if (yOffset >= VerticalOffset + ViewportSize.Height + _viewportOverflowLenght) { break; } (View itemContainer, Rectangle childLocation) = GetItemContainerLocationByindex(width, i, yOffset, ref doMeasureInvalidation); // Get next sticky elements if (_nextStickyElement == null && _currentStickyElement != null && itemContainer != _currentStickyElement && GetIsSticky(itemContainer)) { _nextStickyElement = itemContainer; } LayoutChild(itemContainer, childLocation); _visibleItems.Add(itemContainer); lastVisibleItemIndex = i; yOffset += childLocation.Height; ItemsGenerator.SetRealized(i); } // Remove items after viewport for (int i = lastVisibleItemIndex + 1; i < ItemsGenerator.TotalItemsCount; i++) { if (ItemsGenerator.HasItemViewGenerated(i)) { View itemContainer = ItemsGenerator.GetItemViewFromIndex(i); if (Children.Contains(itemContainer) && IsRecycleEnabled == false) { Children.Remove(itemContainer); } ItemsGenerator.SetVirtualized(i); } else { break; } } if (_currentStickyElement != null) { RaiseChild(_currentStickyElement); } _ignoreInvalidation = false; if (doMeasureInvalidation && scrollDelta.Equals(0)) { InvalidateMeasure(); InvalidateLayout(); } }