Exemple #1
0
        public override int FillToEnd(int leadingEdge, int markerLine, int anchorPosition, SectionData sd, LayoutState state)
        {
            int itemCount = state.recyclerState.ItemCount;

            for (int i = anchorPosition; i < itemCount; i++)
            {
                if (markerLine >= leadingEdge)
                {
                    break;
                }

                LayoutState.View           next = state.GetView(i);
                LayoutManager.LayoutParams lp   = next.LayoutParams;
                if (lp.FirstPosition != sd.firstPosition)
                {
                    state.CacheView(i, next.view);
                    break;
                }

                measureChild(next, sd);
                markerLine = layoutChild(next, markerLine, LayoutManager.Direction.END, sd, state);
                AddView(next, i, LayoutManager.Direction.END, state);
            }

            return(markerLine);
        }
Exemple #2
0
        private int layoutChild(LayoutState.View child, int markerLine, LayoutManager.Direction direction, SectionData sd, LayoutState state)
        {
            int height = mLayoutManager.GetDecoratedMeasuredHeight(child.view);
            int width  = mLayoutManager.GetDecoratedMeasuredWidth(child.view);

            int left  = state.isLTR ? sd.contentStart : sd.contentEnd;
            int right = left + width;
            int top;
            int bottom;

            if (direction == LayoutManager.Direction.END)
            {
                top    = markerLine;
                bottom = top + height;
            }
            else
            {
                bottom = markerLine;
                top    = bottom - height;
            }
            mLayoutManager.LayoutDecorated(child.view, left, top, right, bottom);

            if (direction == LayoutManager.Direction.END)
            {
                markerLine = mLayoutManager.GetDecoratedBottom(child.view);
            }
            else
            {
                markerLine = mLayoutManager.GetDecoratedTop(child.view);
            }

            return(markerLine);
        }
Exemple #3
0
        public override int ComputeHeaderOffset(int firstVisiblePosition, SectionData sd, LayoutState state)
        {
            /*
             * Work from an assumed overlap and add heights from the start until the overlap is zero or
             * less, or the current position (or max items) is reached.
             */

            int areaAbove = 0;

            for (int position = sd.firstPosition + 1; areaAbove < sd.headerHeight && position < firstVisiblePosition; position++)
            {
                // Look to see if the header overlaps with the displayed area of the mSection.
                LayoutState.View child = state.GetView(position);
                measureChild(child, sd);

                areaAbove += mLayoutManager.GetDecoratedMeasuredHeight(child.view);
                state.CacheView(position, child.view);
            }

            if (areaAbove == sd.headerHeight)
            {
                return(0);
            }
            else if (areaAbove > sd.headerHeight)
            {
                return(1);
            }
            else
            {
                return(-areaAbove);
            }
        }
Exemple #4
0
        /// <summary>
        /// Fill a row.
        /// </summary>
        /// <param name="markerLine">      Line indicating the top edge of the row. </param>
        /// <param name="anchorPosition">  Position of the first view in the row. </param>
        /// <param name="direction">       Direction of edge to fill towards. </param>
        /// <param name="measureRowItems"> Measure the row items. </param>
        /// <param name="sd">              Section data. </param>
        /// <param name="state">           Layout state. </param>
        /// <returns> The height of the new row. </returns>
        public int fillRow(int markerLine, int anchorPosition, LayoutManager.Direction direction, bool measureRowItems, SectionData sd, LayoutState state)
        {
            int rowHeight = 0;

            LayoutState.View[] views = new LayoutState.View[mNumColumns];
            for (int i = 0; i < mNumColumns; i++)
            {
                int position = anchorPosition + i;
                if (position >= state.recyclerState.ItemCount)
                {
                    break;
                }

                LayoutState.View view = state.GetView(position);
                if (view.LayoutParams.FirstPosition != sd.firstPosition)
                {
                    state.CacheView(position, view.view);
                    break;
                }

                if (measureRowItems)
                {
                    MeasureChild(view, sd);
                }
                else
                {
                    state.DecacheView(i + anchorPosition);
                }
                rowHeight = Math.Max(rowHeight, mLayoutManager.GetDecoratedMeasuredHeight(view.view));
                views[i]  = view;
            }

            bool directionIsStart = direction == LayoutManager.Direction.START;

            if (directionIsStart)
            {
                markerLine -= rowHeight;
            }

            for (int i = 0; i < mNumColumns; i++)
            {
                int col = directionIsStart ? mNumColumns - i - 1 : i;
                if (views[col] == null)
                {
                    continue;
                }
                LayoutChild(views[col], markerLine, col, rowHeight, sd, state);
                AddView(views[col], col + anchorPosition, direction, state);
            }

            return(rowHeight);
        }
