Ejemplo n.º 1
0
        private void CalculateColumnWidthValues(SectionData sd)
        {
            int availableWidth = mLayoutManager.Width - sd.contentStart - sd.contentEnd;

            if (!mColumnsSpecified)
            {
                if (mMinimumWidth <= 0)
                {
                    mMinimumWidth = (int)TypedValue.ApplyDimension(ComplexUnitType.Dip, 48, mContext.Resources.DisplayMetrics);
                }
                mNumColumns = availableWidth / Math.Abs(mMinimumWidth);
            }
            if (mNumColumns < 1)
            {
                mNumColumns = 1;
            }
            mColumnWidth = availableWidth / mNumColumns;
            if (mColumnWidth == 0)
            {
                Console.WriteLine("GridSection", "Too many columns (" + mNumColumns + ") for available width" + availableWidth + ".");
            }
        }
Ejemplo n.º 2
0
        public void GetEdgeStates(Rect outRect, View child, SectionData sd, RecyclerView.State state)
        {
            LayoutManager.LayoutParams lp = (LayoutManager.LayoutParams)child.LayoutParameters;
            int position = lp.ViewPosition;

            int  column    = (position - sd.FirstContentPosition) % mNumColumns;
            bool isLtr     = mLayoutManager.LayoutDirection == ViewCompat.LayoutDirectionLtr;
            int  ltrColumn = AdjustColumnForLayoutDirection(column, isLtr);

            outRect.Left  = ltrColumn == 0 ? ItemDecorator.EXTERNAL : ItemDecorator.INTERNAL;
            outRect.Right = ltrColumn == mNumColumns - 1 ? ItemDecorator.EXTERNAL : ItemDecorator.INTERNAL;

            outRect.Top = position - column == sd.FirstContentPosition ? ItemDecorator.EXTERNAL : ItemDecorator.INTERNAL;
            // Reset position to left column and add num columns, if < itemcount then not last row.
            if (sd.LastContentItemFound)
            {
                outRect.Bottom = position + (mNumColumns - column) > sd.lastContentPosition ? ItemDecorator.EXTERNAL : ItemDecorator.INTERNAL;
            }
            else
            {
                outRect.Bottom = ItemDecorator.INTERNAL;
            }
        }
Ejemplo n.º 3
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);
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
0
 private void measureChild(LayoutState.View child, SectionData sd)
 {
     mLayoutManager.MeasureChildWithMargins(child.view, sd.TotalMarginWidth, 0);
 }
Ejemplo n.º 6
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);
        }
Ejemplo n.º 7
0
 public SectionLayoutManager Initialize(SectionData sd)
 {
     return(this);
 }
Ejemplo n.º 8
0
            public bool IsAssigned(SectionData sd, LayoutManager.LayoutParams lp)
            {
                int kind = lp.isHeader ? HEADER : CONTENT;

                return(sd.sectionManagerKind == LayoutManager.SECTION_MANAGER_CUSTOM && (kind & mTargetKind) != 0 && TextUtils.Equals(sd.sectionManager, mSlmKey));
            }
Ejemplo n.º 9
0
 /// <summary>
 /// Compute the offset for side aligned headers. If the height of the non-visible area of the
 /// section is taller than the header, then the header should be offscreen, in that case return
 /// any +ve number.
 /// </summary>
 /// <param name="firstVisiblePosition"> Position of first visible item in section. </param>
 /// <param name="sd">                   Section data. </param>
 /// <param name="state">                Layout state. </param>
 /// <returns> -ve number giving the distance the header should be offset before the anchor view. A
 /// +ve number indicates the header is offscreen. </returns>
 public abstract int ComputeHeaderOffset(int firstVisiblePosition, SectionData sd, LayoutState state);
Ejemplo n.º 10
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);
        }
Ejemplo n.º 11
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);
        }
Ejemplo n.º 12
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);
        }
Ejemplo n.º 13
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);
        }
Ejemplo n.º 14
0
 public bool IsAssigned(SectionData sd, LayoutManager.LayoutParams lp)
 {
     return(lp.ViewPosition == mPosition);
 }
Ejemplo n.º 15
0
 public abstract int FinishFillToStart(int leadingEdge, View anchor, SectionData sd, LayoutState state);
Ejemplo n.º 16
0
            public bool IsAssigned(SectionData sd, LayoutManager.LayoutParams lp)
            {
                int kind = lp.isHeader ? HEADER : CONTENT;

                return(sd.sectionManagerKind == mSlmId && (kind & mTargetKind) != 0);
            }
Ejemplo n.º 17
0
 public abstract int FillToStart(int leadingEdge, int markerLine, int anchorPosition, SectionData sd, LayoutState state);
Ejemplo n.º 18
0
            public bool IsAssigned(SectionData sd, LayoutManager.LayoutParams lp)
            {
                int kind = lp.isHeader ? HEADER : CONTENT;

                return(lp.FirstPosition == mSfp && (kind & mTargetKind) != 0);
            }
Ejemplo n.º 19
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);
        }