protected static MeasuredDimension ResolveSizeAndState( float size, MeasureSpec measureSpec, MeasuredStateFlags childMeasuredState) { MeasuredDimension result = new MeasuredDimension(); MeasureMode specMode = measureSpec.Mode; float specSize = measureSpec.Size; switch (specMode) { case MeasureSpec.Unspecified: result.Size = size; break; case MeasureSpec.AtMost: if (specSize < size) { result.Size = specSize; result.State |= MeasuredStateFlags.TooSmall; } else { result.Size = size; } break; case MeasureSpec.Exactly: result.Size = specSize; break; } result.State |= childMeasuredState; return(result); }
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 usedWidth = 0; float usedHeight = 0; var remainingSize = availableSize; MeasuredStateFlags childWidthState = MeasuredStateFlags.None; MeasuredStateFlags childHeightState = MeasuredStateFlags.None; int childCount = this.ChildCount; for (int i = 0; i < childCount; i += 1) { var child = this.GetChildAt(i); if (child.Hidden) { continue; } var layoutParams = (LayoutParams)child.LayoutParameters(); this.MeasureChildWithMarginsOverride( child, widthMeasureSpec, usedWidth, (layoutParams.Width == LayoutParams.MatchParent) ? LayoutParams.WrapContent : layoutParams.Width, heightMeasureSpec, usedHeight, layoutParams.Height); var childSize = GetChildUsedSizeWithMargins(child, layoutParams); usedWidth += childSize.Width; usedHeight = Math.Max(usedHeight, childSize.Height); // Update the remaining size remainingSize = new Size( (float)Math.Max(0, availableSize.Width - usedWidth), (float)Math.Max(0, availableSize.Height)); // Update the child state childWidthState = CombineMeasuredStates(childWidthState, child.LayoutProperties().MeasuredSize.WidthState); childHeightState = CombineMeasuredStates(childHeightState, child.LayoutProperties().MeasuredSize.HeightState); } // Calculate the total size used by children Size usedSize = new Size( (float)Math.Max(0, usedWidth), (float)Math.Max(0, usedHeight)); // Default the final size to the size used by children var finalSize = usedSize; var dimensionX = ResolveSizeAndState(finalSize.Width, widthMeasureSpec, childWidthState); var dimensionY = ResolveSizeAndState(finalSize.Height, heightMeasureSpec, childHeightState); this.SetMeasuredSize(dimensionX, dimensionY); }
protected static MeasuredStateFlags CombineMeasuredStates( MeasuredStateFlags currentState, MeasuredStateFlags newState) { return(currentState | newState); }