Exemple #5
0
        protected int AddView(LayoutState.View child, int position, LayoutManager.Direction direction, LayoutState state)
        {
            int addIndex;

            if (direction == LayoutManager.Direction.START)
            {
                addIndex = 0;
            }
            else
            {
                addIndex = mLayoutManager.ChildCount;
            }

            state.DecacheView(position);
            mLayoutManager.AddView(child.view, addIndex);

            return(addIndex);
        }
Exemple #6
0
        /// <summary>
        /// Layout out a view for the given column in a row. Views that have a height param of
        /// MATCH_PARENT are fixed to the height of the row.
        /// </summary>
        /// <param name="child">     View to lay out. </param>
        /// <param name="top">       Line indicating the top edge of the row. </param>
        /// <param name="col">       Column view is being placed into. </param>
        /// <param name="rowHeight"> Height of the row. </param>
        /// <param name="sd">        Section data. </param>
        /// <param name="state">     Layout state. </param>
        private void LayoutChild(LayoutState.View child, int top, int col, int rowHeight, SectionData sd, LayoutState state)
        {
            int height;

            if (child.LayoutParams.Height == LayoutManager.LayoutParams.MatchParent)
            {
                height = rowHeight;
            }
            else
            {
                height = mLayoutManager.GetDecoratedMeasuredHeight(child.view);
            }
            int width = mLayoutManager.GetDecoratedMeasuredWidth(child.view);

            col = AdjustColumnForLayoutDirection(col, state.isLTR);

            int bottom = top + height;
            int left   = (state.isLTR ? sd.contentStart : sd.contentEnd) + col * mColumnWidth;
            int right  = left + width;

            mLayoutManager.LayoutDecorated(child.view, left, top, right, bottom);
        }
Exemple #7
0
        public override int FillToStart(int leadingEdge, int markerLine, int anchorPosition, SectionData sd, LayoutState state)
        {
            // Check to see if we have to adjust for minimum section height. We don't if there is an
            // attached non-header view in this section.
            bool applyMinHeight = false;

            for (int i = 0; i < state.recyclerState.ItemCount; i++)
            {
                View check = mLayoutManager.GetChildAt(0);
                if (check == null)
                {
                    applyMinHeight = false;
                    break;
                }

                LayoutManager.LayoutParams checkParams = (LayoutManager.LayoutParams)check.LayoutParameters;
                if (checkParams.FirstPosition != sd.firstPosition)
                {
                    applyMinHeight = true;
                    break;
                }

                if (!checkParams.isHeader)
                {
                    applyMinHeight = false;
                    break;
                }
            }

            // Work out offset to marker line by measuring items from the end. If section height is less
            // than min height, then adjust marker line and then lay out items.
            int measuredPositionsMarker = -1;
            int sectionHeight           = 0;
            int minHeightOffset         = 0;

            if (applyMinHeight)
            {
                for (int i = anchorPosition; i >= 0; i--)
                {
                    LayoutState.View measure = state.GetView(i);
                    state.CacheView(i, measure.view);
                    LayoutManager.LayoutParams lp = measure.LayoutParams;
                    if (lp.FirstPosition != sd.firstPosition)
                    {
                        break;
                    }

                    if (lp.isHeader)
                    {
                        continue;
                    }

                    measureChild(measure, sd);
                    sectionHeight          += mLayoutManager.GetDecoratedMeasuredHeight(measure.view);
                    measuredPositionsMarker = i;
                    if (sectionHeight >= sd.minimumHeight)
                    {
                        break;
                    }
                }

                if (sectionHeight < sd.minimumHeight)
                {
                    minHeightOffset = sectionHeight - sd.minimumHeight;
                    markerLine     += minHeightOffset;
                }
            }

            for (int i = anchorPosition; i >= 0; i--)
            {
                if (markerLine - minHeightOffset < leadingEdge)
                {
                    break;
                }

                LayoutState.View           next = state.GetView(i);
                LayoutManager.LayoutParams lp   = next.LayoutParams;
                if (lp.isHeader)
                {
                    state.CacheView(i, next.view);
                    break;
                }
                if (lp.FirstPosition != sd.firstPosition)
                {
                    state.CacheView(i, next.view);
                    break;
                }

                if (!applyMinHeight || i < measuredPositionsMarker)
                {
                    measureChild(next, sd);
                }
                else
                {
                    state.DecacheView(i);
                }
                markerLine = layoutChild(next, markerLine, LayoutManager.Direction.START, sd, state);
                AddView(next, i, LayoutManager.Direction.START, state);
            }

            return(markerLine);
        }
