Search in sources :

Example 16 with OrientationHelper

use of android.support.v7.widget.OrientationHelper in project RecyclerViewSnap by rubensousa.

the class GravitySnapHelper method findEndView.

private View findEndView(RecyclerView.LayoutManager layoutManager, OrientationHelper helper) {
    if (layoutManager instanceof LinearLayoutManager) {
        int lastChild = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
        if (lastChild == RecyclerView.NO_POSITION) {
            return null;
        }
        View child = layoutManager.findViewByPosition(lastChild);
        float visibleWidth;
        if (mIsRtlHorizontal) {
            visibleWidth = (float) helper.getDecoratedEnd(child) / helper.getDecoratedMeasurement(child);
        } else {
            visibleWidth = (float) (helper.getTotalSpace() - helper.getDecoratedStart(child)) / helper.getDecoratedMeasurement(child);
        }
        // If we're at the start of the list, we shouldn't snap
        // to avoid having the first item not completely visible.
        boolean startOfList = ((LinearLayoutManager) layoutManager).findFirstCompletelyVisibleItemPosition() == 0;
        if (visibleWidth > 0.5f && !startOfList) {
            return child;
        } else if (mSnapLastItemEnabled && startOfList) {
            return child;
        } else if (startOfList) {
            return null;
        } else {
            // If the child wasn't returned, we need to return the previous view
            return layoutManager.findViewByPosition(lastChild - 1);
        }
    }
    return null;
}
Also used : LinearLayoutManager(android.support.v7.widget.LinearLayoutManager) RecyclerView(android.support.v7.widget.RecyclerView) View(android.view.View)

Example 17 with OrientationHelper

use of android.support.v7.widget.OrientationHelper in project vlayout by alibaba.

the class ColumnLayoutHelper method layoutViews.

