private void ApplyGravityToLine(LineDefinition line)
        {
            int viewCount = line.Views.Count;

            if (viewCount <= 0)
            {
                return;
            }

            float totalWeight = 0;

            foreach (View prev in line.Views)
            {
                CustomLayoutParams plp = (CustomLayoutParams)prev.LayoutParameters;
                totalWeight += this.GetWeight(plp);
            }

            View lastChild = line.Views[viewCount - 1];
            CustomLayoutParams lastChildLayoutParams = (CustomLayoutParams)lastChild.LayoutParameters;
            int excessLength = line.LineLength - (lastChildLayoutParams.Length + lastChildLayoutParams.InlineStartLength);
            int excessOffset = 0;

            foreach (View child in line.Views)
            {
                CustomLayoutParams layoutParams = (CustomLayoutParams)child.LayoutParameters;

                float        weight      = this.GetWeight(layoutParams);
                GravityFlags gravity     = this.GetGravity(layoutParams);
                int          extraLength = (int)Math.Round((double)(excessLength * weight / totalWeight));

                int childLength    = layoutParams.Length + layoutParams.SpacingLength;
                int childThickness = layoutParams.Thickness + layoutParams.SpacingThickness;

                Rect container = new Rect();
                container.Top    = 0;
                container.Left   = excessOffset;
                container.Right  = childLength + extraLength + excessOffset;
                container.Bottom = line.LineThickness;

                Rect result = new Rect();
                Android.Views.Gravity.Apply(gravity, childLength, childThickness, container, result);

                excessOffset += extraLength;
                layoutParams.InlineStartLength    = result.Left + layoutParams.InlineStartLength;
                layoutParams.InlineStartThickness = result.Top;
                layoutParams.Length    = result.Width() - layoutParams.SpacingLength;
                layoutParams.Thickness = result.Height() - layoutParams.SpacingThickness;
            }
        }
 private void ApplyPositionsToViews(LineDefinition line)
 {
     foreach (View child in line.Views)
     {
         CustomLayoutParams layoutParams = (CustomLayoutParams)child.LayoutParameters;
         if (this.config.Orientation == HORIZONTAL)
         {
             layoutParams.SetPosition(this.PaddingLeft + line.LineStartLength + layoutParams.InlineStartLength, this.PaddingTop + line.LineStartThickness + layoutParams.InlineStartThickness);
             child.Measure(MeasureSpec.MakeMeasureSpec(layoutParams.Length, MeasureSpecMode.Exactly), MeasureSpec.MakeMeasureSpec(layoutParams.Thickness, MeasureSpecMode.Exactly));
         }
         else
         {
             layoutParams.SetPosition(this.PaddingLeft + line.LineStartThickness + layoutParams.InlineStartThickness, this.PaddingTop + line.LineStartLength + layoutParams.InlineStartLength);
             child.Measure(MeasureSpec.MakeMeasureSpec(layoutParams.Thickness, MeasureSpecMode.Exactly), MeasureSpec.MakeMeasureSpec(layoutParams.Length, MeasureSpecMode.Exactly));
         }
     }
 }
        private void ApplyGravityToLines(IList <LineDefinition> lines, int realControlLength, int realControlThickness)
        {
            int linesCount = lines.Count;

            if (linesCount <= 0)
            {
                return;
            }

            int            totalWeight     = linesCount;
            LineDefinition lastLine        = lines[linesCount - 1];
            int            excessThickness = realControlThickness - (lastLine.LineThickness + lastLine.LineStartThickness);
            int            excessOffset    = 0;

            foreach (LineDefinition child in lines)
            {
                int          weight         = 1;
                GravityFlags gravity        = this.Gravity;
                int          extraThickness = (int)Math.Round((double)(excessThickness * weight / totalWeight));

                int childLength    = child.LineLength;
                int childThickness = child.LineThickness;

                Rect container = new Rect();
                container.Top    = excessOffset;
                container.Left   = 0;
                container.Right  = realControlLength;
                container.Bottom = childThickness + extraThickness + excessOffset;

                Rect result = new Rect();
                Android.Views.Gravity.Apply(gravity, childLength, childThickness, container, result);

                excessOffset += extraThickness;
                child.AddLineStartLength(result.Left);
                child.AddLineStartThickness(result.Top);
                child.Length    = result.Width();
                child.Thickness = result.Height();
            }
        }
        protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
        {
            int sizeWidth  = MeasureSpec.GetSize(widthMeasureSpec) - this.PaddingRight - this.PaddingLeft;
            int sizeHeight = MeasureSpec.GetSize(heightMeasureSpec) - this.PaddingTop - this.PaddingBottom;

            MeasureSpecMode modeWidth  = MeasureSpec.GetMode(widthMeasureSpec);
            MeasureSpecMode modeHeight = MeasureSpec.GetMode(heightMeasureSpec);

            int controlMaxLength    = this.config.Orientation == HORIZONTAL ? sizeWidth : sizeHeight;
            int controlMaxThickness = this.config.Orientation == HORIZONTAL ? sizeHeight : sizeWidth;

            MeasureSpecMode modeLength    = this.config.Orientation == HORIZONTAL ? modeWidth : modeHeight;
            MeasureSpecMode modeThickness = this.config.Orientation == HORIZONTAL ? modeHeight : modeWidth;

            lines.Clear();
            LineDefinition currentLine = new LineDefinition(controlMaxLength, config);

            lines.Add(currentLine);

            int count = this.ChildCount;

            for (int i = 0; i < count; i++)
            {
                View child = this.GetChildAt(i);
                if (child.Visibility == ViewStates.Gone)
                {
                    continue;
                }

                CustomLayoutParams lp = (CustomLayoutParams)child.LayoutParameters;

                child.Measure(GetChildMeasureSpec(widthMeasureSpec, this.PaddingLeft + this.PaddingRight, lp.Width), GetChildMeasureSpec(heightMeasureSpec, this.PaddingTop + this.PaddingBottom, lp.Height));

                lp.ClearCalculatedFields(this.config.Orientation);
                if (this.config.Orientation == FlowLayout.HORIZONTAL)
                {
                    lp.Length    = child.MeasuredWidth;
                    lp.Thickness = child.MeasuredHeight;
                }
                else
                {
                    lp.Length    = child.MeasuredHeight;
                    lp.Thickness = child.MeasuredWidth;
                }

                bool newLine = lp.newLine || (modeLength != MeasureSpecMode.Unspecified && !currentLine.CanFit(child));
                if (newLine)
                {
                    currentLine = new LineDefinition(controlMaxLength, config);
                    if (this.config.Orientation == VERTICAL && this.config.Direction == LAYOUT_DIRECTION_RTL)
                    {
                        lines.Insert(0, currentLine);
                    }
                    else
                    {
                        lines.Add(currentLine);
                    }
                }

                if (this.config.Orientation == HORIZONTAL && this.config.Direction == LAYOUT_DIRECTION_RTL)
                {
                    currentLine.AddView(0, child);
                }
                else
                {
                    currentLine.AddView(child);
                }
            }

            this.CalculateLinesAndChildPosition(lines);

            int contentLength = 0;

            foreach (LineDefinition l in lines)
            {
                contentLength = Math.Max(contentLength, l.LineLength);
            }
            int contentThickness = currentLine.LineStartThickness + currentLine.LineThickness;

            int realControlLength    = this.FindSize(modeLength, controlMaxLength, contentLength);
            int realControlThickness = this.FindSize(modeHeight, controlMaxThickness, contentThickness);

            this.ApplyGravityToLines(lines, realControlLength, realControlThickness);

            foreach (LineDefinition line in lines)
            {
                this.ApplyGravityToLine(line);
                this.ApplyPositionsToViews(line);
            }

            /* need to take padding into account */
            int totalControlWidth  = this.PaddingLeft + this.PaddingRight;
            int totalControlHeight = this.PaddingBottom + this.PaddingTop;

            if (this.config.Orientation == HORIZONTAL)
            {
                totalControlWidth  += contentLength;
                totalControlHeight += contentThickness;
            }
            else
            {
                totalControlWidth  += contentThickness;
                totalControlHeight += contentLength;
            }
            this.SetMeasuredDimension(ResolveSize(totalControlWidth, widthMeasureSpec), ResolveSize(totalControlHeight, heightMeasureSpec));
        }