Exemple #8
0
 private void measureChild(LayoutState.View child, SectionData sd)
 {
     mLayoutManager.MeasureChildWithMargins(child.view, sd.TotalMarginWidth, 0);
 }
Exemple #9
0
        public override int FillToEnd(int leadingEdge, int markerLine, int anchorPosition, SectionData sd, LayoutState state)
        {
            if (markerLine >= leadingEdge)
            {
                return(markerLine);
            }

            int itemCount = state.recyclerState.ItemCount;

            if (anchorPosition >= itemCount)
            {
                return(markerLine);
            }

            LayoutState.View anchor = state.GetView(anchorPosition);
            state.CacheView(anchorPosition, anchor.view);
            if (anchor.LayoutParams.FirstPosition != sd.firstPosition)
            {
                return(markerLine);
            }

            int firstContentPosition = sd.hasHeader ? sd.firstPosition + 1 : sd.firstPosition;

            // Ensure the anchor is the first item in the row.
            int col = (anchorPosition - firstContentPosition) % mNumColumns;

            for (int i = 1; i <= col; i++)
            {
                // Detach and scrap attached items in this row, so we can re-lay them again. The last
                // child view in the index can be the header so we just skip past it if it last.
                for (int j = 1; j <= mLayoutManager.ChildCount; j++)
                {
                    View child = mLayoutManager.GetChildAt(mLayoutManager.ChildCount - j);
                    if (mLayoutManager.GetPosition(child) == anchorPosition - i)
                    {
                        markerLine = mLayoutManager.GetDecoratedTop(child);
                        mLayoutManager.DetachAndScrapViewAt(j, state.recycler);
                        break;
                    }

                    LayoutManager.LayoutParams lp = (LayoutManager.LayoutParams)child.LayoutParameters;
                    if (lp.FirstPosition != sd.firstPosition)
                    {
                        break;
                    }
                }
            }
            anchorPosition = anchorPosition - col;

            // Lay out rows to end.
            for (int i = anchorPosition; i < itemCount; i += mNumColumns)
            {
                if (markerLine >= leadingEdge)
                {
                    break;
                }

                LayoutState.View view = state.GetView(i);
                if (view.LayoutParams.FirstPosition != sd.firstPosition)
                {
                    state.CacheView(i, view.view);
                    break;
                }

                int rowHeight = fillRow(markerLine, i, LayoutManager.Direction.END, true, sd, state);
                markerLine += rowHeight;
            }

            return(markerLine);
        }
Exemple #10
0
        /// <summary>
        /// Measure view. A view is given an area as wide as a single column with an undefined height.
        /// </summary>
        /// <param name="child"> View to measure. </param>
        /// <param name="sd">    Section data. </param>
        private void MeasureChild(LayoutState.View child, SectionData sd)
        {
            int widthOtherColumns = (mNumColumns - 1) * mColumnWidth;

            mLayoutManager.MeasureChildWithMargins(child.view, sd.marginStart + sd.marginEnd + widthOtherColumns, 0);
        }