@Override
public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state, VirtualLayoutManager.LayoutStateWrapper layoutState, LayoutChunkResult result, LayoutManagerHelper helper) {
    // reach the end of this layout
    if (isOutOfRange(layoutState.getCurrentPosition())) {
        return;
    }
    final boolean layoutInVertical = helper.getOrientation() == VERTICAL;
    final OrientationHelper orientationHelper = helper.getMainOrientationHelper();
    final int itemCount = getItemCount();
    if (mViews == null || mViews.length != itemCount) {
        mViews = new View[itemCount];
    }
    if (mEqViews == null || mEqViews.length != itemCount) {
        mEqViews = new View[itemCount];
    } else {
        Arrays.fill(mEqViews, null);
    }
    final int count = getAllChildren(mViews, recycler, layoutState, result, helper);
    if (layoutInVertical) {
        // TODO: only handle vertical layout now
        int maxVMargin = 0;
        int lastHMargin = 0;
        int totalMargin = 0;
        for (int i = 0; i < count; i++) {
            View view = mViews[i];
            ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
            if (layoutParams instanceof RecyclerView.LayoutParams) {
                RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) layoutParams;
                params.leftMargin = Math.max(lastHMargin, params.leftMargin);
                totalMargin += params.leftMargin;
                if (i != count - 1) {
                    // not last item
                    lastHMargin = params.rightMargin;
                    params.rightMargin = 0;
                } else {
                    totalMargin += params.rightMargin;
                }
                maxVMargin = Math.max(maxVMargin, params.topMargin + params.bottomMargin);
            }
        }
        final int totalWidth = helper.getContentWidth() - helper.getPaddingLeft() - helper.getPaddingRight() - getHorizontalMargin() - getHorizontalPadding();
        final int availableWidth = totalWidth - totalMargin;
        int usedWidth = 0;
        int minHeight = Integer.MAX_VALUE;
        int uniformHeight = -1;
        if (!Float.isNaN(mAspectRatio)) {
            uniformHeight = (int) (totalWidth / mAspectRatio + 0.5f);
        }
        int eqSize = 0;
        for (int i = 0; i < count; i++) {
            View view = mViews[i];
            VirtualLayoutManager.LayoutParams params = (VirtualLayoutManager.LayoutParams) view.getLayoutParams();
            int heightSpec = helper.getChildMeasureSpec(helper.getContentHeight() - helper.getPaddingTop() - helper.getPaddingBottom(), uniformHeight > 0 ? uniformHeight : params.height, true);
            if (mWeights != null && i < mWeights.length && !Float.isNaN(mWeights[i]) && mWeights[i] >= 0) {
                // calculate width with weight in percentage
                int resizeWidth = (int) (mWeights[i] * 1.0f / 100 * availableWidth + 0.5f);
                if (!Float.isNaN(params.mAspectRatio)) {
                    int specialHeight = (int) (resizeWidth / params.mAspectRatio + 0.5f);
                    heightSpec = View.MeasureSpec.makeMeasureSpec(specialHeight, View.MeasureSpec.EXACTLY);
                }
                helper.measureChild(view, View.MeasureSpec.makeMeasureSpec(resizeWidth, View.MeasureSpec.EXACTLY), heightSpec);
                // add width into usedWidth
                usedWidth += resizeWidth;
                // find minHeight
                minHeight = Math.min(minHeight, view.getMeasuredHeight());
            } else {
                mEqViews[eqSize++] = view;
            }
        }
        for (int i = 0; i < eqSize; i++) {
            View view = mEqViews[i];
            VirtualLayoutManager.LayoutParams params = (VirtualLayoutManager.LayoutParams) view.getLayoutParams();
            int heightSpec;
            int resizeWidth = (int) ((availableWidth - usedWidth) * 1.0f / eqSize + 0.5f);
            if (!Float.isNaN(params.mAspectRatio)) {
                int specialHeight = (int) (resizeWidth / params.mAspectRatio + 0.5f);
                heightSpec = View.MeasureSpec.makeMeasureSpec(specialHeight, View.MeasureSpec.EXACTLY);
            } else {
                heightSpec = helper.getChildMeasureSpec(helper.getContentHeight() - helper.getPaddingTop() - helper.getPaddingBottom(), uniformHeight > 0 ? uniformHeight : params.height, true);
            }
            //if cols' length is less than view's count, then remainder views share the rest space
            helper.measureChild(view, View.MeasureSpec.makeMeasureSpec(resizeWidth, View.MeasureSpec.EXACTLY), heightSpec);
            // find minHeight
            minHeight = Math.min(minHeight, view.getMeasuredHeight());
        }
        // uniform all views into min height
        for (int i = 0; i < count; i++) {
            View view = mViews[i];
            if (view.getMeasuredHeight() != minHeight) {
                //noinspection ResourceType
                helper.measureChild(view, View.MeasureSpec.makeMeasureSpec(view.getMeasuredWidth(), View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(minHeight, View.MeasureSpec.EXACTLY));
            }
        }
        result.mConsumed = minHeight + maxVMargin + getVerticalMargin() + getVerticalPadding();
        calculateRect(minHeight + maxVMargin, mTempArea, layoutState, helper);
        // do layout
        int left = mTempArea.left;
        for (int i = 0; i < count; i++) {
            View view = mViews[i];
            int top = mTempArea.top, bottom = mTempArea.bottom;
            int right = left + orientationHelper.getDecoratedMeasurementInOther(view);
            layoutChild(view, left, top, right, bottom, helper);
            left = right;
        }
    }
    Arrays.fill(mViews, null);
    Arrays.fill(mEqViews, null);
}
Also used : OrientationHelper(android.support.v7.widget.OrientationHelper) ViewGroup(android.view.ViewGroup) RecyclerView(android.support.v7.widget.RecyclerView) VirtualLayoutManager(com.alibaba.android.vlayout.VirtualLayoutManager) RecyclerView(android.support.v7.widget.RecyclerView) View(android.view.View)

Example 18 with OrientationHelper

use of android.support.v7.widget.OrientationHelper in project vlayout by alibaba.

the class GridLayoutHelper method layoutViews.

