Ejemplo n.º 1
0
        // Do measurement when in vertical orientation
        private void MeasureVertical(nfloat parentWidth, nfloat parentHeight)
        {
            // Work out our width
            var width  = LayoutParameters.TryResolveWidth(this, parentWidth, parentHeight);
            var height = LayoutParameters.TryResolveHeight(this, parentWidth, parentHeight);

            // Allow room for padding
            if (width != nfloat.MaxValue)
            {
                width -= Padding.TotalWidth();
            }

            // Work out the total fixed size
            nfloat totalFixedSize   = 0;
            double totalWeight      = 0;
            int    visibleViewCount = 0;

            foreach (var v in SubViews.Where(x => !x.Gone))
            {
                if (v.LayoutParameters.HeightUnits == Units.ParentRatio)
                {
                    // We'll deal with this later

                    // For now, lets just total up the specified weights
                    totalWeight += v.LayoutParameters.Weight;
                }
                else
                {
                    // Lay it out
                    v.Measure(adjustLayoutWidth(width, v), nfloat.MaxValue);
                    totalFixedSize += v.GetMeasuredSize().Height;
                }

                // Include margins
                totalFixedSize += v.LayoutParameters.Margins.TotalHeight();
                visibleViewCount++;
            }


            // Also need to include our own padding
            totalFixedSize += Padding.TotalHeight();

            // And spacing between controls
            if (visibleViewCount > 1)
            {
                totalFixedSize += (visibleViewCount - 1) * Spacing;
            }

            nfloat totalVariableSize = 0;

            if (LayoutParameters.HeightUnits == Units.ContentRatio || height == nfloat.MaxValue)
            {
                // This is a weird case: we have a height of wrap content, but child items that want to fill parent too.
                // Temporarily switch those items to wrap content and use their natural size
                foreach (var v in SubViews.Where(x => !x.Gone && x.LayoutParameters.HeightUnits == Units.ParentRatio))
                {
                    v.Measure(adjustLayoutWidth(width, v), nfloat.MaxValue);
                    totalVariableSize += v.GetMeasuredSize().Height;
                }
            }
            else
            {
                // If we've had an explicit weight passed to us, ignore the calculated total weight and use it instead
                if (_totalWeight != 0)
                {
                    totalWeight = _totalWeight;
                }

                // Work out how much room we've got to share around
                nfloat room = height - totalFixedSize;

                // Layout the fill parent items
                foreach (var v in SubViews.Where(x => !x.Gone && x.LayoutParameters.HeightUnits == Units.ParentRatio))
                {
                    // Work out size
                    if (room < 0)
                    {
                        room = 0;
                    }
                    nfloat size = (nfloat)(totalWeight == 0 ? room : room * v.LayoutParameters.Weight / totalWeight);

                    // Measure it
                    v.Measure(adjustLayoutWidth(width, v), size);

                    // Update total size
                    totalVariableSize += v.GetMeasuredSize().Height;

                    // Adjust the weighting calculation in case the view didn't accept our measurement
                    room        -= v.GetMeasuredSize().Height;
                    totalWeight -= v.LayoutParameters.Weight;
                }
            }

            CGSize sizeMeasured = CGSize.Empty;

            if (width == nfloat.MaxValue)
            {
                // Work out the maximum width of all children that aren't fill parent
                sizeMeasured.Width = 0;
                foreach (var v in SubViews.Where(x => !x.Gone && x.LayoutParameters.WidthUnits != Units.ParentRatio))
                {
                    nfloat totalChildWidth = v.GetMeasuredSize().Width + v.LayoutParameters.Margins.TotalWidth();
                    if (totalChildWidth > sizeMeasured.Width)
                    {
                        sizeMeasured.Width = totalChildWidth;
                    }
                }

                // Set the width of all children that are fill parent
                foreach (var v in SubViews.Where(x => !x.Gone && x.LayoutParameters.WidthUnits == Units.ParentRatio))
                {
                    v.Measure(sizeMeasured.Width, v.GetMeasuredSize().Height);
                }

                sizeMeasured.Width += Padding.TotalWidth();
            }
            else
            {
                width += Padding.TotalWidth();
            }

            if (height == nfloat.MaxValue)
            {
                height = totalFixedSize + totalVariableSize;
            }

            if (LayoutParameters.ParentIsScorllView(this))
            {
                height = totalFixedSize + totalVariableSize;
                if (LayoutParameters.HeightUnits == Units.ParentRatio)
                {
                    height = height < parentHeight ? parentHeight : height;
                }
            }

            // And finally, set our measure dimensions
            SetMeasuredSize(LayoutParameters.ResolveSize(new CGSize(width, height), sizeMeasured));
        }