示例#1
0
        private MeasuredSize measureChild(global::System.IntPtr childPtr, float width, int measureModeWidth, float height, int measureModeHeight)
        {
            // We need to measure child layout
            View child = Registry.GetManagedBaseHandleFromNativePtr(childPtr) as View;

            LayoutItem childLayout = child.Layout;

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

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

            childLayout.Measure( childWidthMeasureSpec, childHeightMeasureSpec);

            return new MeasuredSize(childLayout.MeasuredWidth.Size.AsRoundedValue(),childLayout.MeasuredHeight.Size.AsRoundedValue());
        }
示例#2
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);
        }
示例#3
0
        private void MeasureWeightedChild(LayoutItem childLayout, float totalWeightLength, float totalWeight, float childWeight,
                                          MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec,
                                          HeightAndWidthState childState, Orientation orientation)
        {
            bool horizontal = false;

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

            float childsShare   = totalWeightLength * (childWeight / totalWeight);
            float desiredWidth  = childLayout.Owner.WidthSpecification;
            float desiredHeight = childLayout.Owner.HeightSpecification;

            MeasureSpecification childWidthMeasureSpec;
            MeasureSpecification childHeightMeasureSpec;

            if (horizontal)
            {
                childWidthMeasureSpec = new MeasureSpecification(new LayoutLength(childsShare - (childLayout.Margin.Start + childLayout.Margin.End)), MeasureSpecification.ModeType.Exactly);

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

                childHeightMeasureSpec = new MeasureSpecification(new LayoutLength(childsShare - (childLayout.Margin.Top + childLayout.Margin.Bottom)), 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;
            }
        }
示例#4
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);
        }
示例#5
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);
        }
示例#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 />
        /// 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>
        /// <since_tizen> 6 </since_tizen>
        protected virtual void MeasureChild(LayoutItem child, MeasureSpecification parentWidthMeasureSpec, MeasureSpecification parentHeightMeasureSpec)
        {
            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);
        }
示例#7
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);
        }
示例#8
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);
        }
示例#9
0
        protected void MeasureChildWithoutPadding(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(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);
        }
示例#10
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;
            }
        }
示例#11
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
示例#12
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.
            for (int i = 0; i < LayoutChildren.Count; i++)
            {
                LayoutItem childLayout = LayoutChildren[i];
                if (childLayout.Owner.ExcludeLayouting)
                {
                    MeasureChildWithoutPadding(childLayout, widthMeasureSpec, heightMeasureSpec);
                    continue;
                }

                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 = Math.Max(_totalLength, (_totalLength + childMargin.Start + childMargin.End));
                }
                else
                {
                    if (useExcessSpace)
                    {
                        // Parent is not defiend!!!
                        // 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(
                            new MeasureSpecification(
                                new LayoutLength(widthMeasureSpec.Size - (childLayout.Margin.Start + childLayout.Margin.End)),
                                widthMeasureSpec.Mode),
                            new LayoutLength(Padding.Start + Padding.End),
                            new LayoutLength(LayoutParamPolicies.WrapContent));

                        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(childDesiredHeight));

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

                    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() + (i < LayoutChildren.Count - 1 ? CellPadding.Width : 0));
                    }
                }

                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

            float widthSize = _totalLength;

            widthSize = Math.Max(widthSize, SuggestedMinimumWidth.AsDecimal());
            MeasuredSize widthSizeAndState = ResolveSizeAndState(new LayoutLength(widthSize + Padding.Start + Padding.End), 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 - (Padding.Start + Padding.End);

            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];
                    if (childLayout.Owner.ExcludeLayouting)
                    {
                        continue;
                    }

                    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);
                } // for loop
            }
            else
            {
                // No excess space or no weighted children
                alternativeMaxHeight = Math.Max(alternativeMaxHeight, weightedMaxHeight);
            }

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



            // Padding should be concerned when specification is Wrapcontent.
            maxHeight += (Owner.HeightSpecification == LayoutParamPolicies.WrapContent) ? (Padding.Top + Padding.Bottom) : 0;
            maxHeight  = Math.Max(maxHeight, SuggestedMinimumHeight.AsRoundedValue());

            widthSizeAndState.State = childState.widthState;

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

            if (matchHeight)
            {
                ForceUniformHeight(widthMeasureSpec);
            }
        } // MeasureHorizontal