@Override
public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state, LayoutStateWrapper layoutState, LayoutChunkResult result, LayoutManagerHelper helper) {
    // reach the end of this layout
    if (isOutOfRange(layoutState.getCurrentPosition())) {
        return;
    }
    boolean isStartLine = false, isEndLine = false;
    final int currentPosition = layoutState.getCurrentPosition();
    final int itemDirection = layoutState.getItemDirection();
    final boolean layingOutInPrimaryDirection = itemDirection == LayoutStateWrapper.ITEM_DIRECTION_TAIL;
    OrientationHelper orientationHelper = helper.getMainOrientationHelper();
    final boolean layoutInVertical = helper.getOrientation() == VERTICAL;
    if (layoutInVertical) {
        mTotalSize = helper.getContentWidth() - helper.getPaddingRight() - helper.getPaddingLeft() - getHorizontalMargin() - getHorizontalPadding();
        mSizePerSpan = (int) ((mTotalSize - (mSpanCount - 1) * mHGap) * 1.0f / mSpanCount + 0.5f);
    } else {
        mTotalSize = helper.getContentHeight() - helper.getPaddingBottom() - helper.getPaddingTop() - getVerticalMargin() - getVerticalPadding();
        mSizePerSpan = (int) ((mTotalSize - (mSpanCount - 1) * mVGap) * 1.0f / mSpanCount + 0.5f);
    }
    int count = 0;
    int consumedSpanCount = 0;
    int remainingSpan = mSpanCount;
    ensureSpanCount();
    if (!layingOutInPrimaryDirection) {
        // fill the remaining spacing this row
        int itemSpanIndex = getSpanIndex(recycler, state, layoutState.getCurrentPosition());
        int itemSpanSize = getSpanSize(recycler, state, layoutState.getCurrentPosition());
        remainingSpan = itemSpanIndex + itemSpanSize;
        // should find the last element of this row
        if (itemSpanIndex != mSpanCount - 1) {
            int index = layoutState.getCurrentPosition();
            int revRemainingSpan = mSpanCount - remainingSpan;
            while (count < mSpanCount && revRemainingSpan > 0) {
                // go reverse direction to find views fill current row
                index -= itemDirection;
                if (isOutOfRange(index)) {
                    break;
                }
                final int spanSize = getSpanSize(recycler, state, index);
                if (spanSize > mSpanCount) {
                    throw new IllegalArgumentException("Item at position " + index + " requires " + spanSize + " spans but GridLayoutManager has only " + mSpanCount + " spans.");
                }
                View view = layoutState.retrieve(recycler, index);
                if (view == null)
                    break;
                if (!isStartLine) {
                    isStartLine = helper.getReverseLayout() ? index == getRange().getUpper() : index == getRange().getLower();
                }
                if (!isEndLine) {
                    isEndLine = helper.getReverseLayout() ? index == getRange().getLower() : index == getRange().getUpper();
                }
                revRemainingSpan -= spanSize;
                if (revRemainingSpan < 0)
                    break;
                consumedSpanCount += spanSize;
                mSet[count] = view;
                count++;
            }
            if (count > 0) {
                // reverse array
                int s = 0, e = count - 1;
                while (s < e) {
                    View temp = mSet[s];
                    mSet[s] = mSet[e];
                    mSet[e] = temp;
                    s++;
                    e--;
                }
            }
        }
    }
    while (count < mSpanCount && layoutState.hasMore(state) && remainingSpan > 0) {
        int pos = layoutState.getCurrentPosition();
        if (isOutOfRange(pos)) {
            if (DEBUG)
                Log.d(TAG, "pos [" + pos + "] is out of range");
            break;
        }
        final int spanSize = getSpanSize(recycler, state, pos);
        if (spanSize > mSpanCount) {
            throw new IllegalArgumentException("Item at position " + pos + " requires " + spanSize + " spans but GridLayoutManager has only " + mSpanCount + " spans.");
        }
        remainingSpan -= spanSize;
        if (remainingSpan < 0) {
            // item did not fit into this row or column
            break;
        }
        View view = layoutState.next(recycler);
        if (view == null) {
            break;
        }
        if (!isStartLine) {
            isStartLine = helper.getReverseLayout() ? pos == getRange().getUpper().intValue() : pos == getRange().getLower().intValue();
        }
        if (!isEndLine) {
            isEndLine = helper.getReverseLayout() ? pos == getRange().getLower().intValue() : pos == getRange().getUpper().intValue();
        }
        consumedSpanCount += spanSize;
        mSet[count] = view;
        count++;
    }
    if (count == 0) {
        return;
    }
    int maxSize = 0;
    // we should assign spans before item decor offsets are calculated
    assignSpans(recycler, state, count, consumedSpanCount, layingOutInPrimaryDirection, helper);
    if (remainingSpan > 0 && mIsAutoExpand) {
        if (layoutInVertical) {
            mSizePerSpan = (helper.getContentWidth() - helper.getPaddingRight() - getHorizontalMargin() - getHorizontalPadding() - helper.getPaddingLeft() - (count - 1) * mHGap) / count;
        } else {
            mSizePerSpan = (helper.getContentHeight() - helper.getPaddingBottom() - getVerticalMargin() - getVerticalPadding() - helper.getPaddingTop() - (count - 1) * mVGap) / count;
        }
    }
    boolean weighted = false;
    if (mWeights != null && mWeights.length > 0) {
        weighted = true;
        int totalSpace;
        if (layoutInVertical) {
            totalSpace = helper.getContentWidth() - helper.getPaddingLeft() - helper.getPaddingRight() - getHorizontalMargin() - getHorizontalPadding() - (count - 1) * mHGap;
        } else {
            totalSpace = helper.getContentHeight() - helper.getPaddingTop() - helper.getPaddingBottom() - getVerticalMargin() - getVerticalPadding() - (count - 1) * mVGap;
        }
        // calculate width with weight in percentage
        int eqCnt = 0, remainingSpace = totalSpace;
        int colCnt = (remainingSpan > 0 && mIsAutoExpand) ? count : mSpanCount;
        for (int i = 0; i < colCnt; i++) {
            if (i < mWeights.length && !Float.isNaN(mWeights[i]) && mWeights[i] >= 0) {
                float weight = mWeights[i];
                mSpanCols[i] = (int) (weight * 1.0f / 100 * totalSpace + 0.5f);
                remainingSpace -= mSpanCols[i];
            } else {
                eqCnt++;
                mSpanCols[i] = -1;
            }
        }
        if (eqCnt > 0) {
            int eqLength = remainingSpace / eqCnt;
            for (int i = 0; i < colCnt; i++) {
                if (mSpanCols[i] < 0) {
                    mSpanCols[i] = eqLength;
                }
            }
        }
    }
    for (int i = 0; i < count; i++) {
        View view = mSet[i];
        helper.addChildView(layoutState, view, layingOutInPrimaryDirection ? -1 : 0);
        int spanSize = getSpanSize(recycler, state, helper.getPosition(view)), spec;
        if (weighted) {
            final int index = mSpanIndices[i];
            int spanLength = 0;
            for (int j = 0; j < spanSize; j++) {
                spanLength += mSpanCols[j + index];
            }
            spec = View.MeasureSpec.makeMeasureSpec(Math.max(0, spanLength), View.MeasureSpec.EXACTLY);
        } else {
            spec = View.MeasureSpec.makeMeasureSpec(mSizePerSpan * spanSize + Math.max(0, spanSize - 1) * (layoutInVertical ? mHGap : mVGap), View.MeasureSpec.EXACTLY);
        }
        final VirtualLayoutManager.LayoutParams lp = (VirtualLayoutManager.LayoutParams) view.getLayoutParams();
        if (helper.getOrientation() == VERTICAL) {
            helper.measureChild(view, spec, getMainDirSpec(lp.height, mTotalSize, View.MeasureSpec.getSize(spec), lp.mAspectRatio));
        } else {
            helper.measureChild(view, getMainDirSpec(lp.width, mTotalSize, View.MeasureSpec.getSize(spec), lp.mAspectRatio), View.MeasureSpec.getSize(spec));
        }
        final int size = orientationHelper.getDecoratedMeasurement(view);
        if (size > maxSize) {
            maxSize = size;
        }
    }
    // views that did not measure the maxSize has to be re-measured
    final int maxMeasureSpec = getMainDirSpec(maxSize, mTotalSize, 0, Float.NaN);
    for (int i = 0; i < count; i++) {
        final View view = mSet[i];
        if (orientationHelper.getDecoratedMeasurement(view) != maxSize) {
            int spanSize = getSpanSize(recycler, state, helper.getPosition(view)), spec;
            if (weighted) {
                final int index = mSpanIndices[i];
                int spanLength = 0;
                for (int j = 0; j < spanSize; j++) {
                    spanLength += mSpanCols[j + index];
                }
                spec = View.MeasureSpec.makeMeasureSpec(Math.max(0, spanLength), View.MeasureSpec.EXACTLY);
            } else {
                spec = View.MeasureSpec.makeMeasureSpec(mSizePerSpan * spanSize + Math.max(0, spanSize - 1) * (layoutInVertical ? mHGap : mVGap), View.MeasureSpec.EXACTLY);
            }
            if (helper.getOrientation() == VERTICAL) {
                helper.measureChild(view, spec, maxMeasureSpec);
            } else {
                helper.measureChild(view, maxMeasureSpec, spec);
            }
        }
    }
    int startSpace = 0, endSpace = 0;
    if (isStartLine) {
        startSpace = layoutInVertical ? mMarginTop + mPaddingTop : mMarginLeft + mPaddingLeft;
    }
    if (isEndLine) {
        endSpace = layoutInVertical ? mMarginBottom + mPaddingBottom : mMarginRight + mPaddingRight;
    }
    result.mConsumed = maxSize + startSpace + endSpace;
    final boolean layoutStart = layoutState.getLayoutDirection() == LayoutStateWrapper.LAYOUT_START;
    if (!mLayoutWithAnchor && (!isEndLine || !layoutStart) && (!isStartLine || layoutStart)) {
        result.mConsumed += (layoutInVertical ? mVGap : mHGap);
    }
    int left = 0, right = 0, top = 0, bottom = 0;
    if (layoutInVertical) {
        if (layoutState.getLayoutDirection() == LayoutStateWrapper.LAYOUT_START) {
            bottom = layoutState.getOffset() - endSpace - ((mLayoutWithAnchor || isEndLine) ? 0 : mVGap);
            top = bottom - maxSize;
        } else {
            top = layoutState.getOffset() + startSpace + ((mLayoutWithAnchor || isStartLine) ? 0 : mVGap);
            bottom = top + maxSize;
        }
    } else {
        if (layoutState.getLayoutDirection() == LayoutStateWrapper.LAYOUT_START) {
            right = layoutState.getOffset() - endSpace - (mLayoutWithAnchor || isEndLine ? 0 : mHGap);
            left = right - maxSize;
        } else {
            left = layoutState.getOffset() + startSpace + (mLayoutWithAnchor || isStartLine ? 0 : mHGap);
            right = left + maxSize;
        }
    }
    for (int i = 0; i < count; i++) {
        View view = mSet[i];
        final int index = mSpanIndices[i];
        LayoutParams params = (LayoutParams) view.getLayoutParams();
        if (layoutInVertical) {
            if (weighted) {
                left = helper.getPaddingLeft() + mMarginLeft + mPaddingLeft;
                for (int j = 0; j < index; j++) left += mSpanCols[j] + mHGap;
            } else
                left = helper.getPaddingLeft() + mMarginLeft + mPaddingLeft + mSizePerSpan * index + index * mHGap;
            right = left + orientationHelper.getDecoratedMeasurementInOther(view);
        } else {
            if (weighted) {
                top = helper.getPaddingTop() + mMarginTop + mPaddingTop;
                for (int j = 0; j < index; j++) top += mSpanCols[j] + mVGap;
            } else
                top = helper.getPaddingTop() + mMarginTop + mPaddingTop + mSizePerSpan * index + index * mVGap;
            bottom = top + orientationHelper.getDecoratedMeasurementInOther(view);
        }
        if (DEBUG) {
            Log.d(TAG, "layout item in position: " + params.getViewPosition() + " with text " + ((TextView) view).getText() + " with SpanIndex: " + index + " into (" + left + ", " + top + ", " + right + ", " + bottom + " )");
        }
        // We calculate everything with View's bounding box (which includes decor and margins)
        // To calculate correct layout position, we subtract margins.
        // modified by huifeng at 20160907, margins are already subtracted
        layoutChild(view, left, top, right, bottom, helper);
        // Consume the available space if the view is not removed OR changed
        if (params.isItemRemoved() || params.isItemChanged()) {
            result.mIgnoreConsumed = true;
        }
        result.mFocusable |= view.isFocusable();
    }
    mLayoutWithAnchor = false;
    Arrays.fill(mSet, null);
    Arrays.fill(mSpanIndices, 0);
    Arrays.fill(mSpanCols, 0);
}
Also used : LayoutParams(com.alibaba.android.vlayout.VirtualLayoutManager.LayoutParams) OrientationHelper(android.support.v7.widget.OrientationHelper) LayoutParams(com.alibaba.android.vlayout.VirtualLayoutManager.LayoutParams) VirtualLayoutManager(com.alibaba.android.vlayout.VirtualLayoutManager) RecyclerView(android.support.v7.widget.RecyclerView) TextView(android.widget.TextView) View(android.view.View)

