コード例 #1
0
        public void UpdateMarkerLayout()
        {
            var view           = Element;
            var _context       = Context;
            var headlessOffset = CompressedLayout.GetHeadlessOffset(view);
            var x      = (int)_context.ToPixels(view.X + headlessOffset.X);
            var y      = (int)_context.ToPixels(view.Y + headlessOffset.Y);
            var size   = view.Measure(double.PositiveInfinity, double.PositiveInfinity, MeasureFlags.IncludeMargins);
            var width  = Math.Max(0, (int)_context.ToPixels(size.Request.Width));
            var height = Math.Max(0, (int)_context.ToPixels(size.Request.Height));

            Measure(MeasureSpec.MakeMeasureSpec(width, Android.Views.MeasureSpecMode.Unspecified), MeasureSpec.MakeMeasureSpec(height, Android.Views.MeasureSpecMode.Unspecified));
            Layout(x, y, x + width, y + height);
        }
コード例 #2
0
        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 && 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");
            }

            // 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();
        }
コード例 #3
0
        public void UpdateLayout()
        {
            var reference = Guid.NewGuid().ToString();

            Performance.Start(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)Build.VERSION.SdkInt >= 18)
            {
                UpdateClipToBounds();
            }

            Performance.Stop(reference);

            //On Width or Height changes, the anchors needs to be updated
            UpdateAnchorX();
            UpdateAnchorY();
        }
コード例 #4
0
        public void UpdateLayout()
        {
            var reference = Guid.NewGuid().ToString();

            Performance.Start(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");
            }

            Performance.Stop(reference);

            //On Width or Height changes, the anchors needs to be updated
            UpdateAnchorX();
            UpdateAnchorY();
        }