Exemple #11
0
        public override int FillToStart(int leadingEdge, int markerLine, int anchorPosition, SectionData sd, LayoutState state)
        {
            int firstContentPosition = sd.hasHeader ? sd.firstPosition + 1 : sd.firstPosition;

            // Check to see if we have to adjust for minimum section height. We don't if there is an
            // attached non-header view in this section.
            bool applyMinHeight = false;

            for (int i = 0; i < mLayoutManager.ChildCount; i++)
            {
                View check = mLayoutManager.GetChildAt(0);
                LayoutManager.LayoutParams checkParams = (LayoutManager.LayoutParams)check.LayoutParameters;
                if (checkParams.FirstPosition != sd.firstPosition)
                {
                    applyMinHeight = true;
                    break;
                }

                if (!checkParams.isHeader)
                {
                    applyMinHeight = false;
                    break;
                }
            }

            // _ _ ^ a b
            int col = (anchorPosition - firstContentPosition) % mNumColumns;

            for (int i = 1; i < mNumColumns - col; i++)
            {
                // Detach and scrap attached items in this row, so we can re-lay them again. The last
                // child view in the index can be the header so we just skip past it if it last.
                for (int j = 0; j < mLayoutManager.ChildCount; j++)
                {
                    View child = mLayoutManager.GetChildAt(j);
                    LayoutManager.LayoutParams lp = (LayoutManager.LayoutParams)child.LayoutParameters;
                    if (lp.FirstPosition != sd.firstPosition)
                    {
                        break;
                    }

                    if (mLayoutManager.GetPosition(child) == anchorPosition + i)
                    {
                        mLayoutManager.DetachAndScrapViewAt(j, state.recycler);
                        break;
                    }
                }
            }
            // Ensure the anchor is the first item in the row.
            int columnAnchorPosition = anchorPosition - col;

            // Work out offset to marker line by measuring rows from the end. If section height is less
            // than min height, then adjust marker line and then lay out items.
            int measuredPositionsMarker = -1;
            int sectionHeight           = 0;
            int minHeightOffset         = 0;

            if (applyMinHeight)
            {
                for (int i = columnAnchorPosition; i >= 0; i -= mNumColumns)
                {
                    LayoutState.View check = state.GetView(i);
                    state.CacheView(i, check.view);
                    LayoutManager.LayoutParams checkParams = check.LayoutParams;
                    if (checkParams.FirstPosition != sd.firstPosition)
                    {
                        break;
                    }

                    int rowHeight = 0;
                    for (int j = 0; j < mNumColumns && i + j <= anchorPosition; j++)
                    {
                        LayoutState.View measure = state.GetView(i + j);
                        state.CacheView(i + j, measure.view);
                        LayoutManager.LayoutParams measureParams = measure.LayoutParams;
                        if (measureParams.FirstPosition != sd.firstPosition)
                        {
                            break;
                        }

                        if (measureParams.isHeader)
                        {
                            continue;
                        }

                        MeasureChild(measure, sd);
                        rowHeight = Math.Max(rowHeight, mLayoutManager.GetDecoratedMeasuredHeight(measure.view));
                    }

                    sectionHeight          += rowHeight;
                    measuredPositionsMarker = i;
                    if (sectionHeight >= sd.minimumHeight)
                    {
                        break;
                    }
                }

                if (sectionHeight < sd.minimumHeight)
                {
                    minHeightOffset = sectionHeight - sd.minimumHeight;
                    markerLine     += minHeightOffset;
                }
            }

            // Lay out rows to end.
            for (int i = columnAnchorPosition; i >= 0; i -= mNumColumns)
            {
                if (markerLine - minHeightOffset < leadingEdge)
                {
                    break;
                }

                LayoutState.View rowAnchor = state.GetView(i);
                state.CacheView(i, rowAnchor.view);
                LayoutManager.LayoutParams lp = rowAnchor.LayoutParams;
                if (lp.isHeader || lp.FirstPosition != sd.firstPosition)
                {
                    break;
                }

                bool measureRowItems = !applyMinHeight || i < measuredPositionsMarker;
                int  rowHeight       = fillRow(markerLine, i, LayoutManager.Direction.START, measureRowItems, sd, state);
                markerLine -= rowHeight;
            }

            return(markerLine);
        }