Example 19 with OrientationHelper

use of android.support.v7.widget.OrientationHelper in project vlayout by alibaba.

the class StaggeredGridLayoutHelper method recycleFromStart.

private void recycleFromStart(RecyclerView.Recycler recycler, int line, LayoutManagerHelper helper) {
    final OrientationHelper orientationHelper = helper.getMainOrientationHelper();
    boolean changed = true;
    while (helper.getChildCount() > 0 && changed) {
        View child = helper.getChildAt(0);
        if (child != null && orientationHelper.getDecoratedEnd(child) < line) {
            LayoutParams lp = (LayoutParams) child.getLayoutParams();
            int position = lp.getViewPosition();
            Span span = findSpan(position, child, true);
            if (span != null) {
                span.popStart(orientationHelper);
                helper.removeChildView(child);
                recycler.recycleView(child);
            } else {
                changed = false;
            }
        } else {
            // done
            return;
        }
    }
}
Also used : LayoutParams(android.support.v7.widget.RecyclerView.LayoutParams) OrientationHelper(android.support.v7.widget.OrientationHelper) RecyclerView(android.support.v7.widget.RecyclerView) View(android.view.View)

Example 20 with OrientationHelper

use of android.support.v7.widget.OrientationHelper in project vlayout by alibaba.