コード例 #5
0
        void OnUpdateNativeControl(CALayer caLayer)
        {
            var view   = Renderer.Element;
            var uiview = Renderer.NativeView;

            if (view == null || view.Batched)
            {
                return;
            }

            bool shouldInteract;

            if (view is Layout layout)
            {
                if (layout.InputTransparent)
                {
                    shouldInteract = !layout.CascadeInputTransparent;
                }
                else
                {
                    shouldInteract = layout.IsEnabled;
                }
            }
            else
            {
                shouldInteract = !view.InputTransparent && view.IsEnabled;
            }

            if (_isInteractive != shouldInteract)
            {
#if __MOBILE__
                uiview.UserInteractionEnabled = shouldInteract;
#endif
                _isInteractive = shouldInteract;
            }

            var boundsChanged = _lastBounds != view.Bounds && TrackFrame;
#if !__MOBILE__
            var viewParent          = view.RealParent as VisualElement;
            var parentBoundsChanged = _lastParentBounds != (viewParent == null ? Rectangle.Zero : viewParent.Bounds);
#else
            var thread = !boundsChanged && !caLayer.Frame.IsEmpty && Application.Current?.OnThisPlatform()?.GetHandleControlUpdatesOnMainThread() == false;
#endif
            var anchorX      = (float)view.AnchorX;
            var anchorY      = (float)view.AnchorY;
            var translationX = (float)view.TranslationX;
            var translationY = (float)view.TranslationY;
            var rotationX    = (float)view.RotationX;
            var rotationY    = (float)view.RotationY;
            var rotation     = (float)view.Rotation;
            var scale        = (float)view.Scale;
            var scaleX       = (float)view.ScaleX * scale;
            var scaleY       = (float)view.ScaleY * scale;
            var width        = (float)view.Width;
            var height       = (float)view.Height;
            var x            = (float)view.X + (float)CompressedLayout.GetHeadlessOffset(view).X;
            var y            = (float)view.Y + (float)CompressedLayout.GetHeadlessOffset(view).Y;
            var opacity      = (float)view.Opacity;
            var isVisible    = view.IsVisible;

            var updateTarget = Interlocked.Increment(ref _updateCount);

            void update()
            {
                if (updateTarget != _updateCount)
                {
                    return;
                }
#if __MOBILE__
                var visualElement = view;
#endif
                var parent = view.RealParent;

                var shouldRelayoutSublayers = false;
                if (isVisible && caLayer.Hidden)
                {
#if !__MOBILE__
                    uiview.Hidden = false;
#endif
                    caLayer.Hidden = false;
                    if (!caLayer.Frame.IsEmpty)
                    {
                        shouldRelayoutSublayers = true;
                    }
                }

                if (!isVisible && !caLayer.Hidden)
                {
#if !__MOBILE__
                    uiview.Hidden = true;
#endif
                    caLayer.Hidden          = true;
                    shouldRelayoutSublayers = true;
                }

                // ripe for optimization
                var transform = CATransform3D.Identity;

#if __MOBILE__
                bool shouldUpdate = (!(visualElement is Page) || visualElement is ContentPage) && width > 0 && height > 0 && parent != null && boundsChanged;
#else
                // We don't care if it's a page or not since bounds of the window can change
                // TODO: Find why it doesn't work to check if the parentsBounds changed  and remove true;
                parentBoundsChanged = true;
                bool shouldUpdate = width > 0 && height > 0 && parent != null && (boundsChanged || parentBoundsChanged);
#endif
                // Dont ever attempt to actually change the layout of a Page unless it is a ContentPage
                // iOS is a really big fan of you not actually modifying the View's of the UIViewControllers
                if (shouldUpdate && TrackFrame)
                {
#if __MOBILE__
                    var target = new RectangleF(x, y, width, height);
#else
                    var   visualParent = parent as VisualElement;
                    float newY         = visualParent == null ? y : Math.Max(0, (float)(visualParent.Height - y - view.Height));
                    var   target       = new RectangleF(x, newY, width, height);
#endif

                    // must reset transform prior to setting frame...
                    caLayer.Transform = transform;
                    uiview.Frame      = target;
                    if (shouldRelayoutSublayers)
                    {
                        caLayer.LayoutSublayers();
                    }
                }
                else if (width <= 0 || height <= 0)
                {
                    //TODO: FInd why it doesn't work
#if __MOBILE__
                    caLayer.Hidden = true;
#endif
                    return;
                }
#if __MOBILE__
                caLayer.AnchorPoint = new PointF(anchorX, anchorY);
#else
                caLayer.AnchorPoint = new PointF(anchorX - 0.5f, anchorY - 0.5f);
#endif
                caLayer.Opacity = opacity;
                const double epsilon = 0.001;

                // position is relative to anchor point
                if (Math.Abs(anchorX - .5) > epsilon)
                {
                    transform = transform.Translate((anchorX - .5f) * width, 0, 0);
                }
                if (Math.Abs(anchorY - .5) > epsilon)
                {
                    transform = transform.Translate(0, (anchorY - .5f) * height, 0);
                }

                if (Math.Abs(translationX) > epsilon || Math.Abs(translationY) > epsilon)
                {
                    transform = transform.Translate(translationX, translationY, 0);
                }

                if (Math.Abs(scaleX - 1) > epsilon || Math.Abs(scaleY - 1) > epsilon)
                {
                    transform = transform.Scale(scaleX, scaleY, scale);
                }

                // not just an optimization, iOS will not "pixel align" a view which has m34 set
                if (Math.Abs(rotationY % 180) > epsilon || Math.Abs(rotationX % 180) > epsilon)
                {
                    transform.m34 = 1.0f / -400f;
                }

                if (Math.Abs(rotationX % 360) > epsilon)
                {
                    transform = transform.Rotate(rotationX * (float)Math.PI / 180.0f, 1.0f, 0.0f, 0.0f);
                }
                if (Math.Abs(rotationY % 360) > epsilon)
                {
                    transform = transform.Rotate(rotationY * (float)Math.PI / 180.0f, 0.0f, 1.0f, 0.0f);
                }

                transform = transform.Rotate(rotation * (float)Math.PI / 180.0f, 0.0f, 0.0f, 1.0f);

                if (Foundation.NSThread.IsMain)
                {
                    caLayer.Transform = transform;
                    return;
                }
                CoreFoundation.DispatchQueue.MainQueue.DispatchAsync(() =>
                {
                    caLayer.Transform = transform;
                });
            }

#if __MOBILE__
            if (thread)
            {
                CADisplayLinkTicker.Default.Invoke(update);
            }
            else
            {
                update();
            }
#else
            update();
#endif

            _lastBounds = view.Bounds;
#if !__MOBILE__
            _lastParentBounds = viewParent?.Bounds ?? Rectangle.Zero;
#endif
        }