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));
        }
Ejemplo n.º 2
0
 // Helper to get the total measured width of all subviews, including all padding and margins
 private nfloat getTotalMeasuredWidth()
 {
     return((nfloat)(Padding.TotalWidth() + getTotalSpacing() + SubViews.Where(x => !x.Gone).Sum(x => x.GetMeasuredSize().Width + x.LayoutParameters.Margins.TotalWidth())));
 }
Ejemplo n.º 3
0
 // Helper to get the total measured height of all subviews, including all padding and margins
 private nfloat getTotalMeasuredHeight()
 {
     return(Padding.TotalHeight() + getTotalSpacing() + (nfloat)SubViews.Where(x => !x.Gone).Sum(x => x.GetMeasuredSize().Height + x.LayoutParameters.Margins.TotalHeight()));
 }
Ejemplo n.º 4
0
        protected override void onMeasure(float parentWidth, float parentHeight)
        {
            var unresolved = new List <View>();

            var width  = LayoutParameters.TryResolveWidth(this, parentWidth);
            var height = LayoutParameters.TryResolveHeight(this, parentHeight);

            // Remove padding
            if (width != float.MaxValue)
            {
                width -= Padding.TotalWidth();
            }
            if (height != float.MaxValue)
            {
                height -= Padding.TotalHeight();
            }

            // Measure all subviews where both dimensions can be resolved
            bool  haveResolvedSize = false;
            float maxWidth = 0, maxHeight = 0;

            foreach (var v in SubViews.Where(x => !x.Gone))
            {
                // Try to resolve subview width
                var subViewWidth = float.MaxValue;
                if (v.LayoutParameters.WidthUnits == Units.ParentRatio)
                {
                    if (width == float.MaxValue)
                    {
                        unresolved.Add(v);
                        continue;
                    }
                    else
                    {
                        subViewWidth = width - v.LayoutParameters.Margins.TotalWidth();
                    }
                }

                // Try to resolve subview height
                var subViewHeight = float.MaxValue;
                if (v.LayoutParameters.HeightUnits == Units.ParentRatio)
                {
                    if (height == float.MaxValue)
                    {
                        unresolved.Add(v);
                        continue;
                    }
                    else
                    {
                        subViewHeight = height - v.LayoutParameters.Margins.TotalHeight();
                    }
                }

                // Measure it
                v.Measure(subViewWidth, subViewHeight);

                if (!haveResolvedSize)
                {
                    maxWidth         = v.GetMeasuredSize().Width + v.LayoutParameters.Margins.TotalWidth();
                    maxHeight        = v.GetMeasuredSize().Height + v.LayoutParameters.Margins.TotalHeight();
                    haveResolvedSize = true;
                }
                else
                {
                    maxWidth  = Math.Max(maxWidth, v.GetMeasuredSize().Width + v.LayoutParameters.Margins.TotalWidth());
                    maxHeight = Math.Max(maxHeight, v.GetMeasuredSize().Height + v.LayoutParameters.Margins.TotalHeight());
                }
            }

            // Now resolve the unresolved subviews by either using the dimensions of the view
            // that were resolved, or none were, use their natural size
            foreach (var v in unresolved)
            {
                var subViewWidth = float.MaxValue;
                if (v.LayoutParameters.WidthUnits == Units.ParentRatio && haveResolvedSize)
                {
                    subViewWidth = maxWidth - v.LayoutParameters.Margins.TotalWidth();
                }

                var subViewHeight = float.MaxValue;
                if (v.LayoutParameters.HeightUnits == Units.ParentRatio && haveResolvedSize)
                {
                    subViewHeight = maxHeight - v.LayoutParameters.Margins.TotalHeight();
                }

                // Measure it
                v.Measure(subViewWidth, subViewHeight);
            }

            SizeF sizeMeasured = SizeF.Empty;

            if (width == float.MaxValue)
            {
                sizeMeasured.Width = SubViews.Max(x => x.GetMeasuredSize().Width + x.LayoutParameters.Margins.TotalWidth()) + Padding.TotalWidth();
            }

            if (height == float.MaxValue)
            {
                sizeMeasured.Height = SubViews.Max(x => x.GetMeasuredSize().Height + x.LayoutParameters.Margins.TotalHeight()) + Padding.TotalHeight();
            }

            // Done!
            SetMeasuredSize(LayoutParameters.ResolveSize(new SizeF(width, height), sizeMeasured));
        }
