Search in sources :

Example 6 with OrientationHelperEx

use of com.alibaba.android.vlayout.OrientationHelperEx in project vlayout by alibaba.

the class RangeGridLayoutHelper method layoutViews.

// TODO optimize this method
@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;
    boolean isSecondStartLine = false, isSecondEndLine = false;
    final int currentPosition = layoutState.getCurrentPosition();
    GridRangeStyle rangeStyle = mRangeStyle.findRangeStyleByPosition(currentPosition);
    final int itemDirection = layoutState.getItemDirection();
    final boolean layingOutInPrimaryDirection = itemDirection == LayoutStateWrapper.ITEM_DIRECTION_TAIL;
    OrientationHelperEx orientationHelper = helper.getMainOrientationHelper();
    final boolean layoutInVertical = helper.getOrientation() == VERTICAL;
    if (layoutInVertical) {
        mTotalSize = helper.getContentWidth() - helper.getPaddingRight() - helper.getPaddingLeft() - rangeStyle.getFamilyHorizontalMargin() - rangeStyle.getFamilyHorizontalPadding();
        rangeStyle.mSizePerSpan = (int) ((mTotalSize - (rangeStyle.mSpanCount - 1) * rangeStyle.mHGap) * 1.0f / rangeStyle.mSpanCount + 0.5f);
    } else {
        mTotalSize = helper.getContentHeight() - helper.getPaddingBottom() - helper.getPaddingTop() - rangeStyle.getFamilyVerticalMargin() - rangeStyle.getFamilyVerticalPadding();
        rangeStyle.mSizePerSpan = (int) ((mTotalSize - (rangeStyle.mSpanCount - 1) * rangeStyle.mVGap) * 1.0f / rangeStyle.mSpanCount + 0.5f);
    }
    int count = 0;
    int consumedSpanCount = 0;
    int remainingSpan = rangeStyle.mSpanCount;
    rangeStyle.ensureSpanCount();
    if (!layingOutInPrimaryDirection) {
        // fill the remaining spacing this row
        int itemSpanIndex = getSpanIndex(rangeStyle.mSpanSizeLookup, rangeStyle.mSpanCount, recycler, state, currentPosition);
        int itemSpanSize = getSpanSize(rangeStyle.mSpanSizeLookup, recycler, state, currentPosition);
        remainingSpan = itemSpanIndex + itemSpanSize;
        // should find the last element of this row
        if (itemSpanIndex != rangeStyle.mSpanCount - 1) {
            int index = layoutState.getCurrentPosition();
            int revRemainingSpan = rangeStyle.mSpanCount - remainingSpan;
            while (count < rangeStyle.mSpanCount && revRemainingSpan > 0) {
                // go reverse direction to find views fill current row
                index -= itemDirection;
                if (rangeStyle.isOutOfRange(index)) {
                    break;
                }
                final int spanSize = getSpanSize(rangeStyle.mSpanSizeLookup, recycler, state, index);
                if (spanSize > rangeStyle.mSpanCount) {
                    throw new IllegalArgumentException("Item at position " + index + " requires " + spanSize + " spans but RangeGridLayoutHelper has only " + rangeStyle.mSpanCount + " spans.");
                }
                View view = layoutState.retrieve(recycler, index);
                if (view == null) {
                    break;
                }
                if (!isStartLine) {
                    isStartLine = helper.getReverseLayout() ? index == mRangeStyle.getRange().getUpper().intValue() : index == mRangeStyle.getRange().getLower().intValue();
                }
                if (!isEndLine) {
                    isEndLine = helper.getReverseLayout() ? index == mRangeStyle.getRange().getLower().intValue() : index == mRangeStyle.getRange().getUpper().intValue();
                }
                revRemainingSpan -= spanSize;
                if (revRemainingSpan < 0) {
                    break;
                }
                consumedSpanCount += spanSize;
                rangeStyle.mSet[count] = view;
                count++;
            }
            if (count > 0) {
                // reverse array
                int s = 0, e = count - 1;
                while (s < e) {
                    View temp = rangeStyle.mSet[s];
                    rangeStyle.mSet[s] = rangeStyle.mSet[e];
                    rangeStyle.mSet[e] = temp;
                    s++;
                    e--;
                }
            }
        }
    }
    while (count < rangeStyle.mSpanCount && layoutState.hasMore(state) && remainingSpan > 0) {
        int pos = layoutState.getCurrentPosition();
        if (rangeStyle.isOutOfRange(pos)) {
            if (DEBUG) {
                Log.d(TAG, "pos [" + pos + "] is out of range");
            }
            break;
        }
        final int spanSize = getSpanSize(rangeStyle.mSpanSizeLookup, recycler, state, pos);
        if (spanSize > rangeStyle.mSpanCount) {
            throw new IllegalArgumentException("Item at position " + pos + " requires " + spanSize + " spans but GridLayoutManager has only " + rangeStyle.mSpanCount + " spans.");
        }
        remainingSpan -= spanSize;
        if (remainingSpan < 0) {
            // item did not fit into this row or column
            break;
        }
        if (!isStartLine) {
            isStartLine = helper.getReverseLayout() ? pos == mRangeStyle.getRange().getUpper().intValue() : pos == mRangeStyle.getRange().getLower().intValue();
        }
        if (!isSecondStartLine) {
            if (!rangeStyle.equals(mRangeStyle)) {
                isSecondStartLine = helper.getReverseLayout() ? pos == rangeStyle.getRange().getUpper().intValue() : pos == rangeStyle.getRange().getLower().intValue();
            }
        }
        if (!isEndLine) {
            isEndLine = helper.getReverseLayout() ? pos == mRangeStyle.getRange().getLower().intValue() : pos == mRangeStyle.getRange().getUpper().intValue();
        }
        if (!isSecondEndLine) {
            if (!rangeStyle.equals(mRangeStyle)) {
                isSecondEndLine = helper.getReverseLayout() ? pos == rangeStyle.getRange().getLower().intValue() : pos == rangeStyle.getRange().getUpper().intValue();
                if (DEBUG) {
                    Log.d(TAG, "isSecondEndLineLogic:" + isSecondEndLine + "  helper.getReverseLayout()=" + helper.getReverseLayout() + " pos=" + pos + " rangeStyle.getRange().getLower()=" + rangeStyle.getRange().getLower() + " rangeStyle.getRange().getUpper()=" + rangeStyle.getRange().getUpper());
                }
            }
        }
        View view = layoutState.next(recycler);
        if (view == null) {
            break;
        }
        consumedSpanCount += spanSize;
        rangeStyle.mSet[count] = view;
        count++;
    }
    if (count == 0) {
        return;
    }
    int maxSize = 0;
    // we should assign spans before item decor offsets are calculated
    assignSpans(rangeStyle, recycler, state, count, consumedSpanCount, layingOutInPrimaryDirection, helper);
    if (remainingSpan > 0 && (count == consumedSpanCount) && rangeStyle.mIsAutoExpand) {
        // autoExpand only support when each cell occupy one span.
        if (layoutInVertical) {
            rangeStyle.mSizePerSpan = (mTotalSize - (count - 1) * rangeStyle.mHGap) / count;
        } else {
            rangeStyle.mSizePerSpan = (mTotalSize - (count - 1) * rangeStyle.mVGap) / count;
        }
    } else if (!layingOutInPrimaryDirection && remainingSpan == 0 && (count == consumedSpanCount) && rangeStyle.mIsAutoExpand) {
        // autoExpand only support when each cell occupy one span.
        if (layoutInVertical) {
            rangeStyle.mSizePerSpan = (mTotalSize - (count - 1) * rangeStyle.mHGap) / count;
        } else {
            rangeStyle.mSizePerSpan = (mTotalSize - (count - 1) * rangeStyle.mVGap) / count;
        }
    }
    boolean weighted = false;
    if (rangeStyle.mWeights != null && rangeStyle.mWeights.length > 0) {
        weighted = true;
        int totalSpace;
        if (layoutInVertical) {
            totalSpace = mTotalSize - (count - 1) * rangeStyle.mHGap;
        } else {
            totalSpace = mTotalSize - (count - 1) * rangeStyle.mVGap;
        }
        // calculate width with weight in percentage
        int eqCnt = 0, remainingSpace = totalSpace;
        int colCnt = (remainingSpan > 0 && rangeStyle.mIsAutoExpand) ? count : rangeStyle.mSpanCount;
        for (int i = 0; i < colCnt; i++) {
            if (i < rangeStyle.mWeights.length && !Float.isNaN(rangeStyle.mWeights[i]) && rangeStyle.mWeights[i] >= 0) {
                float weight = rangeStyle.mWeights[i];
                rangeStyle.mSpanCols[i] = (int) (weight * 1.0f / 100 * totalSpace + 0.5f);
                remainingSpace -= rangeStyle.mSpanCols[i];
            } else {
                eqCnt++;
                rangeStyle.mSpanCols[i] = -1;
            }
        }
        if (eqCnt > 0) {
            int eqLength = remainingSpace / eqCnt;
            for (int i = 0; i < colCnt; i++) {
                if (rangeStyle.mSpanCols[i] < 0) {
                    rangeStyle.mSpanCols[i] = eqLength;
                }
            }
        }
    }
    for (int i = 0; i < count; i++) {
        View view = rangeStyle.mSet[i];
        helper.addChildView(layoutState, view, layingOutInPrimaryDirection ? -1 : 0);
        int spanSize = getSpanSize(rangeStyle.mSpanSizeLookup, recycler, state, helper.getPosition(view)), spec;
        if (weighted) {
            final int index = rangeStyle.mSpanIndices[i];
            int spanLength = 0;
            for (int j = 0; j < spanSize; j++) {
                spanLength += rangeStyle.mSpanCols[j + index];
            }
            spec = View.MeasureSpec.makeMeasureSpec(Math.max(0, spanLength), View.MeasureSpec.EXACTLY);
        } else {
            spec = View.MeasureSpec.makeMeasureSpec(rangeStyle.mSizePerSpan * spanSize + Math.max(0, spanSize - 1) * (layoutInVertical ? rangeStyle.mHGap : rangeStyle.mVGap), View.MeasureSpec.EXACTLY);
        }
        final LayoutParams lp = (LayoutParams) view.getLayoutParams();
        if (helper.getOrientation() == VERTICAL) {
            helper.measureChildWithMargins(view, spec, getMainDirSpec(rangeStyle, lp.height, mTotalSize, View.MeasureSpec.getSize(spec), lp.mAspectRatio));
        } else {
            helper.measureChildWithMargins(view, getMainDirSpec(rangeStyle, 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(rangeStyle, maxSize, mTotalSize, 0, Float.NaN);
    for (int i = 0; i < count; i++) {
        final View view = rangeStyle.mSet[i];
        if (orientationHelper.getDecoratedMeasurement(view) != maxSize) {
            int spanSize = getSpanSize(rangeStyle.mSpanSizeLookup, recycler, state, helper.getPosition(view)), spec;
            if (weighted) {
                final int index = rangeStyle.mSpanIndices[i];
                int spanLength = 0;
                for (int j = 0; j < spanSize; j++) {
                    spanLength += rangeStyle.mSpanCols[j + index];
                }
                spec = View.MeasureSpec.makeMeasureSpec(Math.max(0, spanLength), View.MeasureSpec.EXACTLY);
            } else {
                spec = View.MeasureSpec.makeMeasureSpec(rangeStyle.mSizePerSpan * spanSize + Math.max(0, spanSize - 1) * (layoutInVertical ? rangeStyle.mHGap : rangeStyle.mVGap), View.MeasureSpec.EXACTLY);
            }
            if (helper.getOrientation() == VERTICAL) {
                helper.measureChildWithMargins(view, spec, maxMeasureSpec);
            } else {
                helper.measureChildWithMargins(view, maxMeasureSpec, spec);
            }
        }
    }
    int startSpace = 0, endSpace = 0;
    int secondStartSpace = 0, secondEndSpace = 0;
    boolean isLayoutEnd = layoutState.getLayoutDirection() == VirtualLayoutManager.LayoutStateWrapper.LAYOUT_END;
    final boolean isOverLapMargin = helper.isEnableMarginOverLap();
    if (isStartLine) {
        startSpace = computeStartSpace(helper, layoutInVertical, isLayoutEnd, isOverLapMargin);
    }
    if (isSecondStartLine) {
        secondStartSpace = (layoutInVertical ? rangeStyle.getMarginTop() + rangeStyle.getPaddingTop() : rangeStyle.getMarginLeft() + rangeStyle.getPaddingLeft());
    }
    if (isEndLine) {
        endSpace = layoutInVertical ? mRangeStyle.getMarginBottom() + mRangeStyle.getPaddingBottom() : mRangeStyle.getMarginRight() + mRangeStyle.getPaddingRight();
    }
    if (isSecondEndLine) {
        secondEndSpace = (layoutInVertical ? rangeStyle.getMarginBottom() + rangeStyle.getPaddingBottom() : rangeStyle.getMarginRight() + rangeStyle.getPaddingRight());
        if (DEBUG) {
            Log.d(TAG, "isSecondEndLineLogic:" + isSecondEndLine + " pos=" + currentPosition + " secondEndSpace=" + secondEndSpace);
        }
    }
    result.mConsumed = maxSize + startSpace + endSpace + secondStartSpace + secondEndSpace;
    final boolean layoutStart = layoutState.getLayoutDirection() == LayoutStateWrapper.LAYOUT_START;
    int consumedGap = 0;
    if (!mLayoutWithAnchor) {
        if (!layoutStart) {
            if (!isStartLine) {
                if (isSecondStartLine) {
                    consumedGap = (layoutInVertical ? rangeStyle.mParent.mVGap : rangeStyle.mParent.mHGap);
                    if (DEBUG) {
                        Log.d(TAG, "⬇ " + currentPosition + " 1 " + consumedGap + " gap");
                    }
                } else {
                    consumedGap = (layoutInVertical ? rangeStyle.mVGap : rangeStyle.mHGap);
                    if (DEBUG) {
                        Log.d(TAG, "⬇ " + currentPosition + " 2 " + consumedGap + " gap");
                    }
                }
            }
        } else {
            if (!isEndLine) {
                if (isSecondEndLine) {
                    consumedGap = (layoutInVertical ? rangeStyle.mParent.mVGap : rangeStyle.mParent.mHGap);
                    if (DEBUG) {
                        Log.d(TAG, "⬆ " + currentPosition + " 3 " + consumedGap + " gap");
                    }
                } else {
                    consumedGap = (layoutInVertical ? rangeStyle.mVGap : rangeStyle.mHGap);
                    if (DEBUG) {
                        Log.d(TAG, "⬆ " + currentPosition + " 4 " + consumedGap + " gap");
                    }
                }
            }
        }
    }
    result.mConsumed += consumedGap;
    if (result.mConsumed <= 0) {
        result.mConsumed = 0;
    }
    int lastUnconsumedSpace = 0;
    /**
     * layoutView() may be triggered by layoutManager's scrollInternalBy() or onFocusSearchFailed() or onLayoutChildren()
     *
     * In case of scrollInternalBy() or onFocusSearchFailed(), layoutState.isRefreshLayout() == false, and layoutState.mOffset = ChildClosestToExpose + alignOffset,
     * see {@link com.alibaba.android.vlayout.ExposeLinearLayoutManagerEx#updateLayoutStateExpose(int, int, boolean, State)},
     * this means last line's layout padding or margin is not really consumed, so considering it before layout new line.
     *
     * In case of onLayoutChildren(), layoutState.isRefreshLayout() == true, and layoutState.mOffset = anchorInfo.mCoordinate = anchorChild.start + alignOffset,
     * see {@link com.alibaba.android.vlayout.ExposeLinearLayoutManagerEx#updateAnchorInfoForLayoutExpose(State, AnchorInfo)},
     * this means last line's layout padding or margin is consumed.
     */
    if (!layoutState.isRefreshLayout()) {
        if (layoutStart) {
            int lastLinePosition = currentPosition + 1;
            if (!isOutOfRange(lastLinePosition)) {
                RangeStyle<GridRangeStyle> neighbourRange = mRangeStyle.findRangeStyleByPosition(lastLinePosition);
                if (neighbourRange.isFirstPosition(lastLinePosition)) {
                    lastUnconsumedSpace = layoutInVertical ? neighbourRange.getMarginTop() + neighbourRange.getPaddingTop() : neighbourRange.getMarginLeft() + neighbourRange.getPaddingLeft();
                    if (DEBUG) {
                        Log.d(TAG, "⬆ " + currentPosition + " 1 " + lastUnconsumedSpace + " last");
                    }
                }
            }
        } else {
            int lastLinePosition = currentPosition - 1;
            if (!isOutOfRange(lastLinePosition)) {
                RangeStyle<GridRangeStyle> neighbourRange = mRangeStyle.findRangeStyleByPosition(lastLinePosition);
                if (neighbourRange.isLastPosition(lastLinePosition)) {
                    lastUnconsumedSpace = layoutInVertical ? neighbourRange.getMarginBottom() + neighbourRange.getPaddingBottom() : neighbourRange.getMarginRight() + neighbourRange.getPaddingRight();
                    if (DEBUG) {
                        Log.d(TAG, "⬇ " + currentPosition + " 2 " + lastUnconsumedSpace + " last");
                    }
                }
            }
        }
    }
    if (DEBUG) {
        Log.d(TAG, (layoutStart ? "⬆ " : "⬇ ") + currentPosition + " consumed " + result.mConsumed + " startSpace " + startSpace + " endSpace " + endSpace + " secondStartSpace " + secondStartSpace + " secondEndSpace " + secondEndSpace + " lastUnconsumedSpace " + lastUnconsumedSpace + " isSecondEndLine=" + isSecondEndLine);
    }
    int left = 0, right = 0, top = 0, bottom = 0;
    if (layoutInVertical) {
        if (layoutStart) {
            bottom = layoutState.getOffset() - endSpace - secondEndSpace - (consumedGap) - lastUnconsumedSpace;
            top = bottom - maxSize;
        } else {
            top = layoutState.getOffset() + startSpace + secondStartSpace + (consumedGap) + lastUnconsumedSpace;
            bottom = top + maxSize;
        }
    } else {
        if (layoutStart) {
            right = layoutState.getOffset() - endSpace - (consumedGap) - lastUnconsumedSpace;
            left = right - maxSize;
        } else {
            left = layoutState.getOffset() + startSpace + (consumedGap) + lastUnconsumedSpace;
            right = left + maxSize;
        }
    }
    for (int i = 0; i < count; i++) {
        View view = rangeStyle.mSet[i];
        final int index = rangeStyle.mSpanIndices[i];
        LayoutParams params = (LayoutParams) view.getLayoutParams();
        if (layoutInVertical) {
            if (weighted) {
                left = helper.getPaddingLeft() + rangeStyle.getFamilyMarginLeft() + rangeStyle.getFamilyPaddingLeft();
                for (int j = 0; j < index; j++) {
                    left += rangeStyle.mSpanCols[j] + rangeStyle.mHGap;
                }
            } else {
                left = helper.getPaddingLeft() + rangeStyle.getFamilyMarginLeft() + rangeStyle.getFamilyPaddingLeft() + rangeStyle.mSizePerSpan * index + index * rangeStyle.mHGap;
            }
            right = left + orientationHelper.getDecoratedMeasurementInOther(view);
        } else {
            if (weighted) {
                top = helper.getPaddingTop() + rangeStyle.getFamilyMarginTop() + rangeStyle.getFamilyPaddingTop();
                for (int j = 0; j < index; j++) {
                    top += rangeStyle.mSpanCols[j] + rangeStyle.mVGap;
                }
            } else {
                top = helper.getPaddingTop() + rangeStyle.getFamilyMarginTop() + rangeStyle.getFamilyPaddingTop() + rangeStyle.mSizePerSpan * index + index * rangeStyle.mVGap;
            }
            bottom = top + orientationHelper.getDecoratedMeasurementInOther(view);
        }
        if (DEBUG) {
            Log.d(TAG, "layout item in position: " + params.getViewPosition() + " with text with SpanIndex: " + index + " into (" + left + ", " + top + ", " + right + ", " + bottom + "), topInfo=[layoutState.getOffset()=" + layoutState.getOffset() + " startSpace=" + startSpace + " secondStartSpace=" + secondStartSpace + " consumedGap=" + consumedGap + " lastUnconsumedSpace=" + lastUnconsumedSpace + "]");
        }
        // We calculate everything with View's bounding box (which includes decor and margins)
        // To calculate correct layout position, we subtract margins.
        rangeStyle.layoutChild(view, left, top, right, bottom, helper, false);
        // 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(rangeStyle.mSet, null);
    Arrays.fill(rangeStyle.mSpanIndices, 0);
    Arrays.fill(rangeStyle.mSpanCols, 0);
}
Also used : LayoutParams(com.alibaba.android.vlayout.VirtualLayoutManager.LayoutParams) OrientationHelperEx(com.alibaba.android.vlayout.OrientationHelperEx) RecyclerView(android.support.v7.widget.RecyclerView) View(android.view.View)

Example 7 with OrientationHelperEx

use of com.alibaba.android.vlayout.OrientationHelperEx in project vlayout by alibaba.

the class FloatLayoutHelper method doMeasureAndLayout.

private void doMeasureAndLayout(View view, LayoutManagerHelper helper) {
    if (view == null || helper == null)
        return;
    final VirtualLayoutManager.LayoutParams params = (VirtualLayoutManager.LayoutParams) view.getLayoutParams();
    final boolean layoutInVertical = helper.getOrientation() == VERTICAL;
    if (layoutInVertical) {
        final int widthSpec = helper.getChildMeasureSpec(helper.getContentWidth() - helper.getPaddingLeft() - helper.getPaddingRight(), params.width, !layoutInVertical);
        int heightSpec;
        if (!Float.isNaN(params.mAspectRatio) && params.mAspectRatio > 0) {
            heightSpec = helper.getChildMeasureSpec(helper.getContentHeight() - helper.getPaddingTop() - helper.getPaddingBottom(), (int) (View.MeasureSpec.getSize(widthSpec) / params.mAspectRatio + 0.5f), layoutInVertical);
        } else if (!Float.isNaN(mAspectRatio) && mAspectRatio > 0) {
            heightSpec = helper.getChildMeasureSpec(helper.getContentHeight() - helper.getPaddingTop() - helper.getPaddingBottom(), (int) (View.MeasureSpec.getSize(widthSpec) / mAspectRatio + 0.5f), layoutInVertical);
        } else {
            heightSpec = helper.getChildMeasureSpec(helper.getContentHeight() - helper.getPaddingTop() - helper.getPaddingBottom(), params.height, layoutInVertical);
        }
        // do measurement, measure child without taking off margins, see https://github.com/alibaba/Tangram-Android/issues/81
        helper.measureChild(view, widthSpec, heightSpec);
    } else {
        int widthSpec;
        final int heightSpec = helper.getChildMeasureSpec(helper.getContentHeight() - helper.getPaddingTop() - helper.getPaddingBottom(), params.height, layoutInVertical);
        if (!Float.isNaN(params.mAspectRatio) && params.mAspectRatio > 0) {
            widthSpec = helper.getChildMeasureSpec(helper.getContentWidth() - helper.getPaddingLeft() - helper.getPaddingRight(), (int) (View.MeasureSpec.getSize(heightSpec) * params.mAspectRatio + 0.5f), !layoutInVertical);
        } else if (!Float.isNaN(mAspectRatio) && mAspectRatio > 0) {
            widthSpec = helper.getChildMeasureSpec(helper.getContentWidth() - helper.getPaddingLeft() - helper.getPaddingRight(), (int) (View.MeasureSpec.getSize(heightSpec) * mAspectRatio + 0.5f), !layoutInVertical);
        } else {
            widthSpec = helper.getChildMeasureSpec(helper.getContentWidth() - helper.getPaddingLeft() - helper.getPaddingRight(), params.width, !layoutInVertical);
        }
        // do measurement,  measure child without taking off margins, see https://github.com/alibaba/Tangram-Android/issues/81
        helper.measureChild(view, widthSpec, heightSpec);
    }
    final OrientationHelperEx orientationHelper = helper.getMainOrientationHelper();
    int left, top, right, bottom;
    if (mAlignType == TOP_RIGHT) {
        top = helper.getPaddingTop() + mY + mAdjuster.top;
        right = helper.getContentWidth() - helper.getPaddingRight() - mX - mAdjuster.right;
        left = right - params.leftMargin - params.rightMargin - view.getMeasuredWidth();
        bottom = top + params.topMargin + params.bottomMargin + view.getMeasuredHeight();
    } else if (mAlignType == BOTTOM_LEFT) {
        left = helper.getPaddingLeft() + mX + mAdjuster.left;
        bottom = helper.getContentHeight() - helper.getPaddingBottom() - mY - mAdjuster.bottom;
        right = left + params.leftMargin + params.rightMargin + view.getMeasuredWidth();
        top = bottom - view.getMeasuredHeight() - params.topMargin - params.bottomMargin;
    } else if (mAlignType == BOTTOM_RIGHT) {
        right = helper.getContentWidth() - helper.getPaddingRight() - mX - mAdjuster.right;
        bottom = helper.getContentHeight() - helper.getPaddingBottom() - mY - mAdjuster.bottom;
        left = right - (layoutInVertical ? orientationHelper.getDecoratedMeasurementInOther(view) : orientationHelper.getDecoratedMeasurement(view));
        top = bottom - (layoutInVertical ? orientationHelper.getDecoratedMeasurement(view) : orientationHelper.getDecoratedMeasurementInOther(view));
    } else {
        // TOP_LEFT
        left = helper.getPaddingLeft() + mX + mAdjuster.left;
        top = helper.getPaddingTop() + mY + mAdjuster.top;
        right = left + (layoutInVertical ? orientationHelper.getDecoratedMeasurementInOther(view) : orientationHelper.getDecoratedMeasurement(view));
        bottom = top + (layoutInVertical ? orientationHelper.getDecoratedMeasurement(view) : orientationHelper.getDecoratedMeasurementInOther(view));
    }
    if (left < helper.getPaddingLeft() + mAdjuster.left) {
        left = helper.getPaddingLeft() + mAdjuster.left;
        right = left + (layoutInVertical ? orientationHelper.getDecoratedMeasurementInOther(view) : orientationHelper.getDecoratedMeasurement(view));
    }
    if (right > helper.getContentWidth() - helper.getPaddingRight() - mAdjuster.right) {
        right = helper.getContentWidth() - helper.getPaddingRight() - mAdjuster.right;
        left = right - params.leftMargin - params.rightMargin - view.getMeasuredWidth();
    }
    if (top < helper.getPaddingTop() + mAdjuster.top) {
        top = helper.getPaddingTop() + mAdjuster.top;
        bottom = top + (layoutInVertical ? orientationHelper.getDecoratedMeasurement(view) : orientationHelper.getDecoratedMeasurementInOther(view));
    }
    if (bottom > helper.getContentHeight() - helper.getPaddingBottom() - mAdjuster.bottom) {
        bottom = helper.getContentHeight() - helper.getPaddingBottom() - mAdjuster.bottom;
        top = bottom - (layoutInVertical ? orientationHelper.getDecoratedMeasurement(view) : orientationHelper.getDecoratedMeasurementInOther(view));
    }
    layoutChildWithMargin(view, left, top, right, bottom, helper);
}
Also used : OrientationHelperEx(com.alibaba.android.vlayout.OrientationHelperEx) VirtualLayoutManager(com.alibaba.android.vlayout.VirtualLayoutManager)

Example 8 with OrientationHelperEx

use of com.alibaba.android.vlayout.OrientationHelperEx in project vlayout by alibaba.

the class SingleLayoutHelper 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;
    }
    View view = layoutState.next(recycler);
    if (view == null) {
        result.mFinished = true;
        return;
    }
    helper.addChildView(layoutState, view);
    final VirtualLayoutManager.LayoutParams params = (VirtualLayoutManager.LayoutParams) view.getLayoutParams();
    final boolean layoutInVertical = helper.getOrientation() == VERTICAL;
    int parentWidth = helper.getContentWidth() - helper.getPaddingLeft() - helper.getPaddingRight() - getHorizontalMargin() - getHorizontalPadding();
    int parentHeight = helper.getContentHeight() - helper.getPaddingTop() - helper.getPaddingBottom() - getVerticalMargin() - getVerticalPadding();
    if (!Float.isNaN(mAspectRatio)) {
        if (layoutInVertical) {
            parentHeight = (int) (parentWidth / mAspectRatio + 0.5f);
        } else {
            parentWidth = (int) (parentHeight * mAspectRatio + 0.5f);
        }
    }
    if (layoutInVertical) {
        final int widthSpec = helper.getChildMeasureSpec(parentWidth, Float.isNaN(mAspectRatio) ? params.width : parentWidth, !layoutInVertical && Float.isNaN(mAspectRatio));
        final int heightSpec = helper.getChildMeasureSpec(parentHeight, Float.isNaN(params.mAspectRatio) ? (Float.isNaN(mAspectRatio) ? params.height : parentHeight) : (int) (parentWidth / params.mAspectRatio + 0.5f), layoutInVertical && Float.isNaN(mAspectRatio));
        // do measurement
        helper.measureChildWithMargins(view, widthSpec, heightSpec);
    } else {
        final int widthSpec = helper.getChildMeasureSpec(parentWidth, Float.isNaN(params.mAspectRatio) ? (Float.isNaN(mAspectRatio) ? params.width : parentWidth) : (int) (parentHeight * params.mAspectRatio + 0.5f), !layoutInVertical && Float.isNaN(mAspectRatio));
        final int heightSpec = helper.getChildMeasureSpec(parentHeight, Float.isNaN(mAspectRatio) ? params.height : parentHeight, layoutInVertical && Float.isNaN(mAspectRatio));
        // do measurement
        helper.measureChildWithMargins(view, widthSpec, heightSpec);
    }
    OrientationHelperEx orientationHelper = helper.getMainOrientationHelper();
    result.mConsumed = orientationHelper.getDecoratedMeasurement(view);
    // do layout
    int left, top, right, bottom;
    if (layoutInVertical) {
        int viewWidth = orientationHelper.getDecoratedMeasurementInOther(view);
        int available = parentWidth - viewWidth;
        if (available < 0) {
            available = 0;
        }
        left = mMarginLeft + mPaddingLeft + helper.getPaddingLeft() + available / 2;
        right = helper.getContentWidth() - mMarginRight - mPaddingRight - helper.getPaddingRight() - available / 2;
        if (layoutState.getLayoutDirection() == VirtualLayoutManager.LayoutStateWrapper.LAYOUT_START) {
            bottom = layoutState.getOffset() - mMarginBottom - mPaddingBottom;
            top = bottom - result.mConsumed;
        } else {
            top = layoutState.getOffset() + mMarginTop + mPaddingTop;
            bottom = top + result.mConsumed;
        }
    } else {
        int viewHeight = orientationHelper.getDecoratedMeasurementInOther(view);
        int available = parentHeight - viewHeight;
        if (available < 0) {
            available = 0;
        }
        top = helper.getPaddingTop() + mMarginTop + mPaddingTop + available / 2;
        bottom = helper.getContentHeight() - -mMarginBottom - mPaddingBottom - helper.getPaddingBottom() - available / 2;
        if (layoutState.getLayoutDirection() == VirtualLayoutManager.LayoutStateWrapper.LAYOUT_START) {
            right = layoutState.getOffset() - mMarginRight - mPaddingRight;
            left = right - result.mConsumed;
        } else {
            left = layoutState.getOffset() + mMarginLeft + mPaddingLeft;
            right = left + result.mConsumed;
        }
    }
    if (layoutInVertical) {
        result.mConsumed += getVerticalMargin() + getVerticalPadding();
    } else {
        result.mConsumed += getHorizontalMargin() + getHorizontalPadding();
    }
    layoutChildWithMargin(view, left, top, right, bottom, helper);
}
Also used : OrientationHelperEx(com.alibaba.android.vlayout.OrientationHelperEx) VirtualLayoutManager(com.alibaba.android.vlayout.VirtualLayoutManager) RecyclerView(android.support.v7.widget.RecyclerView) View(android.view.View)

Example 9 with OrientationHelperEx

use of com.alibaba.android.vlayout.OrientationHelperEx in project vlayout by alibaba.

the class StickyLayoutHelper 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;
    }
    // find view in currentPosition
    View view = mFixView;
    if (view == null) {
        view = layoutState.next(recycler);
    } else {
        layoutState.skipCurrentPosition();
    }
    if (view == null) {
        result.mFinished = true;
        return;
    }
    doMeasure(view, helper);
    // do layout
    final boolean layoutInVertical = helper.getOrientation() == VERTICAL;
    final OrientationHelperEx orientationHelper = helper.getMainOrientationHelper();
    result.mConsumed = orientationHelper.getDecoratedMeasurement(view);
    RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams();
    // Do normal measure&layout phase by default
    mDoNormalHandle = true;
    final int remainingSpace = layoutState.getAvailable() - result.mConsumed + layoutState.getExtra();
    int left, top, right, bottom;
    if (helper.getOrientation() == VERTICAL) {
        // not support RTL now
        if (helper.isDoLayoutRTL()) {
            right = helper.getContentWidth() - helper.getPaddingRight() - mMarginRight;
            left = right - orientationHelper.getDecoratedMeasurementInOther(view);
        } else {
            left = helper.getPaddingLeft() + mMarginLeft;
            right = left + orientationHelper.getDecoratedMeasurementInOther(view);
        }
        // whether this layout pass is layout to start or to end
        if (layoutState.getLayoutDirection() == LayoutStateWrapper.LAYOUT_START) {
            // fill start, from bottom to top
            bottom = layoutState.getOffset() - mMarginBottom;
            top = layoutState.getOffset() - result.mConsumed;
        } else {
            // fill end, from top to bottom
            if (mStickyStart) {
                top = layoutState.getOffset() + mMarginTop;
                bottom = layoutState.getOffset() + result.mConsumed;
            } else {
                bottom = orientationHelper.getEndAfterPadding() - mMarginBottom - mOffset - mAdjuster.bottom;
                top = bottom - result.mConsumed;
            }
        }
        if (helper.getReverseLayout() || !mStickyStart) {
            if ((remainingSpace < (mOffset + mAdjuster.bottom) && layoutState.getItemDirection() == LayoutStateWrapper.ITEM_DIRECTION_TAIL) || (bottom > mMarginBottom + mOffset + mAdjuster.bottom)) {
                mDoNormalHandle = false;
                mFixView = view;
                bottom = orientationHelper.getEndAfterPadding() - mMarginBottom - mOffset - mAdjuster.bottom;
                top = bottom - result.mConsumed;
            }
        } else {
            // should not use 0
            if ((remainingSpace < (mOffset + mAdjuster.top) && layoutState.getItemDirection() == LayoutStateWrapper.ITEM_DIRECTION_HEAD) || (top < mMarginTop + mOffset + mAdjuster.top)) {
                mDoNormalHandle = false;
                mFixView = view;
                top = orientationHelper.getStartAfterPadding() + mMarginTop + mOffset + mAdjuster.top;
                bottom = top + result.mConsumed;
            } else {
                if (VirtualLayoutManager.sDebuggable) {
                    Log.i("Sticky", "remainingSpace: " + remainingSpace + "    offset: " + mOffset);
                }
            }
        }
    } else {
        top = helper.getPaddingTop();
        bottom = top + orientationHelper.getDecoratedMeasurementInOther(view) + mMarginTop;
        if (layoutState.getLayoutDirection() == LayoutStateWrapper.LAYOUT_START) {
            right = layoutState.getOffset() - mMarginRight;
            left = layoutState.getOffset() - result.mConsumed;
        } else {
            left = layoutState.getOffset() + mMarginLeft;
            right = layoutState.getOffset() + result.mConsumed;
        }
        if (helper.getReverseLayout() || !mStickyStart) {
            if (remainingSpace < mOffset + mAdjuster.right) {
                mDoNormalHandle = false;
                mFixView = view;
                right = orientationHelper.getEndAfterPadding() - mOffset - mAdjuster.right;
                left = right - result.mConsumed;
            }
        } else {
            if (remainingSpace < mOffset + mAdjuster.left) {
                mDoNormalHandle = false;
                mFixView = view;
                left = orientationHelper.getStartAfterPadding() + mOffset + mAdjuster.left;
                right = result.mConsumed;
            }
        }
    }
    layoutChildWithMargin(view, left, top, right, bottom, helper);
    result.mConsumed += (layoutInVertical ? getVerticalMargin() : getHorizontalMargin());
    if (state.isPreLayout()) {
        mDoNormalHandle = true;
    }
    if (mDoNormalHandle) {
        helper.addChildView(layoutState, view);
        handleStateOnResult(result, view);
    } else {
    // result.mConsumed += mOffset;
    }
}
Also used : OrientationHelperEx(com.alibaba.android.vlayout.OrientationHelperEx) RecyclerView(android.support.v7.widget.RecyclerView) RecyclerView(android.support.v7.widget.RecyclerView) View(android.view.View)

