Example #1
0
        } // MeasureHorizontally

        void MeasureVertical(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
        {
            var   widthMode           = widthMeasureSpec.Mode;
            var   heightMode          = heightMeasureSpec.Mode;
            bool  isExactly           = (heightMode == MeasureSpecification.ModeType.Exactly);
            bool  matchWidth          = false;
            bool  allFillParent       = true;
            float maxWidth            = 0.0f;
            float alternativeMaxWidth = 0.0f;
            float weightedMaxWidth    = 0.0f;
            float totalWeight         = 0.0f;

            // Reset total length
            _totalLength = 0.0f;
            LayoutLength usedExcessSpace = new LayoutLength(0);

            HeightAndWidthState childState = new HeightAndWidthState(MeasuredSize.StateType.MeasuredSizeOK,
                                                                     MeasuredSize.StateType.MeasuredSizeTooSmall);


            // measure children, and determine if further resolution is required

            // 1st phase:
            // We cycle through all children and measure children with weight 0 (non weighted children) according to their specs
            // to accumulate total used space in mTotalLength based on measured sizes and margins.
            // Weighted children are not measured at this phase.
            // Available space for weighted children will be calculated in the phase 2 based on mTotalLength value.
            uint index = 0;

            foreach (LayoutItem childLayout in _children)
            {
                LayoutLength childDesiredWidth  = new LayoutLength(childLayout.Owner.WidthSpecification);
                LayoutLength childDesiredHeight = new LayoutLength(childLayout.Owner.HeightSpecification);
                float        childWeight        = childLayout.Owner.Weight;
                Extents      childMargin        = childLayout.Margin;
                totalWeight += childWeight;

                bool useExcessSpace = (childDesiredHeight.AsRoundedValue() == 0) && (childWeight > 0);

                if (isExactly && useExcessSpace)
                {
                    LayoutLength totalLength = new LayoutLength(_totalLength);
                    _totalLength = Math.Max(totalLength.AsDecimal(), (totalLength + childMargin.Top + childMargin.Bottom).AsDecimal());
                }
                else
                {
                    LayoutLength childHeight = new LayoutLength(0);
                    if (useExcessSpace)
                    {
                        // The heightMode is either Unspecified or AtMost, and
                        // this child is only laid out using excess space. Measure
                        // using WrapContent so that we can find out the view's
                        // optimal height. We'll restore the original height of 0
                        // after measurement.
                        MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification(widthMeasureSpec,
                                                                                                  new LayoutLength(childLayout.Padding.Start + childLayout.Padding.End),
                                                                                                  childDesiredWidth);
                        MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification(heightMeasureSpec,
                                                                                                   new LayoutLength(childLayout.Padding.Top + childLayout.Padding.Bottom),
                                                                                                   new LayoutLength(LayoutParamPolicies.WrapContent));
                        childLayout.Measure(childWidthMeasureSpec, childHeightMeasureSpec);
                        childHeight      = childLayout.MeasuredHeight.Size;
                        usedExcessSpace += childHeight;
                    }
                    else
                    {
                        MeasureChild(childLayout, widthMeasureSpec, heightMeasureSpec);
                        childHeight = childLayout.MeasuredHeight.Size;
                    }

                    float length      = (childHeight + childMargin.Top + childMargin.Bottom).AsDecimal();
                    float cellPadding = CellPadding.Height;
                    // No need to add cell padding to the end of last item.
                    if (index >= _children.Count - 1)
                    {
                        cellPadding = 0.0f;
                    }
                    _totalLength = Math.Max(_totalLength, _totalLength + length + cellPadding);
                }

                bool matchWidthLocally = false;
                if (widthMode != MeasureSpecification.ModeType.Exactly && childDesiredWidth == new LayoutLength(LayoutParamPolicies.MatchParent))
                {
                    // Will have to re-measure at least this child when we know exact height.
                    matchWidth        = true;
                    matchWidthLocally = true;
                }

                float        marginWidth = (childLayout.Margin.Start) + (childLayout.Margin.End);
                LayoutLength childWidth  = new LayoutLength(childLayout.MeasuredWidth.Size.AsDecimal() + marginWidth);

                // was combineMeasuredStates()
                if (childLayout.MeasuredWidthAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
                {
                    childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall;
                }
                if (childLayout.MeasuredHeightAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
                {
                    childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall;
                }

                maxWidth      = (Math.Max(maxWidth, childWidth.AsDecimal()));
                allFillParent = (allFillParent && (childDesiredWidth == new LayoutLength(LayoutParamPolicies.MatchParent)));

                float widthforWeight = childWidth.AsDecimal();
                if (matchWidthLocally)
                {
                    widthforWeight = marginWidth;
                }

                if (childWeight > 0)
                {
                    /*
                     * Widths of weighted Views are bogus if we end up remeasuring, so keep them separate.
                     */
                    weightedMaxWidth = Math.Max(weightedMaxWidth, widthforWeight);
                }
                else
                {
                    alternativeMaxWidth = Math.Max(alternativeMaxWidth, widthforWeight);
                }
            } // foreach


            Extents padding = Padding;

            _totalLength += padding.Top + padding.Bottom;
            LayoutLength heightSize = new LayoutLength(_totalLength);

            heightSize = new LayoutLength(Math.Max(heightSize.AsDecimal(), SuggestedMinimumHeight.AsDecimal()));
            MeasuredSize heightSizeAndState = ResolveSizeAndState(heightSize, heightMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK);

            heightSize = heightSizeAndState.Size;

            // Either expand children with weight to take up available space or
            // shrink them if they extend beyond our current bounds. If we skipped
            // measurement on any children, we need to measure them now.

            // 2nd phase:
            // We cycle through weighted children now (children with weight > 0).
            // The children are measured with exact size equal to their share of the available space based on their weights.
            // TotalLength is updated to include weighted children measured sizes.

            float remainingExcess = heightSize.AsDecimal() - _totalLength + usedExcessSpace.AsDecimal();

            if (remainingExcess != 0 && totalWeight > 0.0f)
            {
                float remainingWeightSum = totalWeight;

                _totalLength = 0;

                foreach (LayoutItem childLayout in _children)
                {
                    int     desiredWidth  = childLayout.Owner.WidthSpecification;
                    int     desiredHeight = childLayout.Owner.HeightSpecification;
                    float   childWeight   = childLayout.Owner.Weight;
                    Extents childMargin   = childLayout.Margin;

                    float childHeight = 0;
                    if (childWeight > 0)
                    {
                        float share = (childWeight * remainingExcess) / remainingWeightSum;
                        remainingExcess    -= share;
                        remainingWeightSum -= childWeight;

                        // Always lay out weighted elements with intrinsic size regardless of the parent spec
                        // for consistency between specs.
                        if (desiredHeight == 0)
                        {
                            // This child needs to be laid out from scratch using
                            // only its share of excess space.
                            childHeight = share;
                        }
                        else
                        {
                            // This child had some intrinsic width to which we
                            // need to add its share of excess space.
                            childHeight = childLayout.MeasuredHeight.Size.AsDecimal() + share;
                        }

                        MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification(widthMeasureSpec,
                                                                                                  new LayoutLength(Padding.Start + Padding.End),
                                                                                                  new LayoutLength(desiredWidth));

                        MeasureSpecification childHeightMeasureSpec = new MeasureSpecification(new LayoutLength(childHeight), MeasureSpecification.ModeType.Exactly);
                        childLayout.Measure(childWidthMeasureSpec, childHeightMeasureSpec);

                        // Child may now not fit in vertical dimension.
                        if (childLayout.MeasuredHeightAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
                        {
                            childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall;
                        }
                    }

                    bool matchWidthLocally = false;
                    if (widthMode != MeasureSpecification.ModeType.Exactly && desiredWidth == (int)ChildLayoutData.MatchParent)
                    {
                        // Will have to re-measure at least this child when we know exact height.
                        matchWidth        = true;
                        matchWidthLocally = true;
                    }

                    float marginWidth = childMargin.Start + childMargin.End;
                    float childWidth  = childLayout.MeasuredWidth.Size.AsDecimal() + marginWidth;
                    maxWidth      = Math.Max(maxWidth, childWidth);
                    allFillParent = allFillParent && desiredWidth == (int)ChildLayoutData.MatchParent;


                    alternativeMaxWidth = Math.Max(alternativeMaxWidth, matchWidthLocally ? marginWidth : childWidth);

                    childHeight = childLayout.MeasuredHeight.Size.AsDecimal();
                    float length      = childHeight + childMargin.Top + childMargin.Bottom;
                    float cellPadding = CellPadding.Height;
                    // No need to add cell padding to the end of last item.
                    if (index >= _children.Count - 1)
                    {
                        cellPadding = 0.0f;
                    }
                    _totalLength = Math.Max(_totalLength, _totalLength + length + cellPadding);
                } // foreach

                // Add in our padding
                _totalLength += Padding.Top + Padding.Bottom;
            }
            else
            {
                alternativeMaxWidth = Math.Max(alternativeMaxWidth, weightedMaxWidth);
            }

            if (!allFillParent && widthMode != MeasureSpecification.ModeType.Exactly)
            {
                maxWidth = alternativeMaxWidth;
            }
            maxWidth += padding.Start + padding.End;
            maxWidth  = Math.Max(maxWidth, SuggestedMinimumWidth.AsRoundedValue());

            heightSizeAndState.State = childState.heightState;

            SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(maxWidth), widthMeasureSpec, childState.widthState),
                                  heightSizeAndState);

            if (matchWidth)
            {
                ForceUniformWidth(_children.Count, heightMeasureSpec);
            }
        } // MeasureVertically
Example #2
0
        } // MeasureHorizontal

        private void MeasureVertical(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
        {
            var   widthMode           = widthMeasureSpec.Mode;
            var   heightMode          = heightMeasureSpec.Mode;
            bool  isExactly           = (heightMode == MeasureSpecification.ModeType.Exactly);
            bool  matchWidth          = false;
            bool  allFillParent       = true;
            float maxWidth            = 0.0f;
            float alternativeMaxWidth = 0.0f;
            float weightedMaxWidth    = 0.0f;
            float totalWeight         = 0.0f;

            // Reset total length
            _totalLength = 0.0f;
            float usedExcessSpace          = 0.0f;
            HeightAndWidthState childState = new HeightAndWidthState(MeasuredSize.StateType.MeasuredSizeOK,
                                                                     MeasuredSize.StateType.MeasuredSizeOK);


            // measure children, and determine if further resolution is required

            // 1st phase:
            // We cycle through all children and measure children with weight 0 (non weighted children) according to their specs
            // to accumulate total used space in _totalLength.
            // Weighted children are not measured in this phase.
            // Available space for weighted children will be calculated in the phase 2 based on _totalLength value.
            for (int i = 0; i < LayoutChildren.Count; i++)
            {
                LayoutItem childLayout       = LayoutChildren[i];
                int        childDesiredWidth = childLayout.Owner.WidthSpecification;
                float      childWeight       = childLayout.Owner.Weight;
                Extents    childMargin       = childLayout.Margin;
                totalWeight += childWeight;

                bool useExcessSpace = (childLayout.Owner.HeightSpecification == 0) && (childWeight > 0);
                if (isExactly && useExcessSpace)
                {
                    _totalLength = Math.Max(_totalLength, (_totalLength + childMargin.Top + childMargin.Bottom));
                }
                else
                {
                    if (useExcessSpace)
                    {
                        // The heightMode is either Unspecified or AtMost, and
                        // this child is only laid out using excess space. Measure
                        // using WrapContent so that we can find out the view's
                        // optimal height.
                        // We'll restore the original height of 0 after measurement.
                        MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification(
                            new MeasureSpecification(
                                new LayoutLength(widthMeasureSpec.Size - (childLayout.Margin.Start + childLayout.Margin.End)),
                                widthMeasureSpec.Mode),
                            new LayoutLength(Padding.Start + Padding.End),
                            new LayoutLength(childDesiredWidth));

                        MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification(
                            new MeasureSpecification(
                                new LayoutLength(heightMeasureSpec.Size - (childLayout.Margin.Top + childLayout.Margin.Bottom)),
                                heightMeasureSpec.Mode),
                            new LayoutLength(Padding.Top + Padding.Bottom),
                            new LayoutLength(LayoutParamPolicies.WrapContent));

                        childLayout.Measure(childWidthMeasureSpec, childHeightMeasureSpec);
                        usedExcessSpace += childLayout.MeasuredHeight.Size.AsDecimal();
                    }
                    else
                    {
                        MeasureChildWithMargins(childLayout, widthMeasureSpec, new LayoutLength(0), heightMeasureSpec, new LayoutLength(0));
                    }

                    LayoutLength childHeight = childLayout.MeasuredHeight.Size;
                    LayoutLength length      = childHeight + childMargin.Top + childMargin.Bottom;


                    if (isExactly)
                    {
                        _totalLength += length.AsDecimal();
                    }
                    else
                    {
                        _totalLength = Math.Max(_totalLength, _totalLength + length.AsDecimal() + (i < LayoutChildren.Count - 1 ? CellPadding.Height : 0));
                    }
                }

                bool matchWidthLocally = false;
                if (widthMode != MeasureSpecification.ModeType.Exactly && childDesiredWidth == LayoutParamPolicies.MatchParent)
                {
                    // Will have to re-measure at least this child when we know exact height.
                    matchWidth        = true;
                    matchWidthLocally = true;
                }

                float marginWidth = childLayout.Margin.Start + childLayout.Margin.End;
                float childWidth  = childLayout.MeasuredWidth.Size.AsDecimal() + marginWidth;

                if (childLayout.MeasuredWidth.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
                {
                    childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall;
                }
                if (childLayout.MeasuredHeight.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
                {
                    childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall;
                }

                maxWidth      = Math.Max(maxWidth, childWidth);
                allFillParent = (allFillParent && childDesiredWidth == LayoutParamPolicies.MatchParent);

                if (childWeight > 0)
                {
                    // Widths of weighted Views are bogus if we end up remeasuring, so keep them separate.
                    weightedMaxWidth = Math.Max(weightedMaxWidth, matchWidthLocally ? marginWidth : childWidth);
                }
                else
                {
                    alternativeMaxWidth = Math.Max(alternativeMaxWidth, matchWidthLocally ? marginWidth : childWidth);
                }
            } // foreach


            float heightSize = _totalLength;

            heightSize = Math.Max(heightSize, SuggestedMinimumHeight.AsDecimal());
            MeasuredSize heightSizeAndState = ResolveSizeAndState(new LayoutLength(heightSize + Padding.Top + Padding.Bottom), heightMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK);

            heightSize = heightSizeAndState.Size.AsDecimal();

            // 2nd phase:
            // We cycle through weighted children now (children with weight > 0).
            // The children are measured with exact size equal to their share of the available space based on their weights.
            // _totalLength is updated to include weighted children measured sizes.
            float remainingExcess = heightSize - _totalLength + usedExcessSpace - (Padding.Top + Padding.Bottom);

            if (remainingExcess != 0 && totalWeight > 0.0f)
            {
                float remainingWeight = totalWeight;
                maxWidth     = 0;
                _totalLength = 0;

                int numberOfChildren = LayoutChildren.Count;
                for (int i = 0; i < numberOfChildren; ++i)
                {
                    LayoutItem childLayout = LayoutChildren[i];

                    float desiredChildWidth = childLayout.Owner.WidthSpecification;

                    float   childWeight = childLayout.Owner.Weight;
                    Extents childMargin = childLayout.Margin;

                    if (childWeight > 0)
                    {
                        MeasureWeightedChild(childLayout, remainingExcess, remainingWeight, childWeight,
                                             widthMeasureSpec, heightMeasureSpec, childState,
                                             Orientation.Vertical);
                    }

                    float length      = childLayout.MeasuredHeight.Size.AsDecimal() + childMargin.Top + childMargin.Bottom;
                    float cellPadding = i < numberOfChildren - 1 ? CellPadding.Height : 0;

                    if (isExactly)
                    {
                        _totalLength += length;
                    }
                    else
                    {
                        float totalLength = _totalLength;
                        _totalLength = Math.Max(_totalLength, _totalLength + length + cellPadding);
                    }

                    bool  matchWidthLocally = (widthMode != MeasureSpecification.ModeType.Exactly) && (desiredChildWidth == LayoutParamPolicies.MatchParent);
                    float marginWidth       = childMargin.Start + childMargin.End;
                    float childWidth        = childLayout.MeasuredWidth.Size.AsDecimal() + marginWidth;

                    maxWidth            = Math.Max(maxWidth, childWidth);
                    alternativeMaxWidth = Math.Max(alternativeMaxWidth, matchWidthLocally ? marginWidth : childWidth);
                    allFillParent       = (allFillParent && desiredChildWidth == LayoutParamPolicies.MatchParent);
                } // for loop
            }
            else
            {
                alternativeMaxWidth = Math.Max(alternativeMaxWidth, weightedMaxWidth);
            }

            if (!allFillParent && widthMode != MeasureSpecification.ModeType.Exactly)
            {
                maxWidth = alternativeMaxWidth;
            }

            maxWidth += (Owner.WidthSpecification == LayoutParamPolicies.WrapContent)?(Padding.Start + Padding.End):0;
            maxWidth  = Math.Max(maxWidth, SuggestedMinimumWidth.AsRoundedValue());

            heightSizeAndState.State = childState.heightState;

            SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(maxWidth + Padding.Top + Padding.Bottom), widthMeasureSpec, childState.widthState),
                                  heightSizeAndState);

            if (matchWidth)
            {
                ForceUniformWidth(heightMeasureSpec);
            }
        } // MeasureVertical
Example #3
0
        protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
        {
            float totalHeight = 0.0f;
            float totalWidth  = 0.0f;

            HeightAndWidthState childState = new HeightAndWidthState(MeasuredSize.StateType.MeasuredSizeOK,
                                                                     MeasuredSize.StateType.MeasuredSizeOK);

            float minPositionX = 0.0f;
            float minPositionY = 0.0f;
            float maxPositionX = 0.0f;
            float maxPositionY = 0.0f;

            // measure children
            foreach (LayoutItem childLayout in _children)
            {
                if (childLayout != null)
                {
                    // Get size of child
                    MeasureChild(childLayout, widthMeasureSpec, heightMeasureSpec);
                    float childWidth  = childLayout.MeasuredWidth.Size.AsDecimal();
                    float childHeight = childLayout.MeasuredHeight.Size.AsDecimal();

                    // Determine the width and height needed by the children using their given position and size.
                    // Children could overlap so find the left most and right most child.
                    Position2D childPosition = childLayout.Owner.Position2D;
                    float      childLeft     = childPosition.X;
                    float      childTop      = childPosition.Y;

                    minPositionX = Math.Min(minPositionX, childLeft);
                    maxPositionX = Math.Max(maxPositionX, childLeft + childWidth);
                    // Children could overlap so find the highest and lowest child.
                    minPositionY = Math.Min(minPositionY, childTop);
                    maxPositionY = Math.Max(maxPositionY, childTop + childHeight);

                    // Store current width and height needed to contain all children.
                    totalWidth  = maxPositionX - minPositionX;
                    totalHeight = maxPositionY - minPositionY;

                    if (childLayout.MeasuredWidthAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
                    {
                        childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall;
                    }
                    if (childLayout.MeasuredWidthAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
                    {
                        childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall;
                    }
                }
            }


            MeasuredSize widthSizeAndState  = ResolveSizeAndState(new LayoutLength(totalWidth), widthMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK);
            MeasuredSize heightSizeAndState = ResolveSizeAndState(new LayoutLength(totalHeight), heightMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK);

            totalWidth  = widthSizeAndState.Size.AsDecimal();
            totalHeight = heightSizeAndState.Size.AsDecimal();

            // Ensure layout respects it's given minimum size
            totalWidth  = Math.Max(totalWidth, SuggestedMinimumWidth.AsDecimal());
            totalHeight = Math.Max(totalHeight, SuggestedMinimumHeight.AsDecimal());

            widthSizeAndState.State  = childState.widthState;
            heightSizeAndState.State = childState.heightState;

            SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(totalWidth), widthMeasureSpec, childState.widthState),
                                  ResolveSizeAndState(new LayoutLength(totalHeight), heightMeasureSpec, childState.heightState));
        }
Example #4
0
 internal virtual void OnMeasureIndependentChildren(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
 {
 }
Example #5
0
 /// <summary>
 /// Ask all of the children of this view to measure themselves, taking into
 /// account both the MeasureSpec requirements for this view and its padding.<br />
 /// The heavy lifting is done in GetChildMeasureSpec.<br />
 /// </summary>
 /// <param name="widthMeasureSpec">The width requirements for this view.</param>
 /// <param name="heightMeasureSpec">The height requirements for this view.</param>
 /// <since_tizen> 6 </since_tizen>
 protected virtual void MeasureChildren(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
 {
     foreach (LayoutItem childLayout in LayoutChildren)
     {
         MeasureChildWithMargins(childLayout, widthMeasureSpec, new LayoutLength(0), heightMeasureSpec, new LayoutLength(0));
     }
 }
Example #6
0
        /// <summary>
        /// Ask one of the children of this view to measure itself, taking into
        /// account both the MeasureSpec requirements for this view and its padding.<br />
        /// and margins. The heavy lifting is done in GetChildMeasureSpecification.<br />
        /// </summary>
        /// <param name="child">The child to measure.</param>
        /// <param name="parentWidthMeasureSpec">The width requirements for this view.</param>
        /// <param name="widthUsed">Extra space that has been used up by the parent horizontally (possibly by other children of the parent).</param>
        /// <param name="parentHeightMeasureSpec">The height requirements for this view.</param>
        /// <param name="heightUsed">Extra space that has been used up by the parent vertically (possibly by other children of the parent).</param>
        /// <exception cref="ArgumentNullException"> Thrown when child is null. </exception>
        /// <since_tizen> 6 </since_tizen>
        protected virtual void MeasureChildWithMargins(LayoutItem child, MeasureSpecification parentWidthMeasureSpec, LayoutLength widthUsed, MeasureSpecification parentHeightMeasureSpec, LayoutLength heightUsed)
        {
            if (null == child)
            {
                throw new ArgumentNullException(nameof(child));
            }

            View    childOwner = child.Owner;
            Extents margin     = childOwner.Margin;

            MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification(
                new MeasureSpecification(
                    new LayoutLength(parentWidthMeasureSpec.Size + widthUsed - (margin.Start + margin.End)),
                    parentWidthMeasureSpec.Mode),
                new LayoutLength(Padding.Start + Padding.End),
                new LayoutLength(childOwner.WidthSpecification));

            MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification(
                new MeasureSpecification(
                    new LayoutLength(parentHeightMeasureSpec.Size + heightUsed - (margin.Top + margin.Bottom)),
                    parentHeightMeasureSpec.Mode),
                new LayoutLength(Padding.Top + Padding.Bottom),
                new LayoutLength(childOwner.HeightSpecification));

            child.Measure(childWidthMeasureSpec, childHeightMeasureSpec);
        }
Example #7
0
        /// <inheritdoc/>
        /// <since_tizen> 9 </since_tizen>
        protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
        {
            MeasuredSize.StateType childWidthState  = MeasuredSize.StateType.MeasuredSizeOK;
            MeasuredSize.StateType childHeightState = MeasuredSize.StateType.MeasuredSizeOK;

            for (int i = 0; i < LayoutChildren.Count; i++)
            {
                LayoutItem childLayout = LayoutChildren[i];
                if (childLayout != null)
                {
                    MeasureChildWithMargins(childLayout, widthMeasureSpec, new LayoutLength(0), heightMeasureSpec, new LayoutLength(0));

                    if (childLayout.MeasuredWidth.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
                    {
                        childWidthState = MeasuredSize.StateType.MeasuredSizeTooSmall;
                    }
                    if (childLayout.MeasuredHeight.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
                    {
                        childHeightState = MeasuredSize.StateType.MeasuredSizeTooSmall;
                    }
                }
            }

            (float childrenWidth, float childrenHeight) = CalculateChildrenSize(widthMeasureSpec.Size.AsDecimal(), heightMeasureSpec.Size.AsDecimal());
            SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(childrenWidth), widthMeasureSpec, childWidthState),
                                  ResolveSizeAndState(new LayoutLength(childrenHeight), heightMeasureSpec, childHeightState));

            // There are 2 cases which require to calculate children's MeasuredWidth/Height as follows.
            //
            // 1. Text with Ellipsis true
            //    TextLabel and TextField calculate MeasuredWidth/Height to cover their text string if they have WrapContent.
            //    This causes children's Ellipsis cannot be displayed with RelativeLayout.
            //    To resolve the above, RelativeLayout recalculates its children's MeasuredWidth/Height based on the children's space calculated by RelativeLayout APIs.
            //
            // 2. FillHorizontal/Vertical true
            //    If children set FillHorizontal/Vertical true, then children's MeasuredWidth/Height are not correctly alculated.
            //    Instead, children's size and position are correctly calculated in OnLayout().
            //    This causes that the grand children's MeasuredWidth/Height are calculated incorrectly.
            //    To resolve the above, RelativeLayout calculates its children's MeasuredWidth/Height based on the children's geometry calculated by RelativeLayout APIs.
            //
            //    e.g.
            //    Let parent have RelativeLayout and parent's size be 1920x1080.
            //    Let child have WrapContent with SetFillHorizontal/Vertical true.
            //    Let grand child have MatchParent.
            //    Then, child's size is 1920x1080 but child's MeasuredWidth/Height is 0x0.
            //    Then, grand child's MeasuredWidth/Height is 0x0 and size is 0x0.
            //
            // TODO: Not to do duplicate operations in OnLayout() again.
            bool needClearCache = false;

            for (int i = 0; i < LayoutChildren.Count; i++)
            {
                LayoutItem childLayout = LayoutChildren[i];
                if (childLayout != null)
                {
                    bool ellipsisTextWidth  = false;
                    bool ellipsisTextHeight = false;
                    bool needMeasuredWidth  = false;
                    bool needMeasuredHeight = false;

                    if (((childLayout.Owner is TextLabel textLabel) && textLabel.Ellipsis) || ((childLayout.Owner is TextField textField) && textField.Ellipsis))
                    {
                        Geometry horizontalSpace = GetHorizontalSpace(childLayout.Owner);
                        if (!horizontalSpace.Size.Equals(0))
                        {
                            ellipsisTextWidth = true;
                            needClearCache    = true;
                        }

                        Geometry verticalSpace = GetVerticalSpace(childLayout.Owner);
                        if (!verticalSpace.Size.Equals(0))
                        {
                            ellipsisTextHeight = true;
                            needClearCache     = true;
                        }
                    }

                    if (!ellipsisTextWidth && RelativeLayout.GetFillHorizontal(childLayout.Owner))
                    {
                        needMeasuredWidth = true;
                        needClearCache    = true;
                    }

                    if (!ellipsisTextHeight && RelativeLayout.GetFillVertical(childLayout.Owner))
                    {
                        needMeasuredHeight = true;
                        needClearCache     = true;
                    }

                    if ((ellipsisTextWidth == false) && (ellipsisTextHeight == false) && (needMeasuredWidth == false) && (needMeasuredHeight == false))
                    {
                        continue;
                    }

                    float width  = childLayout.MeasuredWidth.Size.AsDecimal();
                    float height = childLayout.MeasuredHeight.Size.AsDecimal();

                    if (ellipsisTextWidth)
                    {
                        Geometry horizontalSpace = GetHorizontalSpace(childLayout.Owner);
                        if (!horizontalSpace.Size.Equals(0))
                        {
                            if ((width > horizontalSpace.Size) || ((width < horizontalSpace.Size) && RelativeLayout.GetFillVertical(childLayout.Owner)))
                            {
                                width = horizontalSpace.Size;
                            }
                        }
                    }
                    else if (needMeasuredWidth)
                    {
                        Geometry horizontalGeometry = GetHorizontalLayout(childLayout.Owner);
                        width = horizontalGeometry.Size;
                    }

                    if (ellipsisTextHeight)
                    {
                        Geometry verticalSpace = GetVerticalSpace(childLayout.Owner);
                        if (!verticalSpace.Size.Equals(0))
                        {
                            if ((height > verticalSpace.Size) || ((height < verticalSpace.Size) && RelativeLayout.GetFillHorizontal(childLayout.Owner)))
                            {
                                height = verticalSpace.Size;
                            }
                        }
                    }
                    else if (needMeasuredHeight)
                    {
                        Geometry verticalGeometry = GetVerticalLayout(childLayout.Owner);
                        height = verticalGeometry.Size;
                    }

                    // Padding sizes are added because Padding sizes will be subtracted in MeasureChild().
                    MeasureSpecification childWidthMeasureSpec  = new MeasureSpecification(new LayoutLength(width + Padding.Start + Padding.End), MeasureSpecification.ModeType.Exactly);
                    MeasureSpecification childHeightMeasureSpec = new MeasureSpecification(new LayoutLength(height + Padding.Top + Padding.Bottom), MeasureSpecification.ModeType.Exactly);

                    // To calculate the grand children's Measure() with the mode type Exactly,
                    // children's Measure() is called with MatchParent if the children have WrapContent.
                    //
                    // i.e.
                    // If children have Wrapcontent and the grand children have MatchParent,
                    // then grand children's MeasuredWidth/Height do not fill the children
                    // because the grand children's Measure() is called with the mode type AtMost.
                    int origWidthSpecification  = childLayout.Owner.WidthSpecification;
                    int origHeightSpecification = childLayout.Owner.HeightSpecification;

                    if (ellipsisTextWidth || needMeasuredWidth)
                    {
                        origWidthSpecification = childLayout.Owner.WidthSpecification;
                        childLayout.Owner.WidthSpecification = LayoutParamPolicies.MatchParent;
                    }
                    if (ellipsisTextHeight || needMeasuredHeight)
                    {
                        origHeightSpecification = childLayout.Owner.HeightSpecification;
                        childLayout.Owner.HeightSpecification = LayoutParamPolicies.MatchParent;
                    }

                    MeasureChildWithMargins(childLayout, childWidthMeasureSpec, new LayoutLength(0), childHeightMeasureSpec, new LayoutLength(0));

                    if (ellipsisTextWidth || needMeasuredWidth)
                    {
                        childLayout.Owner.WidthSpecification = origWidthSpecification;
                    }
                    if (ellipsisTextHeight || needMeasuredHeight)
                    {
                        childLayout.Owner.HeightSpecification = origHeightSpecification;
                    }
                }
            }

            if (needClearCache)
            {
                HorizontalRelativeCache.Clear();
                VerticalRelativeCache.Clear();
            }
        }
Example #8
0
        /// <summary>
        /// Calculate the right measure spec for this child.
        /// Does the hard part of MeasureChildren: figuring out the MeasureSpec to
        /// pass to a particular child. This method figures out the right MeasureSpec
        /// for one dimension (height or width) of one child view.<br />
        /// </summary>
        /// <param name="parentMeasureSpec">The requirements for this view. MeasureSpecification.</param>
        /// <param name="padding">The padding of this view for the current dimension and margins, if applicable. LayoutLength.</param>
        /// <param name="childDimension"> How big the child wants to be in the current dimension. LayoutLength.</param>
        /// <returns>a MeasureSpec for the child.</returns>
        public static MeasureSpecification GetChildMeasureSpecification(MeasureSpecification parentMeasureSpec, LayoutLength padding, LayoutLength childDimension)
        {
            MeasureSpecification.ModeType specMode   = parentMeasureSpec.Mode;
            MeasureSpecification.ModeType resultMode = MeasureSpecification.ModeType.Unspecified;

            // Child only can use parent's size without parent's padding and own margin.
            LayoutLength resultSize = new LayoutLength(Math.Max(0.0f, (parentMeasureSpec.Size - padding).AsDecimal()));

            switch (specMode)
            {
            // Parent has imposed an exact size on us
            case MeasureSpecification.ModeType.Exactly:
            {
                if ((int)childDimension.AsRoundedValue() == LayoutParamPolicies.MatchParent)
                {
                    resultMode = MeasureSpecification.ModeType.Exactly;
                }
                else if ((int)childDimension.AsRoundedValue() == LayoutParamPolicies.WrapContent)
                {
                    resultMode = MeasureSpecification.ModeType.AtMost;
                }
                else
                {
                    resultSize = childDimension;
                    resultMode = MeasureSpecification.ModeType.Exactly;
                }

                break;
            }

            // Parent has imposed a maximum size on us
            case MeasureSpecification.ModeType.AtMost:
            {
                if (childDimension.AsRoundedValue() == LayoutParamPolicies.MatchParent)
                {
                    // Crashed. Cannot calculate.

                    // Child wants to be our size, but our size is not fixed.
                    // Constrain child to not be bigger than us.
                    resultMode = MeasureSpecification.ModeType.AtMost;
                }
                else if (childDimension.AsRoundedValue() == LayoutParamPolicies.WrapContent)
                {
                    // Child wants to determine its own size. It can't be
                    // bigger than us.

                    // Don't need parent's size. Size of this child will be determined by its children.
                    resultMode = MeasureSpecification.ModeType.AtMost;
                }
                else
                {
                    // Child wants a specific size... so be it
                    resultSize = childDimension;
                    resultMode = MeasureSpecification.ModeType.Exactly;
                }

                break;
            }

            // Parent asked to see how big we want to be
            case MeasureSpecification.ModeType.Unspecified:
            {
                if ((childDimension.AsRoundedValue() == LayoutParamPolicies.MatchParent))
                {
                    // Child wants to be our size... find out how big it should be

                    // There is no one who has exact size in parent hierarchy.
                    // Cannot calculate.
                    resultMode = MeasureSpecification.ModeType.Unspecified;
                }
                else if (childDimension.AsRoundedValue() == (LayoutParamPolicies.WrapContent))
                {
                    // Child wants to determine its own size.... find out how big
                    // it should be
                    resultMode = MeasureSpecification.ModeType.Unspecified;
                }
                else
                {
                    // Child wants a specific size... let him have it
                    resultSize = childDimension;
                    resultMode = MeasureSpecification.ModeType.Exactly;
                }
                break;
            }
            } // switch

            return(new MeasureSpecification(resultSize, resultMode));
        }
Example #9
0
 internal override void OnMeasureIndependentChildren(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
 {
     foreach (var childLayout in LayoutChildren)
     {
         if (!childLayout.SetPositionByLayout)
         {
             MeasureChildWithoutPadding(childLayout, widthMeasureSpec, heightMeasureSpec);
         }
     }
 }
Example #10
0
        private void MeasureHorizontal(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
        {
            var   widthMode            = widthMeasureSpec.Mode;
            var   heightMode           = heightMeasureSpec.Mode;
            bool  isExactly            = (widthMode == MeasureSpecification.ModeType.Exactly);
            bool  matchHeight          = false;
            bool  allFillParent        = true;
            float maxHeight            = 0.0f;
            float alternativeMaxHeight = 0.0f;
            float weightedMaxHeight    = 0.0f;
            float totalWeight          = 0.0f;

            // Reset measure variables
            _totalLength = 0.0f;
            float usedExcessSpace          = 0.0f;
            HeightAndWidthState childState = new HeightAndWidthState(MeasuredSize.StateType.MeasuredSizeOK,
                                                                     MeasuredSize.StateType.MeasuredSizeOK);

            // 1st phase:
            // We cycle through all children and measure children with weight 0 (non weighted children) according to their specs
            // to accumulate total used space in totalLength based on measured sizes and margins.
            // Weighted children are not measured at this phase.
            // Available space for weighted children will be calculated in the phase 2 based on totalLength value.
            // Max height of children is stored.
            foreach (LayoutItem childLayout in LayoutChildren)
            {
                int     childDesiredHeight = childLayout.Owner.HeightSpecification;
                float   childWeight        = childLayout.Owner.Weight;
                Extents childMargin        = childLayout.Margin;
                totalWeight += childWeight;

                bool useExcessSpace = (childLayout.Owner.WidthSpecification == 0) && (childWeight > 0);
                if (isExactly && useExcessSpace)
                {
                    // Children to be laid out with excess space can be measured later
                    _totalLength += childMargin.Start + childMargin.End;
                }
                else
                {
                    if (useExcessSpace)
                    {
                        // The widthMode is either Unspecified or AtMost, and
                        // this child is only laid out using excess space. Measure
                        // using WrapContent so that we can find out the view's
                        // optimal width.
                        MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification(widthMeasureSpec,
                                                                                                  new LayoutLength(childLayout.Padding.Start + childLayout.Padding.End),
                                                                                                  new LayoutLength(LayoutParamPolicies.WrapContent));

                        MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification(heightMeasureSpec,
                                                                                                   new LayoutLength(childLayout.Padding.Top + childLayout.Padding.Bottom),
                                                                                                   new LayoutLength(childDesiredHeight));

                        childLayout.Measure(childWidthMeasureSpec, childHeightMeasureSpec);
                        usedExcessSpace += childLayout.MeasuredWidth.Size.AsDecimal();
                    }
                    else
                    {
                        MeasureChild(childLayout, widthMeasureSpec, heightMeasureSpec);
                    }

                    LayoutLength childWidth = childLayout.MeasuredWidth.Size;
                    LayoutLength length     = childWidth + childMargin.Start + childMargin.End;

                    if (isExactly)
                    {
                        _totalLength += length.AsDecimal();
                    }
                    else
                    {
                        _totalLength = Math.Max(_totalLength, _totalLength + length.AsDecimal() + CellPadding.Width);
                    }
                }

                bool matchHeightLocally = false;
                if (heightMode != MeasureSpecification.ModeType.Exactly && childDesiredHeight == LayoutParamPolicies.MatchParent)
                {
                    // A child has set to MatchParent on it's height.
                    // Will have to re-measure at least this child when we know exact height.
                    matchHeight        = true;
                    matchHeightLocally = true;
                }

                float marginHeight = childMargin.Top + childMargin.Bottom;
                float childHeight  = childLayout.MeasuredHeight.Size.AsDecimal() + marginHeight;

                if (childLayout.MeasuredWidth.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
                {
                    childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall;
                }
                if (childLayout.MeasuredHeight.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
                {
                    childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall;
                }

                maxHeight     = Math.Max(maxHeight, childHeight);
                allFillParent = (allFillParent && childDesiredHeight == LayoutParamPolicies.MatchParent);

                if (childWeight > 0)
                {
                    // Heights of weighted Views are invalid if we end up remeasuring, so store them separately.
                    weightedMaxHeight = Math.Max(weightedMaxHeight, matchHeightLocally ? marginHeight : childHeight);
                }
                else
                {
                    alternativeMaxHeight = Math.Max(alternativeMaxHeight, matchHeightLocally ? marginHeight : childHeight);
                }
            } // foreach

            Extents padding = Padding;

            _totalLength += padding.Start + padding.End;

            float widthSize = _totalLength;

            widthSize = Math.Max(widthSize, SuggestedMinimumWidth.AsDecimal());
            MeasuredSize widthSizeAndState = ResolveSizeAndState(new LayoutLength(widthSize), widthMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK);

            widthSize = widthSizeAndState.Size.AsDecimal();

            // 2nd phase:
            // Expand children with weight to take up available space
            // We cycle through weighted children now (children with weight > 0).
            // The children are measured with exact size equal to their share of the available space based on their weights.
            // _totalLength is updated to include weighted children measured sizes.
            float remainingExcess = widthSize - _totalLength + usedExcessSpace;

            if (remainingExcess != 0 && totalWeight > 0)
            {
                float remainingWeight = totalWeight;
                maxHeight    = 0;
                _totalLength = 0;

                int numberOfChildren = LayoutChildren.Count;
                for (int i = 0; i < numberOfChildren; ++i)
                {
                    LayoutItem childLayout = LayoutChildren[i];

                    float desiredChildHeight = childLayout.Owner.HeightSpecification;

                    float   childWeight = childLayout.Owner.Weight;
                    Extents childMargin = childLayout.Margin;

                    if (childWeight > 0)
                    {
                        MeasureWeightedChild(childLayout, remainingExcess, remainingWeight, childWeight,
                                             widthMeasureSpec, heightMeasureSpec, childState,
                                             Orientation.Horizontal);
                    }

                    float length      = childLayout.MeasuredWidth.Size.AsDecimal() + childMargin.Start + childMargin.End;
                    float cellPadding = i < numberOfChildren - 1 ? CellPadding.Width : 0;
                    if (isExactly)
                    {
                        _totalLength += length;
                    }
                    else
                    {
                        float totalLength = _totalLength;
                        _totalLength = Math.Max(_totalLength, _totalLength + length + cellPadding);
                    }

                    bool  matchHeightLocally = (heightMode != MeasureSpecification.ModeType.Exactly) && (desiredChildHeight == LayoutParamPolicies.MatchParent);
                    float marginHeight       = childMargin.Top + childMargin.Bottom;
                    float childHeight        = childLayout.MeasuredHeight.Size.AsDecimal() + marginHeight;

                    maxHeight            = Math.Max(maxHeight, childHeight);
                    alternativeMaxHeight = Math.Max(alternativeMaxHeight, matchHeightLocally ? marginHeight : childHeight);
                    allFillParent        = (allFillParent && desiredChildHeight == LayoutParamPolicies.MatchParent);

                    _totalLength += padding.Start + padding.End;
                } // for loop
            }
            else
            {
                // No excess space or no weighted children
                alternativeMaxHeight = Math.Max(alternativeMaxHeight, weightedMaxHeight);
            }

            if (!allFillParent && heightMode != MeasureSpecification.ModeType.Exactly)
            {
                maxHeight = alternativeMaxHeight;
            }

            maxHeight += padding.Top + padding.Bottom;
            maxHeight  = Math.Max(maxHeight, SuggestedMinimumHeight.AsRoundedValue());

            widthSizeAndState.State = childState.widthState;

            SetMeasuredDimensions(widthSizeAndState,
                                  ResolveSizeAndState(new LayoutLength(maxHeight), heightMeasureSpec, childState.heightState));

            if (matchHeight)
            {
                ForceUniformHeight(widthMeasureSpec);
            }
        } // MeasureHorizontal
Example #11
0
        } // MeasureHorizontal

        private void MeasureVertical(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
        {
            var   widthMode       = widthMeasureSpec.Mode;
            var   heightMode      = heightMeasureSpec.Mode;
            bool  isWidthExactly  = (widthMode == MeasureSpecification.ModeType.Exactly);
            bool  isHeightExactly = (heightMode == MeasureSpecification.ModeType.Exactly);
            float maxWidth        = 0.0f;
            float totalWeight     = 0.0f;
            int   childrenCount   = IterateLayoutChildren().Count();

            // Child layout, which wants to match its height to its parent's remaining height, is either following 1 or 2.
            // 1. Child layout whose Owner.HeightSpecification is LayoutParamPolicies.MatchParent.
            // 2. Child layout whose Owner.HeightSpecification is 0 and Owner.Weight is greater than 0.
            // The number of child layout which wants to match its height to its parent's remaining height.
            int childrenMatchParentCount = 0;

            // Reset measure variable
            totalLength = 0.0f;

            HeightAndWidthState childState = new HeightAndWidthState(MeasuredSize.StateType.MeasuredSizeOK,
                                                                     MeasuredSize.StateType.MeasuredSizeOK);

            // 1ST PHASE:
            //
            // We measure all children whose height specification policy is WrapContent without weight.
            // After 1st phase, remaining height of parent is accumulated to calculate height of children
            // whose height specification policy is MatchParent.
            foreach (LayoutItem childLayout in IterateLayoutChildren())
            {
                int     childDesiredWidth  = childLayout.Owner.WidthSpecification;
                int     childDesiredHeight = childLayout.Owner.HeightSpecification;
                float   childWeight        = childLayout.Owner.Weight;
                Extents childMargin        = childLayout.Margin;
                float   childMarginWidth   = childMargin.Start + childMargin.End;
                float   childMarginHeight  = childMargin.Top + childMargin.Bottom;
                bool    useRemainingHeight = (childDesiredHeight == 0) && (childWeight > 0);

                totalWeight += childWeight;

                if ((childDesiredHeight == LayoutParamPolicies.MatchParent) || (useRemainingHeight))
                {
                    childrenMatchParentCount++;
                }

                // MatchParent child layout's margin is not added to totalLength.
                // Consequently, MatchParent child layout's margin is added to remaining size,
                // so the margin is not shared with other MatchParent child layouts.
                // e.g.
                // LinearLayout has size 100.
                // Child layout1 is MatchParent and its margin is 20. (This margin is not ad
                // Child layout2 is MatchParent and its margin is 0.
                // Then, child layout1's size is 30 and child layout2's size is 50.
                if ((childDesiredHeight == LayoutParamPolicies.WrapContent) || ((childDesiredHeight > 0) && (!useRemainingHeight)))
                {
                    MeasureChildWithMargins(childLayout, widthMeasureSpec, new LayoutLength(0), heightMeasureSpec, new LayoutLength(0));

                    float childMeasuredHeight = childLayout.MeasuredHeight.Size.AsDecimal();

                    if (childMeasuredHeight < 0)
                    {
                        totalLength = Math.Max(totalLength, totalLength + childMarginHeight);
                    }
                    else
                    {
                        totalLength = Math.Max(totalLength, totalLength + childMeasuredHeight + childMarginHeight);
                    }
                }

                if (childLayout.MeasuredWidth.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
                {
                    childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall;
                }
                if (childLayout.MeasuredHeight.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
                {
                    childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall;
                }

                float childMeasuredWidth = childLayout.MeasuredWidth.Size.AsDecimal();
                if (childMeasuredWidth < 0)
                {
                    maxWidth = Math.Max(maxWidth, childMarginWidth);
                }
                else
                {
                    maxWidth = Math.Max(maxWidth, childMeasuredWidth + childMarginWidth);
                }
            } // 1ST PHASE foreach

            totalLength = Math.Max(totalLength, totalLength + CellPadding.Height * (childrenCount - 1) + Padding.Top + Padding.Bottom);
            float        heightSize         = Math.Max(totalLength, SuggestedMinimumHeight.AsDecimal());
            MeasuredSize heightSizeAndState = ResolveSizeAndState(new LayoutLength(heightSize), heightMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK);

            heightSize = heightSizeAndState.Size.AsDecimal();

            float remainingHeight   = heightSize - totalLength;
            float totalWeightLength = 0.0f;

            // 2ND PHASE:
            //
            // We measure all children whose height specification policy is MatchParent without weight.
            // After 2nd phase, all children's heights are calculated without considering weight.
            // And the heights of all weighted children are accumulated to calculate weighted height.
            foreach (LayoutItem childLayout in IterateLayoutChildren())
            {
                int     childDesiredWidth  = childLayout.Owner.WidthSpecification;
                int     childDesiredHeight = childLayout.Owner.HeightSpecification;
                float   childWeight        = childLayout.Owner.Weight;
                Extents childMargin        = childLayout.Margin;
                bool    useRemainingHeight = (childDesiredHeight == 0) && (childWeight > 0);
                bool    needToMeasure      = false;

                if ((childDesiredWidth == LayoutParamPolicies.MatchParent) || (useRemainingHeight))
                {
                    if (isWidthExactly)
                    {
                        needToMeasure = true;
                    }
                    // RelativeLayout's MatchParent children should not fill to the RelativeLayout.
                    // Because the children's sizes and positions are calculated by RelativeLayout's APIs.
                    // Therefore, not to fill the RelativeLayout, the mode is changed from Exactly to AtMost.
                    //
                    // Not to print the recursive reference error message for this case, Specification is checked if it is WrapContent.
                    else if (Owner.WidthSpecification == LayoutParamPolicies.WrapContent)
                    {
                        if (childDesiredWidth == LayoutParamPolicies.MatchParent)
                        {
                            Tizen.Log.Error("NUI", "There is a recursive reference! Parent layout(Owner: " + Owner + ")'s WidthSpecification is WrapContent and child layout(Owner: " + childLayout.Owner + ")'s WidthSpecification is MatchParent!");
                        }
                        else
                        {
                            Tizen.Log.Error("NUI", "There is a recursive reference! Parent layout(Owner: " + Owner + ")'s WidthSpecification is WrapContent and child layout(Owner: " + childLayout.Owner + ")'s WidthSpecification is 0 with positive weight!");
                        }
                    }
                }

                if (remainingHeight > 0)
                {
                    if ((childDesiredHeight == LayoutParamPolicies.MatchParent) || (useRemainingHeight))
                    {
                        if (isHeightExactly)
                        {
                            // In MeasureChildWithMargins(), it is assumed that heightMeasureSpec includes Padding.Top and Padding.Bottom.
                            // Therefore, Padding.Top and Padding.Bottom are added to heightMeasureSpec.Size before it is passed to MeasureChildWithMargins().
                            heightMeasureSpec.SetSize(new LayoutLength((int)(remainingHeight / childrenMatchParentCount) + Padding.Top + Padding.Bottom));
                            needToMeasure = true;
                        }
                        // RelativeLayout's MatchParent children should not fill to the RelativeLayout.
                        // Because the children's sizes and positions are calculated by RelativeLayout's APIs.
                        // Therefore, not to fill the RelativeLayout, the mode is changed from Exactly to AtMost.
                        //
                        // Not to print the recursive reference error message for this case, Specification is checked if it is WrapContent.
                        else if (Owner.HeightSpecification == LayoutParamPolicies.WrapContent)
                        {
                            if (childDesiredHeight == LayoutParamPolicies.MatchParent)
                            {
                                Tizen.Log.Error("NUI", "There is a recursive reference! Parent layout(Owner: " + Owner + ")'s HeightSpecification is WrapContent and child layout(Owner: " + childLayout.Owner + ")'s HeightSpecification is MatchParent!");
                            }
                            else
                            {
                                Tizen.Log.Error("NUI", "There is a recursive reference! Parent layout(Owner: " + Owner + ")'s HeightSpecification is WrapContent and child layout(Owner: " + childLayout.Owner + ")'s HeightSpecification is 0 with positive weight!");
                            }
                        }
                    }
                }

                if (needToMeasure == true)
                {
                    MeasureChildWithMargins(childLayout, widthMeasureSpec, new LayoutLength(0), heightMeasureSpec, new LayoutLength(0));
                }

                if (childWeight > 0)
                {
                    float childMeasuredHeight = childLayout.MeasuredHeight.Size.AsDecimal();

                    if (childMeasuredHeight < 0)
                    {
                        totalWeightLength = Math.Max(totalWeightLength, totalWeightLength + childMargin.Top + childMargin.Bottom);
                    }
                    else
                    {
                        totalWeightLength = Math.Max(totalWeightLength, totalWeightLength + childMeasuredHeight + childMargin.Top + childMargin.Bottom);
                    }
                }
            } // 2ND PHASE foreach

            // 3RD PHASE:
            //
            // We measure all weighted children whose owner has weight greater than 0.
            // After 3rd phase, all weighted children has height which is proportional to their weights
            // in remaining height of parent.
            if (totalWeight > 0)
            {
                foreach (LayoutItem childLayout in IterateLayoutChildren())
                {
                    int   childDesiredHeight = childLayout.Owner.HeightSpecification;
                    float childWeight        = childLayout.Owner.Weight;

                    if ((childWeight > 0) && ((childDesiredHeight == LayoutParamPolicies.MatchParent) || (childDesiredHeight == 0)))
                    {
                        if (isHeightExactly)
                        {
                            MeasureWeightedChild(childLayout, totalWeightLength, totalWeight, childWeight,
                                                 widthMeasureSpec, heightMeasureSpec, childState,
                                                 Orientation.Vertical);
                        }
                        // RelativeLayout's MatchParent children should not fill to the RelativeLayout.
                        // Because the children's sizes and positions are calculated by RelativeLayout's APIs.
                        // Therefore, not to fill the RelativeLayout, the mode is changed from Exactly to AtMost.
                        //
                        // Not to print the recursive reference error message for this case, Specification is checked if it is WrapContent.
                        else if (Owner.HeightSpecification == LayoutParamPolicies.WrapContent)
                        {
                            if (childDesiredHeight == LayoutParamPolicies.MatchParent)
                            {
                                Tizen.Log.Error("NUI", "There is a recursive reference! Parent layout(Owner: " + Owner + ")'s HeightSpecification is WrapContent and child layout(Owner: " + childLayout.Owner + ")'s HeightSpecification is MatchParent!");
                            }
                            else
                            {
                                Tizen.Log.Error("NUI", "There is a recursive reference! Parent layout(Owner: " + Owner + ")'s HeightSpecification is WrapContent and child layout(Owner: " + childLayout.Owner + ")'s HeightSpecification is 0 with positive weight!");
                            }
                        }
                    }
                } // 3RD PHASE foreach
            }

            maxWidth = Math.Max(maxWidth, maxWidth + (Padding.Start + Padding.End));
            maxWidth = Math.Max(maxWidth, SuggestedMinimumWidth.AsRoundedValue());

            heightSizeAndState.State = childState.heightState;

            SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(maxWidth), widthMeasureSpec, childState.widthState),
                                  heightSizeAndState);
        } // MeasureVertical
Example #12
0
        /// <summary>
        /// Measure the layout and its content to determine the measured width and the measured height.<br />
        /// </summary>
        /// <param name="widthMeasureSpec">horizontal space requirements as imposed by the parent.</param>
        /// <param name="heightMeasureSpec">vertical space requirements as imposed by the parent.</param>
        /// <since_tizen> 6 </since_tizen>
        protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
        {
            bool    isLayoutRtl = Owner.LayoutDirection == ViewLayoutDirectionType.RTL;
            Extents padding     = Owner.Padding;
            Extents margin      = Owner.Margin;

            Interop.FlexLayout.FlexLayout_SetMargin(swigCPtr, Extents.getCPtr(margin));
            Interop.FlexLayout.FlexLayout_SetPadding(swigCPtr, Extents.getCPtr(padding));

            float width  = FlexUndefined; // Behaves as WrapContent (Flex Auto)
            float height = FlexUndefined; // Behaves as WrapContent (Flex Auto)

            if (widthMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly || widthMeasureSpec.Mode == MeasureSpecification.ModeType.AtMost)
            {
                width = widthMeasureSpec.Size.AsDecimal();
            }

            if (heightMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly || heightMeasureSpec.Mode == MeasureSpecification.ModeType.AtMost)
            {
                height = heightMeasureSpec.Size.AsDecimal();
            }

            // Save measureSpec to measure children.
            // In other Layout, we can pass it as parameter to measuring child but in FlexLayout we can't
            // because measurChild function is called by native callback.
            parentMeasureSpecificationWidth  = widthMeasureSpec;
            parentMeasureSpecificationHeight = heightMeasureSpec;

            // Assign child properties
            for (int i = 0; i < LayoutChildren.Count; i++)
            {
                LayoutItem layoutItem     = LayoutChildren[i];
                View       Child          = layoutItem?.Owner;
                HandleRef  childHandleRef = (HandleRef)Child.GetValue(FlexItemProperty);
                if (childHandleRef.Handle == IntPtr.Zero || Child == null)
                {
                    continue;
                }

                AlignmentType flexAlignemnt   = GetFlexAlignmentSelf(Child);
                PositionType  flexPosition    = GetFlexPositionType(Child);
                float         flexAspectRatio = GetFlexAspectRatio(Child);
                float         flexBasis       = GetFlexBasis(Child);
                float         flexShrink      = GetFlexShrink(Child);
                float         flexGrow        = GetFlexGrow(Child);

                Interop.FlexLayout.FlexLayout_SetFlexAlignmentSelf(childHandleRef, (int)flexAlignemnt);
                Interop.FlexLayout.FlexLayout_SetFlexPositionType(childHandleRef, (int)flexPosition);
                Interop.FlexLayout.FlexLayout_SetFlexAspectRatio(childHandleRef, flexAspectRatio);
                Interop.FlexLayout.FlexLayout_SetFlexBasis(childHandleRef, flexBasis);
                Interop.FlexLayout.FlexLayout_SetFlexShrink(childHandleRef, flexShrink);
                Interop.FlexLayout.FlexLayout_SetFlexGrow(childHandleRef, flexGrow);
            }

            Interop.FlexLayout.FlexLayout_CalculateLayout(swigCPtr, width, height, isLayoutRtl);

            LayoutLength flexLayoutWidth  = new LayoutLength(Interop.FlexLayout.FlexLayout_GetWidth(swigCPtr));
            LayoutLength flexLayoutHeight = new LayoutLength(Interop.FlexLayout.FlexLayout_GetHeight(swigCPtr));

            Debug.WriteLineIf(LayoutDebugFlex, "FlexLayout OnMeasure width:" + flexLayoutWidth.AsRoundedValue()
                              + " height:" + flexLayoutHeight.AsRoundedValue());

            SetMeasuredDimensions(GetDefaultSize(flexLayoutWidth, widthMeasureSpec),
                                  GetDefaultSize(flexLayoutHeight, heightMeasureSpec));
        }
Example #13
0
        /// <inheritdoc/>
        /// <since_tizen> 9 </since_tizen>
        protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
        {
            MeasuredSize.StateType childWidthState  = MeasuredSize.StateType.MeasuredSizeOK;
            MeasuredSize.StateType childHeightState = MeasuredSize.StateType.MeasuredSizeOK;

            for (int i = 0; i < LayoutChildren.Count; i++)
            {
                LayoutItem childLayout = LayoutChildren[i];
                if (childLayout != null)
                {
                    MeasureChildWithMargins(childLayout, widthMeasureSpec, new LayoutLength(0), heightMeasureSpec, new LayoutLength(0));

                    if (childLayout.MeasuredWidth.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
                    {
                        childWidthState = MeasuredSize.StateType.MeasuredSizeTooSmall;
                    }
                    if (childLayout.MeasuredHeight.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
                    {
                        childHeightState = MeasuredSize.StateType.MeasuredSizeTooSmall;
                    }
                }
            }

            (float childrenWidth, float childrenHeight) = CalculateChildrenSize(widthMeasureSpec.Size.AsDecimal(), heightMeasureSpec.Size.AsDecimal());
            SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(childrenWidth), widthMeasureSpec, childWidthState),
                                  ResolveSizeAndState(new LayoutLength(childrenHeight), heightMeasureSpec, childHeightState));

            // RelativeLayout sets its children's size in OnLayout().
            // Therefore, the children's MeasuredWidth/Height are not the same with the children's size.
            // This causes that the grand children's MeasuredWidth/Height are calculated incorrectly.
            // To resolve the above, RelativeLayout updates its children's MeasuredWidth/Height after
            // the RelativeLayout's MeasuredWidth/Height are calculated.
            //
            // e.g.
            // Let parent have RelativeLayout and parent's size be 1920x1080.
            // Let child have WrapContent with SetFillHorizontal/Vertical true.
            // Let grand child have MatchParent.
            // Then, child's size is 1920x1080 but child's MeasuredWidth/Height is 0x0.
            // Then, grand child's MeasuredWidth/Height is 0x0 and size is 0x0.
            //
            // TODO: Not to do the following operation in OnLayout() again.
            for (int i = 0; i < LayoutChildren.Count; i++)
            {
                LayoutItem childLayout = LayoutChildren[i];
                if (childLayout != null)
                {
                    LayoutLength childLeft;
                    LayoutLength childRight;
                    LayoutLength childTop;
                    LayoutLength childBottom;

                    if (childLayout.Owner.WidthSpecification == LayoutParamPolicies.MatchParent)
                    {
                        childLeft  = new LayoutLength(childLayout.Margin.Start);
                        childRight = new LayoutLength(MeasuredWidth.Size.AsDecimal() - childLayout.Margin.End);
                    }
                    else
                    {
                        Geometry horizontalGeometry = GetHorizontalLayout(childLayout.Owner);

                        childLeft  = new LayoutLength(horizontalGeometry.Position + Padding.Start + childLayout.Margin.Start);
                        childRight = new LayoutLength(horizontalGeometry.Position + horizontalGeometry.Size + Padding.Start - childLayout.Margin.End);
                    }

                    if (childLayout.Owner.HeightSpecification == LayoutParamPolicies.MatchParent)
                    {
                        childTop    = new LayoutLength(childLayout.Margin.Top);
                        childBottom = new LayoutLength(MeasuredHeight.Size.AsDecimal() - childLayout.Margin.Bottom);
                    }
                    else
                    {
                        Geometry verticalGeometry = GetVerticalLayout(childLayout.Owner);

                        childTop    = new LayoutLength(verticalGeometry.Position + Padding.Top + childLayout.Margin.Top);
                        childBottom = new LayoutLength(verticalGeometry.Position + verticalGeometry.Size + Padding.Top - childLayout.Margin.Bottom);
                    }

                    // Padding sizes are added because Padding sizes will be subtracted in MeasureChild().
                    MeasureSpecification childWidthMeasureSpec  = new MeasureSpecification(new LayoutLength(childRight.AsDecimal() - childLeft.AsDecimal() + Padding.Start + Padding.End), MeasureSpecification.ModeType.Exactly);
                    MeasureSpecification childHeightMeasureSpec = new MeasureSpecification(new LayoutLength(childBottom.AsDecimal() - childTop.AsDecimal() + Padding.Top + Padding.Bottom), MeasureSpecification.ModeType.Exactly);

                    int origWidthSpecification  = childLayout.Owner.WidthSpecification;
                    int origHeightSpecification = childLayout.Owner.HeightSpecification;

                    // To calculate the grand children's Measure() with the mode type Exactly,
                    // children's Measure() is called with MatchParent if the children have WrapContent.
                    //
                    // i.e.
                    // If children have Wrapcontent and the grand children have MatchParent,
                    // then grand children's MeasuredWidth/Height do not fill the children
                    // because the grand children's Measure() is called with the mode type AtMost.
                    if (childLayout.Owner.WidthSpecification == LayoutParamPolicies.WrapContent)
                    {
                        childLayout.Owner.WidthSpecification = LayoutParamPolicies.MatchParent;
                    }
                    if (childLayout.Owner.HeightSpecification == LayoutParamPolicies.WrapContent)
                    {
                        childLayout.Owner.HeightSpecification = LayoutParamPolicies.MatchParent;
                    }

                    // Use MeasureChild() because Margin sizes were already subtracted from childWidth/HeightMeasureSpec.
                    MeasureChild(childLayout, childWidthMeasureSpec, childHeightMeasureSpec);

                    childLayout.Owner.WidthSpecification  = origWidthSpecification;
                    childLayout.Owner.HeightSpecification = origHeightSpecification;
                }
            }
        }
Example #14
0
        /// <summary>
        /// Measure the layout and its content to determine the measured width and the measured height.<br />
        /// </summary>
        /// <param name="widthMeasureSpec">horizontal space requirements as imposed by the parent.</param>
        /// <param name="heightMeasureSpec">vertical space requirements as imposed by the parent.</param>
        /// <since_tizen> 6 </since_tizen>
        protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
        {
            var gridWidthMode  = widthMeasureSpec.Mode;
            var gridHeightMode = heightMeasureSpec.Mode;
            int widthSize      = (int)widthMeasureSpec.Size.AsRoundedValue();
            int heightSize     = (int)heightMeasureSpec.Size.AsRoundedValue();

            int availableContentWidth;
            int availableContentHeight;

            int desiredChildHeight;
            int desiredChildWidth;

            Extents gridLayoutPadding = Padding;

            var childCount = LayoutChildren.Count;

            // WIDTH SPECIFICATIONS

            // measure first child and use it's dimensions for layout measurement

            if (childCount > 0)
            {
                LayoutItem childLayoutItem = LayoutChildren[0];
                View       childOwner      = childLayoutItem.Owner;

                MeasureChild(childLayoutItem, widthMeasureSpec, heightMeasureSpec);
                desiredChildHeight = (int)childLayoutItem.MeasuredHeight.Size.AsRoundedValue();
                desiredChildWidth  = (int)childLayoutItem.MeasuredWidth.Size.AsRoundedValue();

                // If child has a margin then add it to desired size
                Extents childMargin = childLayoutItem.Margin;
                desiredChildHeight += childMargin.Top + childMargin.Bottom;
                desiredChildWidth  += childMargin.Start + childMargin.End;

                _totalWidth = desiredChildWidth * _columns;

                // Include padding for max and min checks
                _totalWidth += gridLayoutPadding.Start + gridLayoutPadding.End;

                // Ensure width does not exceed specified at most width or less than mininum width
                _totalWidth = Math.Max(_totalWidth, (int)SuggestedMinimumWidth.AsRoundedValue());

                // widthMode EXACTLY so grid must be the given width
                if (gridWidthMode == MeasureSpecification.ModeType.Exactly || gridWidthMode == MeasureSpecification.ModeType.AtMost)
                {
                    // In the case of AT_MOST, widthSize is the max limit.
                    _totalWidth = Math.Min(_totalWidth, widthSize);
                }

                availableContentWidth = _totalWidth - gridLayoutPadding.Start - gridLayoutPadding.End;
                widthSize             = _totalWidth;

                // HEIGHT SPECIFICATIONS

                // heightMode EXACTLY so grid must be the given height
                if (gridHeightMode == MeasureSpecification.ModeType.Exactly || gridHeightMode == MeasureSpecification.ModeType.AtMost)
                {
                    if (childCount > 0)
                    {
                        _totalHeight = gridLayoutPadding.Top + gridLayoutPadding.Bottom;

                        for (int i = 0; i < childCount; i += _columns)
                        {
                            _totalHeight += desiredChildHeight;
                        }

                        // Ensure ourHeight does not exceed specified at most height
                        _totalHeight = Math.Min(_totalHeight, heightSize);
                        _totalHeight = Math.Max(_totalHeight, (int)SuggestedMinimumHeight.AsRoundedValue());

                        heightSize = _totalHeight;
                    } // Child exists

                    // In the case of AT_MOST, availableContentHeight is the max limit.
                    availableContentHeight = heightSize - gridLayoutPadding.Top - gridLayoutPadding.Bottom;
                }
                else
                {
                    // Grid expands to fit content

                    // If number of columns AUTO_FIT then set to 1 column.
                    _columns = (_columns > 0) ? _columns : 1;
                    // Calculate numbers of rows, round down result as later check for remainder.
                    _rows = childCount / _columns;
                    // If number of cells not cleanly dividable by columns, add another row to house remainder cells.
                    _rows += (childCount % _columns > 0) ? 1 : 0;

                    availableContentHeight = desiredChildHeight * _rows;
                }

                // If number of columns not defined
                DetermineNumberOfColumns(availableContentWidth);

                // Locations define the start, end,top and bottom of each cell.
                _locations.CalculateLocations(_columns, availableContentWidth, availableContentHeight, childCount);
            } // Children exists

            SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(widthSize), widthMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK),
                                  ResolveSizeAndState(new LayoutLength(heightSize), heightMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK));
        }
Example #15
0
        /// <summary>
        /// Ask one of the children of this view to measure itself, taking into
        /// account both the MeasureSpec requirements for this view and its padding.<br />
        /// and margins. The child must have MarginLayoutParams The heavy lifting is
        /// done in GetChildMeasureSpecification.<br />
        /// </summary>
        /// <param name="child">The child to measure.</param>
        /// <param name="parentWidthMeasureSpec">The width requirements for this view.</param>
        /// <param name="widthUsed">Extra space that has been used up by the parent horizontally (possibly by other children of the parent).</param>
        /// <param name="parentHeightMeasureSpec">The height requirements for this view.</param>
        /// <param name="heightUsed">Extra space that has been used up by the parent vertically (possibly by other children of the parent).</param>
        /// <since_tizen> 6 </since_tizen>
        protected virtual void MeasureChildWithMargins(LayoutItem child, MeasureSpecification parentWidthMeasureSpec, LayoutLength widthUsed, MeasureSpecification parentHeightMeasureSpec, LayoutLength heightUsed)
        {
            View childOwner = child.Owner;


            MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification(
                new MeasureSpecification(
                    new LayoutLength(parentWidthMeasureSpec.Size + widthUsed - (Padding.Start + Padding.End + childOwner.Margin.Start + childOwner.Margin.End)),
                    parentWidthMeasureSpec.Mode),
                new LayoutLength(Padding.Start + Padding.End),
                new LayoutLength(childOwner.WidthSpecification));

            MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification(
                new MeasureSpecification(
                    new LayoutLength(parentHeightMeasureSpec.Size + heightUsed - (Padding.Top + Padding.Bottom + childOwner.Margin.Top + childOwner.Margin.Bottom)),
                    parentHeightMeasureSpec.Mode),
                new LayoutLength(Padding.Top + Padding.Bottom),
                new LayoutLength(childOwner.HeightSpecification));

            child.Measure(childWidthMeasureSpec, childHeightMeasureSpec);
        }
Example #16
0
        // Starts of the actual measuring and layouting from the given root node.
        // Can be called from multiple starting roots but in series.
        void MeasureAndLayout(View root)
        {
            if (root != null)
            {
                // Get parent MeasureSpecification, this could be the Window or View with an exact size.
                Container  parentNode = root.GetParent();
                Size2D     rootSize;
                Position2D rootPosition = root.Position2D;
                View       parentView   = parentNode as View;
                if (parentView)
                {
                    // Get parent View's Size.  If using Legacy size negotiation then should have been set already.
                    rootSize = new Size2D(parentView.Size2D.Width, parentView.Size2D.Height);
                }
                else
                {
                    // Parent not a View so assume it's a Layer which is the size of the window.
                    rootSize = new Size2D(_window.Size.Width, _window.Size.Height);
                }

                // Determine measure specification for root.
                // The root layout policy could be an exact size, be match parent or wrap children.
                // If wrap children then at most it can be the root parent size.
                // If match parent then should be root parent size.
                // If exact then should be that size limited by the root parent size.

                LayoutLength width  = new LayoutLength(rootSize.Width);
                LayoutLength height = new LayoutLength(rootSize.Height);
                MeasureSpecification.ModeType widthMode  = MeasureSpecification.ModeType.AtMost;
                MeasureSpecification.ModeType heightMode = MeasureSpecification.ModeType.AtMost;

                if (root.WidthSpecification >= 0)
                {
                    // exact size provided so match width exactly
                    width     = new LayoutLength(root.WidthSpecification);
                    widthMode = MeasureSpecification.ModeType.Exactly;
                }
                else if (root.WidthSpecification == LayoutParamPolicies.MatchParent)
                {
                    widthMode = MeasureSpecification.ModeType.Exactly;
                }

                if (root.HeightSpecification >= 0)
                {
                    // exact size provided so match height exactly
                    height     = new LayoutLength(root.HeightSpecification);
                    heightMode = MeasureSpecification.ModeType.Exactly;
                }
                else if (root.HeightSpecification == LayoutParamPolicies.MatchParent)
                {
                    heightMode = MeasureSpecification.ModeType.Exactly;
                }

                MeasureSpecification parentWidthSpecification =
                    new MeasureSpecification(width, widthMode);

                MeasureSpecification parentHeightSpecification =
                    new MeasureSpecification(height, heightMode);

                // Start at root with it's parent's widthSpecification and heightSpecification
                MeasureHierarchy(root, parentWidthSpecification, parentHeightSpecification);

                // Start at root which was just measured.
                PerformLayout(root, new LayoutLength(rootPosition.X),
                              new LayoutLength(rootPosition.Y),
                              new LayoutLength(rootPosition.X) + root.Layout.MeasuredWidth.Size,
                              new LayoutLength(rootPosition.Y) + root.Layout.MeasuredHeight.Size);

                bool readyToPlay = SetupCoreAnimation();

                if (readyToPlay && OverrideCoreAnimation == false)
                {
                    PlayAnimation();
                }
            }
        }
Example #17
0
        /// <summary>
        /// Calculate the right measure spec for this child.
        /// Does the hard part of MeasureChildren: figuring out the MeasureSpec to
        /// pass to a particular child. This method figures out the right MeasureSpec
        /// for one dimension (height or width) of one child view.<br />
        /// </summary>
        /// <param name="parentMeasureSpec">The requirements for this view. MeasureSpecification.</param>
        /// <param name="padding">The padding of this view for the current dimension and margins, if applicable. LayoutLength.</param>
        /// <param name="childDimension"> How big the child wants to be in the current dimension. LayoutLength.</param>
        /// <returns>a MeasureSpec for the child.</returns>
        public static MeasureSpecification GetChildMeasureSpecification(MeasureSpecification parentMeasureSpec, LayoutLength padding, LayoutLength childDimension)
        {
            MeasureSpecification.ModeType specMode   = parentMeasureSpec.Mode;
            MeasureSpecification.ModeType resultMode = MeasureSpecification.ModeType.Unspecified;
            LayoutLength resultSize = new LayoutLength(Math.Max(0.0f, (parentMeasureSpec.Size.AsDecimal() - padding.AsDecimal())));    // reduce available size by the owners padding

            switch (specMode)
            {
            // Parent has imposed an exact size on us
            case MeasureSpecification.ModeType.Exactly:
            {
                if ((int)childDimension.AsRoundedValue() == LayoutParamPolicies.MatchParent)
                {
                    // Child wants to be our size. So be it.
                    resultMode = MeasureSpecification.ModeType.Exactly;
                }
                else if ((int)childDimension.AsRoundedValue() == LayoutParamPolicies.WrapContent)
                {
                    // Child wants to determine its own size. It can't be
                    // bigger than us.
                    resultMode = MeasureSpecification.ModeType.AtMost;
                }
                else
                {
                    resultSize = childDimension;
                    resultMode = MeasureSpecification.ModeType.Exactly;
                }

                break;
            }

            // Parent has imposed a maximum size on us
            case MeasureSpecification.ModeType.AtMost:
            {
                if (childDimension.AsRoundedValue() == LayoutParamPolicies.MatchParent)
                {
                    // Child wants to be our size, but our size is not fixed.
                    // Constrain child to not be bigger than us.
                    resultMode = MeasureSpecification.ModeType.AtMost;
                }
                else if (childDimension.AsRoundedValue() == LayoutParamPolicies.WrapContent)
                {
                    // Child wants to determine its own size. It can't be
                    // bigger than us.
                    resultMode = MeasureSpecification.ModeType.AtMost;
                }
                else
                {
                    // Child wants a specific size... so be it
                    resultSize = childDimension + padding;
                    resultMode = MeasureSpecification.ModeType.Exactly;
                }

                break;
            }

            // Parent asked to see how big we want to be
            case MeasureSpecification.ModeType.Unspecified:
            {
                if ((childDimension.AsRoundedValue() == LayoutParamPolicies.MatchParent))
                {
                    // Child wants to be our size... find out how big it should be
                    resultMode = MeasureSpecification.ModeType.Unspecified;
                }
                else if (childDimension.AsRoundedValue() == (LayoutParamPolicies.WrapContent))
                {
                    // Child wants to determine its own size.... find out how big
                    // it should be
                    resultMode = MeasureSpecification.ModeType.Unspecified;
                }
                else
                {
                    // Child wants a specific size... let him have it
                    resultSize = childDimension + padding;
                    resultMode = MeasureSpecification.ModeType.Exactly;
                }
                break;
            }
            } // switch

            return(new MeasureSpecification(resultSize, resultMode));
        }
Example #18
0
 internal override void OnMeasureIndependentChildren(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
 {
     foreach (LayoutItem childLayout in LayoutChildren.Where(item => item?.Owner?.ExcludeLayouting ?? false))
     {
         MeasureChildWithoutPadding(childLayout, widthMeasureSpec, heightMeasureSpec);
     }
 }
Example #19
0
 /// <summary>
 /// Ask all of the children of this view to measure themselves, taking into
 /// account both the MeasureSpec requirements for this view and its padding.<br />
 /// The heavy lifting is done in GetChildMeasureSpec.<br />
 /// </summary>
 /// <param name="widthMeasureSpec">The width requirements for this view.</param>
 /// <param name="heightMeasureSpec">The height requirements for this view.</param>
 protected virtual void MeasureChildren(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
 {
     foreach (LayoutItem childLayout in _children)
     {
         MeasureChild(childLayout, widthMeasureSpec, heightMeasureSpec);
     }
 }
Example #20
0
        /// <summary>
        /// Ask one of the children of this view to measure itself, taking into
        /// account both the MeasureSpec requirements for this view and its padding.<br />
        /// The heavy lifting is done in GetChildMeasureSpecification.<br />
        /// </summary>
        /// <param name="child">The child to measure.</param>
        /// <param name="parentWidthMeasureSpec">The width requirements for this view.</param>
        /// <param name="parentHeightMeasureSpec">The height requirements for this view.</param>
        /// <exception cref="ArgumentNullException"> Thrown when child is null. </exception>
        /// <since_tizen> 6 </since_tizen>
        protected virtual void MeasureChild(LayoutItem child, MeasureSpecification parentWidthMeasureSpec, MeasureSpecification parentHeightMeasureSpec)
        {
            if (null == child)
            {
                throw new ArgumentNullException(nameof(child));
            }

            View childOwner = child.Owner;

            MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification(
                new MeasureSpecification(new LayoutLength(parentWidthMeasureSpec.Size), parentWidthMeasureSpec.Mode),
                new LayoutLength(Padding.Start + Padding.End),
                new LayoutLength(childOwner.WidthSpecification));

            MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification(
                new MeasureSpecification(new LayoutLength(parentHeightMeasureSpec.Size), parentHeightMeasureSpec.Mode),
                new LayoutLength(Padding.Top + Padding.Bottom),
                new LayoutLength(childOwner.HeightSpecification));

            child.Measure(childWidthMeasureSpec, childHeightMeasureSpec);
        }
Example #21
0
        /// <summary>
        /// Ask one of the children of this view to measure itself, taking into
        /// account both the MeasureSpec requirements for this view and its padding.<br />
        /// The heavy lifting is done in GetChildMeasureSpec.<br />
        /// </summary>
        /// <param name="child">The child to measure.</param>
        /// <param name="parentWidthMeasureSpec">The width requirements for this view.</param>
        /// <param name="parentHeightMeasureSpec">The height requirements for this view.</param>
        protected virtual void MeasureChild(LayoutItem child, MeasureSpecification parentWidthMeasureSpec, MeasureSpecification parentHeightMeasureSpec)
        {
            View childOwner = child.Owner;

            Extents padding = child.Padding; // Padding of this layout's owner, not of the child being measured.

            MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification(parentWidthMeasureSpec,
                                                                                      new LayoutLength(padding.Start + padding.End),
                                                                                      new LayoutLength(childOwner.WidthSpecification));

            MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification(parentHeightMeasureSpec,
                                                                                       new LayoutLength(padding.Top + padding.Bottom),
                                                                                       new LayoutLength(childOwner.HeightSpecification));

            child.Measure(childWidthMeasureSpec, childHeightMeasureSpec);
        }
Example #22
0
        protected void MeasureChildWithoutPadding(LayoutItem child, MeasureSpecification parentWidthMeasureSpec, MeasureSpecification parentHeightMeasureSpec)
        {
            View childOwner = child.Owner;

            MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification(
                new MeasureSpecification(new LayoutLength(parentWidthMeasureSpec.Size), parentWidthMeasureSpec.Mode),
                new LayoutLength(0),
                new LayoutLength(childOwner.WidthSpecification));

            MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification(
                new MeasureSpecification(new LayoutLength(parentHeightMeasureSpec.Size), parentHeightMeasureSpec.Mode),
                new LayoutLength(0),
                new LayoutLength(childOwner.HeightSpecification));

            child.Measure(childWidthMeasureSpec, childHeightMeasureSpec);
        }
Example #23
0
        /// <summary>
        /// Ask one of the children of this view to measure itself, taking into
        /// account both the MeasureSpec requirements for this view and its padding.<br />
        /// and margins. The child must have MarginLayoutParams The heavy lifting is
        /// done in GetChildMeasureSpecification.<br />
        /// </summary>
        /// <param name="child">The child to measure.</param>
        /// <param name="parentWidthMeasureSpec">The width requirements for this view.</param>
        /// <param name="widthUsed">Extra space that has been used up by the parent horizontally (possibly by other children of the parent).</param>
        /// <param name="parentHeightMeasureSpec">The height requirements for this view.</param>
        /// <param name="heightUsed">Extra space that has been used up by the parent vertically (possibly by other children of the parent).</param>
        protected virtual void MeasureChildWithMargins(LayoutItem child, MeasureSpecification parentWidthMeasureSpec, LayoutLength widthUsed, MeasureSpecification parentHeightMeasureSpec, LayoutLength heightUsed)
        {
            View childOwner    = child.Owner;
            int  desiredWidth  = childOwner.WidthSpecification;
            int  desiredHeight = childOwner.HeightSpecification;

            Extents padding = child.Padding; // Padding of this layout's owner, not of the child being measured.

            MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification(parentWidthMeasureSpec,
                                                                                      new LayoutLength(padding.Start + padding.End) +
                                                                                      widthUsed, new LayoutLength(desiredWidth));


            MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification(parentHeightMeasureSpec,
                                                                                       new LayoutLength(padding.Top + padding.Bottom) +
                                                                                       heightUsed, new LayoutLength(desiredHeight));

            child.Measure(childWidthMeasureSpec, childHeightMeasureSpec);
        }
Example #24
0
 /// <summary>
 /// Measure the layout and its content to determine the measured width and the
 /// measured height.<br />
 /// The base class implementation of measure defaults to the background size,
 /// unless a larger size is allowed by the MeasureSpec. Subclasses should
 /// override to provide better measurements of their content.<br />
 /// If this method is overridden, it is the subclass's responsibility to make sure the
 /// measured height and width are at least the layout's minimum height and width.<br />
 /// </summary>
 /// <param name="widthMeasureSpec">horizontal space requirements as imposed by the parent.</param>
 /// <param name="heightMeasureSpec">vertical space requirements as imposed by the parent.</param>
 /// <since_tizen> 6 </since_tizen>
 protected virtual void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
 {
     // GetDefaultSize will limit the MeasureSpec to the suggested minimumWidth and minimumHeight
     SetMeasuredDimensions(GetDefaultSize(SuggestedMinimumWidth, widthMeasureSpec),
                           GetDefaultSize(SuggestedMinimumHeight, heightMeasureSpec));
 }
Example #25
0
        private void MeasureWeightedChild(LayoutItem childLayout, float remainingExcess, float remainingWeight, float childWeight,
                                          MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec,
                                          HeightAndWidthState childState, Orientation orientation)
        {
            bool horizontal = false;

            if (orientation == Orientation.Horizontal)
            {
                horizontal = true;
            }

            float childsShare = (childWeight * remainingExcess) / remainingWeight;

            remainingExcess -= childsShare;
            remainingWeight -= childWeight;

            float desiredWidth  = childLayout.Owner.WidthSpecification;
            float desiredHeight = childLayout.Owner.HeightSpecification;
            float childLength   = 0;

            // Always lay out weighted elements with intrinsic size regardless of the parent spec.
            // for consistency between specs.
            if ((horizontal && (desiredWidth == 0)) || (!horizontal && (desiredHeight == 0)))
            {
                // This child needs to be laid out from scratch using
                // only its share of excess space.
                childLength = childsShare;
            }
            else
            {
                // This child had some intrinsic width to which we
                // need to add its share of excess space.
                if (horizontal)
                {
                    childLength = childLayout.MeasuredWidth.Size.AsDecimal() + childsShare;
                }
                else
                {
                    childLength = childLayout.MeasuredHeight.Size.AsDecimal() + childsShare;
                }
            }

            MeasureSpecification childWidthMeasureSpec;
            MeasureSpecification childHeightMeasureSpec;

            if (horizontal)
            {
                childWidthMeasureSpec  = new MeasureSpecification(new LayoutLength(childLength), MeasureSpecification.ModeType.Exactly);
                childHeightMeasureSpec = GetChildMeasureSpecification(
                    new MeasureSpecification(
                        new LayoutLength(heightMeasureSpec.Size - (childLayout.Owner.Margin.Top + childLayout.Owner.Margin.Bottom)),
                        heightMeasureSpec.Mode),
                    new LayoutLength(Padding.Top + Padding.Bottom),
                    new LayoutLength(desiredHeight));
            }
            else // vertical
            {
                childWidthMeasureSpec = GetChildMeasureSpecification(
                    new MeasureSpecification(
                        new LayoutLength(widthMeasureSpec.Size - (childLayout.Owner.Margin.Start + childLayout.Owner.Margin.End)),
                        widthMeasureSpec.Mode),
                    new LayoutLength(Padding.Start + Padding.End),
                    new LayoutLength(desiredWidth));

                childHeightMeasureSpec = new MeasureSpecification(new LayoutLength(childLength), MeasureSpecification.ModeType.Exactly);
            }

            childLayout.Measure(childWidthMeasureSpec, childHeightMeasureSpec);

            // Child may now not fit in horizontal dimension.
            if (childLayout.MeasuredWidth.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
            {
                childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall;
            }

            // Child may now not fit in vertical dimension.
            if (childLayout.MeasuredHeight.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
            {
                childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall;
            }
        }
Example #26
0
        private void InitChildrenData(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
        {
            bool isHorizontal = (GridOrientation == Orientation.Horizontal);
            int  mainPivot = 0, subPivot = 0;

            int[] pivotStack = new int[isHorizontal ? Columns : Rows];

            vLocations     = hLocations = null;
            vEdgeList      = hEdgeList = null;
            gridChildren   = new List <GridChild>();
            maxColumnConut = Columns;
            maxRowCount    = Rows;

            totalVerticalExpand   = 0;
            totalHorizontalExpand = 0;

            foreach (LayoutItem item in IterateLayoutChildren())
            {
                int          column, columnSpan, row, rowSpan;
                StretchFlags verticalStretch, horizontalStretch;
                View         view = item.Owner;

                column            = GetColumn(view);
                columnSpan        = GetColumnSpan(view);
                row               = GetRow(view);
                rowSpan           = GetRowSpan(view);
                verticalStretch   = GetVerticalStretch(view);
                horizontalStretch = GetHorizontalStretch(view);

                if (column + columnSpan > maxColumnConut || row + rowSpan > maxRowCount)
                {
                    if (column + columnSpan > maxColumnConut)
                    {
                        Tizen.Log.Error("NUI", "Column + ColumnSapn exceeds Grid Columns. Column + ColumnSpan (" + column + " + " + columnSpan + ") > Grid Columns(" + maxColumnConut + ")");
                    }
                    else
                    {
                        Tizen.Log.Error("NUI", "Row + RowSapn exceeds Grid Rows. Row + RowSapn (" + row + " + " + rowSpan + ") > Grid Rows(" + maxRowCount + ")");
                    }

                    gridChildren.Add(new GridChild(null, new Node(0, 1, 0, 0), new Node(0, 1, 0, 0)));

                    continue;
                }

                if (horizontalStretch.HasFlag(StretchFlags.Expand))
                {
                    totalHorizontalExpand++;
                }

                if (verticalStretch.HasFlag(StretchFlags.Expand))
                {
                    totalVerticalExpand++;
                }

                // assign column/row depending on GridOrientation. The main axis count(Columns on Horizontal, Rows otherwise) won't be exceeded
                // explicit column(row) count which is assigned by Columns(Rows). but, cross axis count(Rows(Columns)) can be increased by sub axis count.
                if (column == AutoColumn || row == AutoRow)
                {
                    (int point, int span)mainAxis = isHorizontal ? (column, columnSpan) : (row, rowSpan);
                    (int point, int span)subAxis  = isHorizontal ? (row, rowSpan) : (column, columnSpan);

                    if (subAxis.point != AutoColumn && subAxis.point != AutoRow)
                    {
                        subPivot = subAxis.point;
                    }
                    if (mainAxis.point != AutoColumn && mainAxis.point != AutoRow)
                    {
                        mainPivot = mainAxis.point;
                    }

                    if (mainPivot + mainAxis.span > pivotStack.Length)
                    {
                        mainPivot = 0;
                        subPivot++;
                    }

                    for (int n = mainPivot + mainAxis.span - 1; n >= mainPivot; n--)
                    {
                        if (pivotStack[n] > subPivot)
                        {
                            mainPivot = n + 1;
                            n         = mainPivot + mainAxis.span;

                            if (n > pivotStack.Length)
                            {
                                if (mainAxis.point != AutoColumn && mainAxis.point != AutoRow)
                                {
                                    mainPivot = mainAxis.point;
                                }
                                else
                                {
                                    mainPivot = 0;
                                }

                                n = mainPivot + mainAxis.span;
                                subPivot++;
                            }
                        }
                    }

                    if (isHorizontal)
                    {
                        column = mainPivot;
                        row    = subPivot;
                    }
                    else
                    {
                        column = subPivot;
                        row    = mainPivot;
                    }

                    for (int start = mainPivot, end = mainPivot + mainAxis.span; start < end; start++)
                    {
                        pivotStack[start] = subPivot + subAxis.span;
                    }

                    mainPivot += mainAxis.span;
                }

                if (maxColumnConut < column + columnSpan)
                {
                    maxColumnConut = column + columnSpan;
                }
                if (maxRowCount < row + rowSpan)
                {
                    maxRowCount = row + rowSpan;
                }

                MeasureChildWithMargins(item, widthMeasureSpec, new LayoutLength(0), heightMeasureSpec, new LayoutLength(0));
                gridChildren.Add(new GridChild(item,
                                               new Node(column, columnSpan, item.MeasuredWidth.Size.AsDecimal() + item.Owner.Margin.Start + item.Owner.Margin.End, horizontalStretch),
                                               new Node(row, rowSpan, item.MeasuredHeight.Size.AsDecimal() + item.Owner.Margin.Top + item.Owner.Margin.Bottom, verticalStretch)));
            }
        }
Example #27
0
        private void MeasureHorizontal(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
        {
            var   widthMode            = widthMeasureSpec.Mode;
            var   heightMode           = heightMeasureSpec.Mode;
            bool  isExactly            = (widthMode == MeasureSpecification.ModeType.Exactly);
            bool  matchHeight          = false;
            bool  allFillParent        = true;
            float maxHeight            = 0.0f;
            float alternativeMaxHeight = 0.0f;
            float weightedMaxHeight    = 0.0f;
            float totalWeight          = 0.0f;

            // Reset total length
            _totalLength = 0.0f;
            LayoutLength usedExcessSpace = new LayoutLength(0);

            HeightAndWidthState childState = new HeightAndWidthState(MeasuredSize.StateType.MeasuredSizeOK,
                                                                     MeasuredSize.StateType.MeasuredSizeOK);

            // Measure children, and determine if further resolution is required

            // 1st phase:
            // We cycle through all children and measure children with weight 0 (non weighted children) according to their specs
            // to accumulate total used space in totalLength based on measured sizes and margins.
            // Weighted children are not measured at this phase.
            // Available space for weighted children will be calculated in the phase 2 based on totalLength value.

            foreach (LayoutItem childLayout in _children)
            {
                LayoutLength childDesiredWidth  = new LayoutLength(childLayout.Owner.WidthSpecification);
                LayoutLength childDesiredHeight = new LayoutLength(childLayout.Owner.HeightSpecification);
                float        childWeight        = childLayout.Owner.Weight;
                Extents      childMargin        = childLayout.Margin;
                totalWeight += childWeight;

                bool useExcessSpace = (childDesiredWidth.AsRoundedValue() == 0) && (childWeight > 0);
                if (isExactly && useExcessSpace)
                {
                    _totalLength += childMargin.Start + childMargin.End;
                }
                else
                {
                    if (useExcessSpace)
                    {
                        // The widthMode is either UNSPECIFIED or AT_MOST, and
                        // this child is only laid out using excess space. Measure
                        // using WRAP_CONTENT so that we can find out the view's
                        // optimal width.
                        MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification(widthMeasureSpec, new LayoutLength(childLayout.Padding.Start + childLayout.Padding.End),
                                                                                                  new LayoutLength(LayoutParamPolicies.WrapContent));
                        MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification(heightMeasureSpec, new LayoutLength(childLayout.Padding.Top + childLayout.Padding.Bottom),
                                                                                                   childDesiredHeight);
                        childLayout.Measure(childWidthMeasureSpec, childHeightMeasureSpec);
                        usedExcessSpace += childLayout.MeasuredWidth.Size;
                    }
                    else
                    {
                        MeasureChild(childLayout, widthMeasureSpec, heightMeasureSpec);
                    }
                    LayoutLength childWidth = childLayout.MeasuredWidth.Size;

                    LayoutLength length = childWidth + childMargin.Start + childMargin.End;
                    if (isExactly)
                    {
                        _totalLength += length.AsDecimal();
                    }
                    else
                    {
                        _totalLength = Math.Max(_totalLength, _totalLength + length.AsDecimal() + CellPadding.Width);
                    }
                }

                bool matchHeightLocally = false;
                if (heightMode != MeasureSpecification.ModeType.Exactly && (int)childDesiredHeight.AsRoundedValue() == LayoutParamPolicies.MatchParent)
                {
                    // Will have to re-measure at least this child when we know exact height.
                    matchHeight        = true;
                    matchHeightLocally = true;
                }

                LayoutLength marginHeight = new LayoutLength(childMargin.Top + childMargin.Bottom);
                LayoutLength childHeight  = childLayout.MeasuredHeight.Size + marginHeight;

                if (childLayout.MeasuredWidthAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
                {
                    childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall;
                }
                if (childLayout.MeasuredHeightAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
                {
                    childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall;
                }

                maxHeight     = Math.Max(maxHeight, childHeight.AsDecimal());
                allFillParent = (allFillParent && childDesiredHeight.AsRoundedValue() == LayoutParamPolicies.MatchParent);

                if (childWeight > 0)
                {
                    /*
                     * Heights of weighted Views are bogus if we end up
                     * remeasuring, so keep them separate.
                     */
                    weightedMaxHeight = Math.Max(weightedMaxHeight, matchHeightLocally ? marginHeight.AsDecimal() : childHeight.AsDecimal());
                }
                else
                {
                    alternativeMaxHeight = Math.Max(alternativeMaxHeight, matchHeightLocally ? marginHeight.AsDecimal() : childHeight.AsDecimal());
                }
            } // foreach

            Extents padding = Padding;

            _totalLength += padding.Start + padding.End;
            LayoutLength widthSize = new LayoutLength(_totalLength);

            widthSize = new LayoutLength(Math.Max(widthSize.AsDecimal(), SuggestedMinimumWidth.AsDecimal()));
            MeasuredSize widthSizeAndState = ResolveSizeAndState(widthSize, widthMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK);

            widthSize = widthSizeAndState.Size;

            if (!allFillParent && heightMode != MeasureSpecification.ModeType.Exactly)
            {
                maxHeight = alternativeMaxHeight;
            }
            maxHeight += padding.Top + padding.Bottom;
            maxHeight  = Math.Max(maxHeight, SuggestedMinimumHeight.AsRoundedValue());

            widthSizeAndState.State = childState.widthState;

            SetMeasuredDimensions(widthSizeAndState,
                                  ResolveSizeAndState(new LayoutLength(maxHeight), heightMeasureSpec, childState.heightState));

            if (matchHeight)
            {
                ForceUniformHeight(_children.Count, widthMeasureSpec);
            }
        } // MeasureHorizontally