private void SetNativeDockRegion( NativeView nativeView, DockRegion dockRegion) { if (null == nativeView) { throw new ArgumentNullException(nameof(nativeView)); } var layoutParameters = (NativeDockLayout.LayoutParams)nativeView.LayoutParameters(); layoutParameters.DockRegion = dockRegion; }
protected override void OnLayout( bool changed, float left, float top, float right, float bottom) { var layoutProperties = this.LayoutProperties(); Rectangle remainingRect = new Rectangle( layoutProperties.Padding.Left, layoutProperties.Padding.Top, right - left - layoutProperties.Padding.Left - layoutProperties.Padding.Right, bottom - top - layoutProperties.Padding.Top - layoutProperties.Padding.Bottom); int childCount = this.ChildCount; for (int i = 0; i < childCount; i += 1) { NativeView child = this.GetChildAt(i); if (child.Hidden) { continue; } var layoutParams = (LayoutParams)child.LayoutParameters(); var dockRegion = layoutParams.DockRegion; // Arrange all but the center elements in the first pass if (dockRegion != DockRegion.CenterOverlay) { Rectangle arrangeRect = remainingRect; Size childUsedSize = GetChildUsedSizeWithMargins(child, layoutParams); if (dockRegion == DockRegion.Left) { arrangeRect.Width = childUsedSize.Width; remainingRect.X += childUsedSize.Width; remainingRect.Width = Math.Max(0, remainingRect.Width - childUsedSize.Width); } else if (dockRegion == DockRegion.LeftOverlay) { arrangeRect.Width = childUsedSize.Width; } else if (dockRegion == DockRegion.Top) { arrangeRect.Height = childUsedSize.Height; remainingRect.Y += childUsedSize.Height; remainingRect.Height = Math.Max(0, remainingRect.Height - childUsedSize.Height); } else if (dockRegion == DockRegion.TopOverlay) { arrangeRect.Height = childUsedSize.Height; } else if (dockRegion == DockRegion.Right) { arrangeRect.X = remainingRect.Right - childUsedSize.Width; arrangeRect.Width = childUsedSize.Width; remainingRect.Width = Math.Max(0, remainingRect.Width - childUsedSize.Width); } else if (dockRegion == DockRegion.RightOverlay) { arrangeRect.X = remainingRect.Right - childUsedSize.Width; arrangeRect.Width = childUsedSize.Width; } else if (dockRegion == DockRegion.Bottom) { arrangeRect.Y = remainingRect.Bottom - childUsedSize.Height; arrangeRect.Height = childUsedSize.Height; remainingRect.Height = Math.Max(0, remainingRect.Height - childUsedSize.Height); } else if (dockRegion == DockRegion.BottomOverlay) { arrangeRect.Y = remainingRect.Bottom - childUsedSize.Height; arrangeRect.Height = childUsedSize.Height; } else { throw new NotSupportedException("Unsupported dock region."); } this.LayoutChild(child, layoutParams, arrangeRect); } } // Arrange the center elements now that the center rectangle has been calculated for (int i = 0; i < childCount; i += 1) { NativeView child = this.GetChildAt(i); if (child.Hidden) { continue; } var layoutParams = (LayoutParams)child.LayoutParameters(); // Arrange only the center elements in the second pass if (layoutParams.DockRegion != DockRegion.CenterOverlay) { continue; } this.LayoutChild(child, layoutParams, remainingRect); } }
protected override void OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec) { var layoutProperties = this.LayoutProperties(); Size availableSize = new Size( widthMeasureSpec.Size - layoutProperties.Padding.Left - layoutProperties.Padding.Right, heightMeasureSpec.Size - layoutProperties.Padding.Top - layoutProperties.Padding.Bottom); // Keep track of the space used by children float usedLeft = 0; float usedTop = 0; float usedRight = 0; float usedBottom = 0; // Keep track of the starting point for measuring each dimension // in support of overlay regions float startLeft = 0; float startTop = 0; float startRight = 0; float startBottom = 0; float minWidth = 0; float minHeight = 0; var remainingSize = availableSize; var childWidthState = MeasuredStateFlags.None; var childHeightState = MeasuredStateFlags.None; int childCount = this.ChildCount; for (int i = 0; i < childCount; i += 1) { NativeView child = this.GetChildAt(i); if (child.Hidden) { continue; } var layoutParams = (LayoutParams)child.LayoutParameters(); var dockRegion = layoutParams.DockRegion; // Arrange all but the center elements if (dockRegion != DockRegion.CenterOverlay) { LayoutAxis axis = GetLayoutAxis(dockRegion); // Save the child width and height var childWidth = layoutParams.Width; var childHeight = layoutParams.Height; // Overwrite child MatchParent size on the stacking axis if ((axis == LayoutAxis.Horizontal) && (childWidth == LayoutParams.MatchParent)) { childWidth = LayoutParams.WrapContent; } else if ((axis == LayoutAxis.Vertical) && (childHeight == LayoutParams.MatchParent)) { childHeight = LayoutParams.WrapContent; } // Measure the child this.MeasureChildWithMarginsOverride( child, widthMeasureSpec, usedLeft + usedRight, childWidth, heightMeasureSpec, usedTop + usedBottom, childHeight); Size childUsedSize = GetChildUsedSizeWithMargins(child, layoutParams); if (dockRegion == DockRegion.Left) { usedLeft = Math.Max(usedLeft, startLeft + childUsedSize.Width); startLeft += childUsedSize.Width; minHeight = Math.Max(minHeight, usedTop + usedBottom + childUsedSize.Height); } else if (dockRegion == DockRegion.LeftOverlay) { usedLeft = Math.Max(usedLeft, startLeft + childUsedSize.Width); minHeight = Math.Max(minHeight, usedTop + usedBottom + childUsedSize.Height); } else if (dockRegion == DockRegion.Top) { usedTop = Math.Max(usedTop, startTop + childUsedSize.Height); startTop += childUsedSize.Height; minWidth = Math.Max(minWidth, usedLeft + usedRight + childUsedSize.Width); } else if (dockRegion == DockRegion.TopOverlay) { usedTop = Math.Max(usedTop, startTop + childUsedSize.Height); minWidth = Math.Max(minWidth, usedLeft + usedRight + childUsedSize.Width); } else if (dockRegion == DockRegion.Right) { usedRight = Math.Max(usedRight, startRight + childUsedSize.Width); startRight += childUsedSize.Width; minHeight = Math.Max(minHeight, usedTop + usedBottom + childUsedSize.Height); } else if (dockRegion == DockRegion.RightOverlay) { usedRight = Math.Max(usedRight, startRight + childUsedSize.Width); minHeight = Math.Max(minHeight, usedTop + usedBottom + childUsedSize.Height); } else if (dockRegion == DockRegion.Bottom) { usedBottom = Math.Max(usedBottom, startBottom + childUsedSize.Height); startBottom += childUsedSize.Height; minWidth = Math.Max(minWidth, usedLeft + usedRight + childUsedSize.Width); } else if (dockRegion == DockRegion.BottomOverlay) { usedBottom = Math.Max(usedBottom, startBottom + childUsedSize.Height); minWidth = Math.Max(minWidth, usedLeft + usedRight + childUsedSize.Width); } else { throw new NotSupportedException("Unsupported dock region."); } // Update the remaining size remainingSize = new Size( (float)Math.Max(0, availableSize.Width - startLeft - startRight), (float)Math.Max(0, availableSize.Height - startTop - startBottom)); // Update the child state childWidthState |= child.LayoutProperties().MeasuredSize.WidthState; childHeightState |= child.LayoutProperties().MeasuredSize.HeightState; } } // Measure the center elements now that the center size has been completely calculated Size usedCenterSize = new Size(0, 0); for (int i = 0; i < childCount; i += 1) { NativeView child = this.GetChildAt(i); if (child.Hidden) { continue; } var layoutParams = (LayoutParams)child.LayoutParameters(); var dockRegion = layoutParams.DockRegion; // Arrange only the center elements if (dockRegion != DockRegion.CenterOverlay) { continue; } this.MeasureChildWithMarginsOverride( child, widthMeasureSpec, usedLeft + usedRight, layoutParams.Width, heightMeasureSpec, usedTop + usedBottom, layoutParams.Height); Size childUsedSize = GetChildUsedSizeWithMargins(child, layoutParams); usedCenterSize = new Size( Math.Max(usedCenterSize.Width, childUsedSize.Width), Math.Max(usedCenterSize.Height, childUsedSize.Height)); childWidthState |= child.LayoutProperties().MeasuredSize.WidthState; childHeightState |= child.LayoutProperties().MeasuredSize.HeightState; } // Calculate the total size used by children Size usedSize = new Size( (float)Math.Max(minWidth, usedLeft + usedRight + usedCenterSize.Width), (float)Math.Max(minHeight, usedTop + usedBottom + usedCenterSize.Height)); // Default the final size to the size used by children var finalSize = new Size( usedSize.Width + layoutProperties.Padding.Left + layoutProperties.Padding.Right, usedSize.Height + layoutProperties.Padding.Top + layoutProperties.Padding.Bottom); var dimensionX = ResolveSizeAndState(finalSize.Width, widthMeasureSpec, childWidthState); var dimensionY = ResolveSizeAndState(finalSize.Height, heightMeasureSpec, childHeightState); this.SetMeasuredSize(dimensionX, dimensionY); }