void OnScrollToRequested(object sender, ScrollToRequestedEventArgs e) { if (!_isAttached) { _pendingScrollTo = e; return; } Cell cell; int position; var scrollArgs = (ITemplatedItemsListScrollToRequestedEventArgs)e; var templatedItems = TemplatedItemsView.TemplatedItems; if (Element.IsGroupingEnabled) { var results = templatedItems.GetGroupAndIndexOfItem(scrollArgs.Group, scrollArgs.Item); if (results.Item1 == -1 || results.Item2 == -1) { return; } var group = templatedItems.GetGroup(results.Item1); cell = group[results.Item2]; position = templatedItems.GetGlobalIndexForGroup(group) + results.Item2 + 1; } else { position = templatedItems.GetGlobalIndexOfItem(scrollArgs.Item); if (position == -1) { return; } cell = templatedItems[position]; } //Android offsets position of cells when using header int realPositionWithHeader = position + 1; if (e.Position == ScrollToPosition.MakeVisible) { if (e.ShouldAnimate) { Control.SmoothScrollToPosition(realPositionWithHeader); } else { Control.SetSelection(realPositionWithHeader); } return; } int height = Control.Height; var cellHeight = (int)cell.RenderHeight; if (cellHeight == -1) { int first = Control.FirstVisiblePosition; if (first <= position && position <= Control.LastVisiblePosition) { cellHeight = Control.GetChildAt(position - first).Height; } else { AView view = _adapter.GetView(position, null, null); view.Measure(MeasureSpecFactory.MakeMeasureSpec(Control.Width, MeasureSpecMode.AtMost), MeasureSpecFactory.MakeMeasureSpec(0, MeasureSpecMode.Unspecified)); cellHeight = view.MeasuredHeight; } } var y = 0; if (e.Position == ScrollToPosition.Center) { y = height / 2 - cellHeight / 2; } else if (e.Position == ScrollToPosition.End) { y = height - cellHeight; } if (e.ShouldAnimate) { Control.SmoothScrollToPositionFromTop(realPositionWithHeader, y); } else { Control.SetSelectionFromTop(realPositionWithHeader, y); } }
public void UpdateLayout() { Performance.Start(out string reference); VisualElement view = _renderer.Element; AView aview = _renderer.View; var headlessOffset = CompressedLayout.GetHeadlessOffset(view); var x = (int)_context.ToPixels(view.X + headlessOffset.X); var y = (int)_context.ToPixels(view.Y + headlessOffset.Y); var width = Math.Max(0, (int)_context.ToPixels(view.Width)); var height = Math.Max(0, (int)_context.ToPixels(view.Height)); var formsViewGroup = aview as FormsViewGroup; if (formsViewGroup == null) { Performance.Start(reference, "Measure"); aview.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(height, MeasureSpecMode.Exactly)); Performance.Stop(reference, "Measure"); Performance.Start(reference, "Layout"); aview.Layout(x, y, x + width, y + height); Performance.Stop(reference, "Layout"); } else { Performance.Start(reference, "MeasureAndLayout"); formsViewGroup.MeasureAndLayout(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(height, MeasureSpecMode.Exactly), x, y, x + width, y + height); Performance.Stop(reference, "MeasureAndLayout"); } // If we're running sufficiently new Android, we have to make sure to update the ClipBounds to // match the new size of the ViewGroup if ((int)System.Maui.Maui.SdkInt >= 18) { UpdateClipToBounds(); } Performance.Stop(reference); //On Width or Height changes, the anchors needs to be updated UpdateAnchorX(); UpdateAnchorY(); }
protected override void OnLayout(bool changed, int l, int t, int r, int b) { base.OnLayout(changed, l, t, r, b); if (_viewPager != null) { _viewPager.Measure(MeasureSpecFactory.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(b - t, MeasureSpecMode.Exactly)); _viewPager.Layout(0, 0, r - l, b - t); } }