the class StaggeredGridLayoutHelper method recycle.

private void recycle(RecyclerView.Recycler recycler, LayoutStateWrapper layoutState, Span updatedSpan, int recycleLine, LayoutManagerHelper helper) {
    OrientationHelper orientation = helper.getMainOrientationHelper();
    if (layoutState.getLayoutDirection() == LAYOUT_START) {
        // calculate recycle line
        int maxStart = getMaxStart(updatedSpan.getStartLine(orientation), orientation);
        recycleFromEnd(recycler, Math.max(recycleLine, maxStart) + (orientation.getEnd() - orientation.getStartAfterPadding()), helper);
    } else {
        // calculate recycle line
        int minEnd = getMinEnd(updatedSpan.getEndLine(orientation), orientation);
        recycleFromStart(recycler, Math.min(recycleLine, minEnd) - (orientation.getEnd() - orientation.getStartAfterPadding()), helper);
    }
}
Also used : OrientationHelper(android.support.v7.widget.OrientationHelper)

Aggregations

OrientationHelper (android.support.v7.widget.OrientationHelper)21 RecyclerView (android.support.v7.widget.RecyclerView)21 View (android.view.View)21 VirtualLayoutManager (com.alibaba.android.vlayout.VirtualLayoutManager)10 LinearLayoutManager (android.support.v7.widget.LinearLayoutManager)4 LayoutParams (android.support.v7.widget.RecyclerView.LayoutParams)4 Nullable (android.support.annotation.Nullable)2 GridLayoutManager (android.support.v7.widget.GridLayoutManager)2 ViewGroup (android.view.ViewGroup)2 LayoutParams (android.view.ViewGroup.LayoutParams)1 TextView (android.widget.TextView)1 LayoutHelper (com.alibaba.android.vlayout.LayoutHelper)1 LayoutParams (com.alibaba.android.vlayout.VirtualLayoutManager.LayoutParams)1