protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
            {
                if (_child?.Element == null)
                {
                    SetMeasuredDimension(0, 0);
                    return;
                }

                VisualElement element = _child.Element;

                Context ctx = Context;

                var width = (int)ctx.FromPixels(MeasureSpecFactory.GetSize(widthMeasureSpec));

                SizeRequest request = element.Measure(width, double.PositiveInfinity, MeasureFlags.IncludeMargins);

                Microsoft.Maui.Controls.Compatibility.Layout.LayoutChildIntoBoundingRegion(element, new Rectangle(0, 0, width, request.Request.Height));

                int widthSpec  = MeasureSpecFactory.MakeMeasureSpec((int)ctx.ToPixels(width), MeasureSpecMode.Exactly);
                int heightSpec = MeasureSpecFactory.MakeMeasureSpec((int)ctx.ToPixels(request.Request.Height), MeasureSpecMode.Exactly);

                _child.View.Measure(widthMeasureSpec, heightMeasureSpec);
                SetMeasuredDimension(widthSpec, heightSpec);
            }
        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 Controls.Android.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)Forms.SdkInt >= 18)
            {
                UpdateClipToBounds();
            }

            UpdateClip();

            Performance.Stop(reference);

            //On Width or Height changes, the anchors needs to be updated
            UpdateAnchorX();
            UpdateAnchorY();
        }
Exemple #3
0
        void OnScrollToRequested(object sender, ScrollToRequestedEventArgs e)
        {
            if (!_isAttached)
            {
                _pendingScrollTo = e;
                return;
            }

            Cell cell;
            int  scrollPosition;
            var  scrollArgs = (ITemplatedItemsListScrollToRequestedEventArgs)e;

            var templatedItems = TemplatedItemsView.TemplatedItems;

            if (Element.IsGroupingEnabled)
            {
                var results      = templatedItems.GetGroupAndIndexOfItem(scrollArgs.Group, scrollArgs.Item);
                int indexOfGroup = results.Item1;
                int indexOfItem  = results.Item2;

                if (indexOfGroup == -1)
                {
                    return;
                }

                int itemIndex = indexOfItem == -1 ? 0 : indexOfItem;

                var group = templatedItems.GetGroup(indexOfGroup);
                if (group.Count == 0)
                {
                    cell = group.HeaderContent;
                }
                else
                {
                    cell = group[itemIndex];
                }

                //Increment Scroll Position by 1 when Grouping is enabled. Android offsets position of cells when using header.
                scrollPosition = templatedItems.GetGlobalIndexForGroup(group) + itemIndex + 1;
            }
            else
            {
                scrollPosition = templatedItems.GetGlobalIndexOfItem(scrollArgs.Item);
                if (scrollPosition == -1)
                {
                    return;
                }

                cell = templatedItems[scrollPosition];
            }

            //Android offsets position of cells when using header
            int realPositionWithHeader = scrollPosition + 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 <= scrollPosition && scrollPosition <= Control.LastVisiblePosition)
                {
                    cellHeight = Control.GetChildAt(scrollPosition - first).Height;
                }
                else
                {
                    AView view = _adapter.GetView(scrollPosition, 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);
            }
        }
Exemple #4
0
        public void LayoutView(double x, double y, double width, double height, double?maxWidth = null, double?maxHeight = null)
        {
            if (width == -1)
            {
                width = double.PositiveInfinity;
            }

            if (height == -1)
            {
                height = double.PositiveInfinity;
            }

            Width     = width;
            Height    = height;
            MaxWidth  = maxWidth;
            MaxHeight = maxHeight;
            X         = x;
            Y         = y;

            Context context;

            if (Renderer == null || !(_context.TryGetTarget(out context)) || !Renderer.View.IsAlive())
            {
                return;
            }

            if (View == null)
            {
                var empty = MeasureSpecFactory.GetSize(0);
                Renderer.View.Measure(empty, empty);
                return;
            }

            var request = View.Measure(width, height, MeasureFlags.None);

            var layoutParams = NativeView.LayoutParameters;

            if (double.IsInfinity(height))
            {
                height = request.Request.Height;
            }

            if (double.IsInfinity(width))
            {
                width = request.Request.Width;
            }

            if (height > maxHeight)
            {
                height = maxHeight.Value;
            }

            if (width > maxWidth)
            {
                width = maxWidth.Value;
            }

            if (layoutParams.Width != LP.MatchParent)
            {
                layoutParams.Width = (int)context.ToPixels(width);
            }

            if (layoutParams.Height != LP.MatchParent)
            {
                layoutParams.Height = (int)context.ToPixels(height);
            }

            NativeView.LayoutParameters = layoutParams;
            View.Layout(new Rectangle(x, y, width, height));
            Renderer.UpdateLayout();
        }
Exemple #5
0
        void IPlatformLayout.OnLayout(bool changed, int l, int t, int r, int b)
        {
            if (Page == null)
            {
                return;
            }

            if (changed)
            {
                LayoutRootPage(Page, r - l, b - t);
            }

            GetRenderer(Page)?.UpdateLayout();

            for (var i = 0; i < _renderer.ChildCount; i++)
            {
                AView child = _renderer.GetChildAt(i);
                if (child is ModalContainer)
                {
                    child.Measure(MeasureSpecFactory.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(t - b, MeasureSpecMode.Exactly));
                    child.Layout(l, t, r, b);
                }
            }
        }
        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));


            if (aview is FormsViewGroup formsViewGroup)
            {
                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");
            }
            else if ((aview is LayoutViewGroup || aview is ContentViewGroup || aview is CoordinatorLayout || aview is FragmentContainerView) && width == 0 && height == 0)
            {
                // Nothing to do here; just chill.
            }
            else
            {
                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");
            }

            // We have to make sure to update the ClipBounds to match the new size of the ViewGroup
            UpdateClipToBounds();
            UpdateClip();

            Performance.Stop(reference);

            //On Width or Height changes, the anchors needs to be updated
            UpdateAnchorX();
            UpdateAnchorY();
        }