Ejemplo n.º 5
0
        // Do measurement when in horizontal orientation
        private void MeasureHorizontal(nfloat parentWidth, nfloat parentHeight)
        {
            // Work out our height
            nfloat layoutWidth  = LayoutParameters.TryResolveWidth(this, parentWidth, parentHeight);
            nfloat layoutHeight = LayoutParameters.TryResolveHeight(this, parentWidth, parentHeight);

            // Work out the total fixed size
            var paddings = Padding.TotalWidth();

            _goneViews     = new List <View>();
            _arrangedViews = new View[RowDefinitions.Count, ColumnDefinitions.Count];
            var columnWidthFillParentSubviews = new List <View>();

            //calculating columns
            var minWidth = (nfloat)ColumnDefinitions.Sum(x => x.MinWidth);

            foreach (var v in SubViews.Where(x => !x.Gone))
            {
                _arrangedViews[v.Row, v.Column] = v;
                var columnDefinition = ColumnDefinitions[v.Column];
                var rowDefinition    = RowDefinitions[v.Column];

                nfloat width;
                if (columnDefinition.Width > 0)
                {
                    width = columnDefinition.Width;
                }
                else if (columnDefinition.MaxWidth > 0)
                {
                    width = columnDefinition.MaxWidth;
                }
                else
                {
                    width = parentWidth - paddings;
                }

                nfloat height;
                if (rowDefinition.Height > 0)
                {
                    height = rowDefinition.Height;
                }
                else
                {
                    height = adjustLayoutHeight(layoutHeight, v);
                }

                if (v.LayoutParameters.WidthUnits != Units.ParentRatio)
                {
                    v.Measure(width - v.LayoutParameters.Margins.TotalWidth(), height);
                }
                else
                {
                    v._measuredSize      = new CGSize(0, 0);
                    v._measuredSizeValid = true;
                    columnWidthFillParentSubviews.Add(v);
                }
            }

            {
                nfloat totalWeight = 0;
                nfloat totalWidth  = 0;
                var    columnId    = -1;
                foreach (var column in ColumnDefinitions)
                {
                    columnId++;
                    column.CalculatedWidth = 0;

                    if (column.Width > 0)
                    {
                        column.CalculatedWidth = column.Width;
                    }
                    else if (column.Width == AutoSize.WrapContent)
                    {
                        for (int rowId = 0; rowId < RowDefinitions.Count; rowId++)
                        {
                            var v = _arrangedViews[rowId, columnId];

                            if (v != null)
                            {
                                column.CalculatedWidth = NMath.Max(column.CalculatedWidth, v.GetMeasuredSize().Width + v.LayoutParameters.Margins.TotalWidth());
                            }
                        }
                    }
                    else if (column.Width == AutoSize.FillParent)
                    {
                        totalWeight += column.Weight;
                    }
                    totalWidth += column.CalculatedWidth;
                }

                var room = layoutWidth - totalWidth;
                foreach (var column in ColumnDefinitions.Where(x => x.Width == AutoSize.FillParent))
                {
                    columnId++;

                    column.CalculatedWidth = room * column.Weight / totalWeight;
                }
            }

            {
                var totalWeight = 0;
                var totalHeight = 0;
                var rowId       = -1;
                foreach (var row in RowDefinitions)
                {
                    rowId++;

                    if (row.Height > 0)
                    {
                        row.CalculatedHeight = row.Height;
                        continue;
                    }


                    if (row.Height == AutoSize.WrapContent)
                    {
                        row.CalculatedHeight = 0;
                        for (int columnId = 0; columnId < ColumnDefinitions.Count; columnId++)
                        {
                            var v = _arrangedViews[rowId, columnId];

                            if (v != null)
                            {
                                row.CalculatedHeight = NMath.Max(row.CalculatedHeight, v.GetMeasuredSize().Height);
                            }
                        }
                    }
                }


                var room = layoutHeight - totalHeight;
                foreach (var row in RowDefinitions.Where(x => x.Height == AutoSize.FillParent))
                {
                    row.CalculatedHeight = room * row.Weight / totalWeight;
                }
            }

            CGSize sizeMeasured = CGSize.Empty;

            foreach (var item in ColumnDefinitions)
            {
                sizeMeasured.Width += item.CalculatedWidth;
            }
            sizeMeasured.Width += ColSpacing * (ColumnDefinitions.Count - 1);
            foreach (var item in RowDefinitions)
            {
                sizeMeasured.Height += item.CalculatedHeight;
            }
            sizeMeasured.Height += RowSpacing * (RowDefinitions.Count - 1);

            foreach (var v in columnWidthFillParentSubviews)
            {
                v.Measure(ColumnDefinitions[v.Column].CalculatedWidth, RowDefinitions[v.Row].CalculatedHeight);
            }

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