Example 10 with OrientationHelperEx

use of com.alibaba.android.vlayout.OrientationHelperEx in project vlayout by alibaba.

the class StickyLayoutHelper method afterLayout.

@Override
public void afterLayout(RecyclerView.Recycler recycler, RecyclerView.State state, int startPosition, int endPosition, int scrolled, LayoutManagerHelper helper) {
    super.afterLayout(recycler, state, startPosition, endPosition, scrolled, helper);
    // disabled if mPos is negative number
    if (mPos < 0) {
        return;
    }
    final OrientationHelperEx orientationHelper = helper.getMainOrientationHelper();
    // not normal flow,
    if (!mDoNormalHandle && mPos >= startPosition && mPos <= endPosition) {
        fixLayoutStateFromAbnormal2Normal(orientationHelper, recycler, startPosition, endPosition, helper);
    }
    if (mDoNormalHandle || state.isPreLayout()) {
        if (!state.isPreLayout()) {
        // TODO: sticky only support one item now
        }
        if (mFixView != null) {
            helper.removeChildView(mFixView);
        } else {
            // mDoNormalHandle == true && mFixView == null
            return;
        }
    }
    View stickyView = mFixView;
    // Not in normal flow
    if (!mDoNormalHandle && mFixView != null) {
        // if it's not shown on screen
        if (mFixView.getParent() == null) {
            helper.addFixedView(mFixView);
        } else {
            fixLayoutStateInCase1(orientationHelper, recycler, startPosition, endPosition, helper);
        }
    } else {
        fixLayoutStateInCase2(orientationHelper, recycler, startPosition, endPosition, helper);
    }
    if (stickyListener != null) {
        if (isLastStatusSticking && !isStickyNow()) {
            stickyListener.onUnSticky(mPos, stickyView);
            isLastStatusSticking = false;
        } else if (!isLastStatusSticking && isStickyNow()) {
            stickyListener.onSticky(mPos, mFixView);
            isLastStatusSticking = true;
        }
    }
}
Also used : OrientationHelperEx(com.alibaba.android.vlayout.OrientationHelperEx) RecyclerView(android.support.v7.widget.RecyclerView) View(android.view.View)

Aggregations

OrientationHelperEx (com.alibaba.android.vlayout.OrientationHelperEx)32 RecyclerView (android.support.v7.widget.RecyclerView)26 View (android.view.View)26 VirtualLayoutManager (com.alibaba.android.vlayout.VirtualLayoutManager)18 LayoutParams (com.alibaba.android.vlayout.VirtualLayoutManager.LayoutParams)10 LayoutParams (android.support.v7.widget.RecyclerView.LayoutParams)5 Rect (android.graphics.Rect)2 ArrayMap (android.support.v4.util.ArrayMap)1 SimpleArrayMap (android.support.v4.util.SimpleArrayMap)1 ViewGroup (android.view.ViewGroup)1 LayoutParams (android.view.ViewGroup.LayoutParams)1 TextView (android.widget.TextView)1 LayoutHelper (com.alibaba.android.vlayout.LayoutHelper)1 Range (com.alibaba.android.vlayout.Range)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1