Example usage for android.view View isFocusable

List of usage examples for android.view View isFocusable

Introduction

In this page you can find the example usage for android.view View isFocusable.

Prototype

@ViewDebug.ExportedProperty(category = "focus")
public final boolean isFocusable() 

Source Link

Document

Returns whether this View is currently able to take focus.

Usage

From source file:com.kozhevin.example.carousel.CarouselLayoutManager.java

/**
 * The magic functions :). Fills the given layout, defined by the renderState. This is fairly
 * independent from the rest of the {@link android.support.v7.widget.LinearLayoutManager} and with little change, can be made publicly available
 * as a helper class./*from  w ww .jav  a  2  s .c  o m*/
 *
 * @param recycler
 *            Current recycler that is attached to RecyclerView
 * @param renderState
 *            Configuration on how we should fill out the available space.
 * @param state
 *            Context passed by the RecyclerView to control scroll steps.
 * @param stopOnFocusable
 *            If true, filling stops in the first focusable new child
 * @return Number of pixels that it added. Useful for scoll functions.
 */
private int fill(RecyclerView.Recycler recycler, RenderState renderState, RecyclerView.State state,
        boolean stopOnFocusable) {
    // max offset we should set is mFastScroll + available
    final int start = renderState.mAvailable;
    if (renderState.mScrollingOffset != RenderState.SCOLLING_OFFSET_NaN) {
        // TODO ugly bug fix. should not happen
        if (renderState.mAvailable < 0) {
            renderState.mScrollingOffset += renderState.mAvailable;
        }
        recycleByRenderState(recycler, renderState);
    }
    int remainingSpace = renderState.mAvailable + renderState.mExtra;
    while (remainingSpace > 0 && renderState.hasMore(state)) {
        View view = renderState.next(recycler);
        if (view == null) {
            if (IS_DEBUG && renderState.mScrapList == null) {
                throw new RuntimeException("received null view when unexpected");
            }
            // if we are laying out views in scrap, this may return null which means there is
            // no more items to layout.
            break;
        }
        RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams();
        if (!params.isItemRemoved() && mRenderState.mScrapList == null) {
            if (mShouldReverseLayout == (renderState.mLayoutDirection == RenderState.LAYOUT_START)) {
                addView(view);
            } else {
                addView(view, 0);
            }
        }
        measureChildWithMargins(view, 0, 0);
        int consumed = 0; //mOrientationHelper.getDecoratedMeasurement(view);
        if (mOrientation == VERTICAL) {
            consumed = (int) ((getWidth() - getPaddingLeft() - getPaddingRight()) * DEFAULT_WIDTH_VIEW_RATIO);
        } else {
            consumed = (int) ((getWidth() - getPaddingTop() - getPaddingBottom()) * DEFAULT_WIDTH_VIEW_RATIO);
        }

        int left, top, right, bottom;
        if (mOrientation == VERTICAL) {
            if (isLayoutRTL()) {
                right = getWidth() - getPaddingRight();
                left = right - mOrientationHelper.getDecoratedMeasurementInOther(view);
            } else {
                left = getPaddingLeft();
                right = left + mOrientationHelper.getDecoratedMeasurementInOther(view);
            }
            if (renderState.mLayoutDirection == RenderState.LAYOUT_START) {
                bottom = renderState.mOffset;
                top = renderState.mOffset - consumed;
            } else {
                top = renderState.mOffset;
                bottom = renderState.mOffset + consumed;
            }
        } else {
            top = getPaddingTop();
            bottom = top + mOrientationHelper.getDecoratedMeasurementInOther(view);

            if (renderState.mLayoutDirection == RenderState.LAYOUT_START) {
                right = renderState.mOffset;
                left = renderState.mOffset - consumed;
            } else {
                left = renderState.mOffset;
                right = renderState.mOffset + consumed;
            }
        }
        // We calculate everything with View's bounding box (which includes decor and margins)
        // To calculate correct layout position, we subtract margins.
        layoutDecorated(view, left + params.leftMargin, top + params.topMargin, right - params.rightMargin,
                bottom - params.bottomMargin);
        if (IS_DEBUG) {
            Log.d(TAG,
                    "laid out child at position " + getPosition(view) + ", with l:" + (left + params.leftMargin)
                            + ", t:" + (top + params.topMargin) + ", r:" + (right - params.rightMargin) + ", b:"
                            + (bottom - params.bottomMargin));
        }
        renderState.mOffset += consumed * renderState.mLayoutDirection;

        if (!params.isItemRemoved()) {
            renderState.mAvailable -= consumed;
            // we keep a separate remaining space because mAvailable is important for recycling
            remainingSpace -= consumed;
        }

        if (renderState.mScrollingOffset != RenderState.SCOLLING_OFFSET_NaN) {
            renderState.mScrollingOffset += consumed;
            if (renderState.mAvailable < 0) {
                renderState.mScrollingOffset += renderState.mAvailable;
            }
            recycleByRenderState(recycler, renderState);
        }
        if (stopOnFocusable && view.isFocusable()) {
            break;
        }

        if (state != null && state.getTargetScrollPosition() == getPosition(view)) {
            break;
        }
    }
    makeScaleView(renderState);

    updatePositionForInsert();

    if (IS_DEBUG) {
        validateChildOrder();
    }
    return start - renderState.mAvailable;
}

From source file:cn.ismartv.tvrecyclerview.widget.GridLayoutManager.java

@Override
void layoutChunk(RecyclerView.Recycler recycler, RecyclerView.State state, LayoutState layoutState,
        LayoutChunkResult result) {/*w w  w  .j  a  v a 2 s.  com*/
    final int otherDirSpecMode = mOrientationHelper.getModeInOther();
    final boolean flexibleInOtherDir = otherDirSpecMode != View.MeasureSpec.EXACTLY;
    final int currentOtherDirSize = getChildCount() > 0 ? mCachedBorders[mSpanCount] : 0;
    // if grid layout's dimensions are not specified, let the new row change the measurements
    // This is not perfect since we not covering all rows but still solves an important case
    // where they may have a header row which should be laid out according to children.
    if (flexibleInOtherDir) {
        updateMeasurements(); //  reset measurements
    }
    final boolean layingOutInPrimaryDirection = layoutState.mItemDirection == LayoutState.ITEM_DIRECTION_TAIL;
    int count = 0;
    int consumedSpanCount = 0;
    int remainingSpan = mSpanCount;
    if (!layingOutInPrimaryDirection) {
        int itemSpanIndex = getSpanIndex(recycler, state, layoutState.mCurrentPosition);
        int itemSpanSize = getSpanSize(recycler, state, layoutState.mCurrentPosition);
        remainingSpan = itemSpanIndex + itemSpanSize;
    }
    while (count < mSpanCount && layoutState.hasMore(state) && remainingSpan > 0) {
        int pos = layoutState.mCurrentPosition;
        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) {
            break; // item did not fit into this row or column
        }
        View view = layoutState.next(recycler);
        if (view == null) {
            break;
        }
        consumedSpanCount += spanSize;
        mSet[count] = view;
        count++;
    }

    if (count == 0) {
        result.mFinished = true;
        return;
    }

    int maxSize = 0;
    float maxSizeInOther = 0; // use a float to get size per span

    // we should assign spans before item decor offsets are calculated
    assignSpans(recycler, state, count, consumedSpanCount, layingOutInPrimaryDirection);
    for (int i = 0; i < count; i++) {
        View view = mSet[i];
        if (layoutState.mScrapList == null) {
            if (layingOutInPrimaryDirection) {
                addView(view);
            } else {
                addView(view, 0);
            }
        } else {
            if (layingOutInPrimaryDirection) {
                addDisappearingView(view);
            } else {
                addDisappearingView(view, 0);
            }
        }
        calculateItemDecorationsForChild(view, mDecorInsets);

        measureChild(view, otherDirSpecMode, false);
        final int size = mOrientationHelper.getDecoratedMeasurement(view);
        if (size > maxSize) {
            maxSize = size;
        }
        final LayoutParams lp = (LayoutParams) view.getLayoutParams();
        final float otherSize = 1f * mOrientationHelper.getDecoratedMeasurementInOther(view) / lp.mSpanSize;
        if (otherSize > maxSizeInOther) {
            maxSizeInOther = otherSize;
        }
    }
    if (flexibleInOtherDir) {
        // re-distribute columns
        guessMeasurement(maxSizeInOther, currentOtherDirSize);
        // now we should re-measure any item that was match parent.
        maxSize = 0;
        for (int i = 0; i < count; i++) {
            View view = mSet[i];
            measureChild(view, View.MeasureSpec.EXACTLY, true);
            final int size = mOrientationHelper.getDecoratedMeasurement(view);
            if (size > maxSize) {
                maxSize = size;
            }
        }
    }

    // Views that did not measure the maxSize has to be re-measured
    // We will stop doing this once we introduce Gravity in the GLM layout params
    for (int i = 0; i < count; i++) {
        final View view = mSet[i];
        if (mOrientationHelper.getDecoratedMeasurement(view) != maxSize) {
            final LayoutParams lp = (LayoutParams) view.getLayoutParams();
            final Rect decorInsets = lp.mDecorInsets;
            final int verticalInsets = decorInsets.top + decorInsets.bottom + lp.topMargin + lp.bottomMargin;
            final int horizontalInsets = decorInsets.left + decorInsets.right + lp.leftMargin + lp.rightMargin;
            final int totalSpaceInOther = getSpaceForSpanRange(lp.mSpanIndex, lp.mSpanSize);
            final int wSpec;
            final int hSpec;
            if (mOrientation == VERTICAL) {
                wSpec = getChildMeasureSpec(totalSpaceInOther, View.MeasureSpec.EXACTLY, horizontalInsets,
                        lp.width, false);
                hSpec = View.MeasureSpec.makeMeasureSpec(maxSize - verticalInsets, View.MeasureSpec.EXACTLY);
            } else {
                wSpec = View.MeasureSpec.makeMeasureSpec(maxSize - horizontalInsets, View.MeasureSpec.EXACTLY);
                hSpec = getChildMeasureSpec(totalSpaceInOther, View.MeasureSpec.EXACTLY, verticalInsets,
                        lp.height, false);
            }
            measureChildWithDecorationsAndMargin(view, wSpec, hSpec, true);
        }
    }

    result.mConsumed = maxSize;

    int left = 0, right = 0, top = 0, bottom = 0;
    if (mOrientation == VERTICAL) {
        if (layoutState.mLayoutDirection == LayoutState.LAYOUT_START) {
            bottom = layoutState.mOffset;
            top = bottom - maxSize;
        } else {
            top = layoutState.mOffset;
            bottom = top + maxSize;
        }
    } else {
        if (layoutState.mLayoutDirection == LayoutState.LAYOUT_START) {
            right = layoutState.mOffset;
            left = right - maxSize;
        } else {
            left = layoutState.mOffset;
            right = left + maxSize;
        }
    }
    for (int i = 0; i < count; i++) {
        View view = mSet[i];
        LayoutParams params = (LayoutParams) view.getLayoutParams();
        if (mOrientation == VERTICAL) {
            if (isLayoutRTL()) {
                right = getPaddingLeft() + mCachedBorders[mSpanCount - params.mSpanIndex];
                left = right - mOrientationHelper.getDecoratedMeasurementInOther(view);
            } else {
                left = getPaddingLeft() + mCachedBorders[params.mSpanIndex];
                right = left + mOrientationHelper.getDecoratedMeasurementInOther(view);
            }
        } else {
            top = getPaddingTop() + mCachedBorders[params.mSpanIndex];
            bottom = top + mOrientationHelper.getDecoratedMeasurementInOther(view);
        }
        // We calculate everything with View's bounding box (which includes decor and margins)
        // To calculate correct layout position, we subtract margins.
        layoutDecoratedWithMargins(view, left, top, right, bottom);
        if (DEBUG) {
            Log.d(TAG,
                    "laid out child at position " + getPosition(view) + ", with l:" + (left + params.leftMargin)
                            + ", t:" + (top + params.topMargin) + ", r:" + (right - params.rightMargin) + ", b:"
                            + (bottom - params.bottomMargin) + ", span:" + params.mSpanIndex + ", spanSize:"
                            + params.mSpanSize);
        }
        // Consume the available space if the view is not removed OR changed
        if (params.isItemRemoved() || params.isItemChanged()) {
            result.mIgnoreConsumed = true;
        }
        result.mFocusable |= view.isFocusable();
    }
    Arrays.fill(mSet, null);
}

From source file:cn.ismartv.tvrecyclerview.widget.StaggeredGridLayoutManager.java

private int fill(RecyclerView.Recycler recycler, LayoutState layoutState, RecyclerView.State state) {
    mRemainingSpans.set(0, mSpanCount, true);
    // The target position we are trying to reach.
    final int targetLine;

    // Line of the furthest row.
    if (mLayoutState.mInfinite) {
        if (layoutState.mLayoutDirection == LAYOUT_END) {
            targetLine = Integer.MAX_VALUE;
        } else { // LAYOUT_START
            targetLine = Integer.MIN_VALUE;
        }//  w  w  w  .  j a  va  2s .  c o m
    } else {
        if (layoutState.mLayoutDirection == LAYOUT_END) {
            targetLine = layoutState.mEndLine + layoutState.mAvailable;
        } else { // LAYOUT_START
            targetLine = layoutState.mStartLine - layoutState.mAvailable;
        }
    }

    updateAllRemainingSpans(layoutState.mLayoutDirection, targetLine);
    if (DEBUG) {
        Log.d(TAG, "FILLING targetLine: " + targetLine + "," + "remaining spans:" + mRemainingSpans
                + ", state: " + layoutState);
    }

    // the default coordinate to add new view.
    final int defaultNewViewLine = mShouldReverseLayout ? mPrimaryOrientation.getEndAfterPadding()
            : mPrimaryOrientation.getStartAfterPadding();
    boolean added = false;
    while (layoutState.hasMore(state) && (mLayoutState.mInfinite || !mRemainingSpans.isEmpty())) {
        View view = layoutState.next(recycler);
        LayoutParams lp = ((LayoutParams) view.getLayoutParams());
        final int position = lp.getViewLayoutPosition();
        final int spanIndex = mLazySpanLookup.getSpan(position);
        Span currentSpan;
        final boolean assignSpan = spanIndex == LayoutParams.INVALID_SPAN_ID;
        if (assignSpan) {
            currentSpan = lp.mFullSpan ? mSpans[0] : getNextSpan(layoutState);
            mLazySpanLookup.setSpan(position, currentSpan);
            if (DEBUG) {
                Log.d(TAG, "assigned " + currentSpan.mIndex + " for " + position);
            }
        } else {
            if (DEBUG) {
                Log.d(TAG, "using " + spanIndex + " for pos " + position);
            }
            currentSpan = mSpans[spanIndex];
        }
        // assign span before measuring so that item decorators can get updated span index
        lp.mSpan = currentSpan;
        if (layoutState.mLayoutDirection == LAYOUT_END) {
            addView(view);
        } else {
            addView(view, 0);
        }
        measureChildWithDecorationsAndMargin(view, lp, false);

        final int start;
        final int end;
        if (layoutState.mLayoutDirection == LAYOUT_END) {
            start = lp.mFullSpan ? getMaxEnd(defaultNewViewLine) : currentSpan.getEndLine(defaultNewViewLine);
            end = start + mPrimaryOrientation.getDecoratedMeasurement(view);
            if (assignSpan && lp.mFullSpan) {
                LazySpanLookup.FullSpanItem fullSpanItem;
                fullSpanItem = createFullSpanItemFromEnd(start);
                fullSpanItem.mGapDir = LAYOUT_START;
                fullSpanItem.mPosition = position;
                mLazySpanLookup.addFullSpanItem(fullSpanItem);
            }
        } else {
            end = lp.mFullSpan ? getMinStart(defaultNewViewLine) : currentSpan.getStartLine(defaultNewViewLine);
            start = end - mPrimaryOrientation.getDecoratedMeasurement(view);
            if (assignSpan && lp.mFullSpan) {
                LazySpanLookup.FullSpanItem fullSpanItem;
                fullSpanItem = createFullSpanItemFromStart(end);
                fullSpanItem.mGapDir = LAYOUT_END;
                fullSpanItem.mPosition = position;
                mLazySpanLookup.addFullSpanItem(fullSpanItem);
            }
        }

        // check if this item may create gaps in the future
        if (lp.mFullSpan && layoutState.mItemDirection == ITEM_DIRECTION_HEAD) {
            if (assignSpan) {
                mLaidOutInvalidFullSpan = true;
            } else {
                final boolean hasInvalidGap;
                if (layoutState.mLayoutDirection == LAYOUT_END) {
                    hasInvalidGap = !areAllEndsEqual();
                } else { // layoutState.mLayoutDirection == LAYOUT_START
                    hasInvalidGap = !areAllStartsEqual();
                }
                if (hasInvalidGap) {
                    final LazySpanLookup.FullSpanItem fullSpanItem = mLazySpanLookup.getFullSpanItem(position);
                    if (fullSpanItem != null) {
                        fullSpanItem.mHasUnwantedGapAfter = true;
                    }
                    mLaidOutInvalidFullSpan = true;
                }
            }
        }
        attachViewToSpans(view, lp, layoutState);
        final int otherStart;
        final int otherEnd;
        if (isLayoutRTL() && mOrientation == VERTICAL) {
            otherEnd = lp.mFullSpan ? mSecondaryOrientation.getEndAfterPadding()
                    : mSecondaryOrientation.getEndAfterPadding()
                            - (mSpanCount - 1 - currentSpan.mIndex) * mSizePerSpan;
            otherStart = otherEnd - mSecondaryOrientation.getDecoratedMeasurement(view);
        } else {
            otherStart = lp.mFullSpan ? mSecondaryOrientation.getStartAfterPadding()
                    : currentSpan.mIndex * mSizePerSpan + mSecondaryOrientation.getStartAfterPadding();
            otherEnd = otherStart + mSecondaryOrientation.getDecoratedMeasurement(view);
        }

        if (mOrientation == VERTICAL) {
            layoutDecoratedWithMargins(view, otherStart, start, otherEnd, end);
        } else {
            layoutDecoratedWithMargins(view, start, otherStart, end, otherEnd);
        }

        if (lp.mFullSpan) {
            updateAllRemainingSpans(mLayoutState.mLayoutDirection, targetLine);
        } else {
            updateRemainingSpans(currentSpan, mLayoutState.mLayoutDirection, targetLine);
        }
        recycle(recycler, mLayoutState);
        if (mLayoutState.mStopInFocusable && view.isFocusable()) {
            if (lp.mFullSpan) {
                mRemainingSpans.clear();
            } else {
                mRemainingSpans.set(currentSpan.mIndex, false);
            }
        }
        added = true;
    }
    if (!added) {
        recycle(recycler, mLayoutState);
    }
    final int diff;
    if (mLayoutState.mLayoutDirection == LAYOUT_START) {
        final int minStart = getMinStart(mPrimaryOrientation.getStartAfterPadding());
        diff = mPrimaryOrientation.getStartAfterPadding() - minStart;
    } else {
        final int maxEnd = getMaxEnd(mPrimaryOrientation.getEndAfterPadding());
        diff = maxEnd - mPrimaryOrientation.getEndAfterPadding();
    }
    return diff > 0 ? Math.min(layoutState.mAvailable, diff) : 0;
}

From source file:ir.besteveryeverapp.telegram.support.widget.StaggeredGridLayoutManager.java

private int fill(RecyclerView.Recycler recycler, LayoutState layoutState, RecyclerView.State state) {
    mRemainingSpans.set(0, mSpanCount, true);
    // The target position we are trying to reach.
    final int targetLine;

    // Line of the furthest row.
    if (mLayoutState.mInfinite) {
        if (layoutState.mLayoutDirection == LayoutState.LAYOUT_END) {
            targetLine = Integer.MAX_VALUE;
        } else { // LAYOUT_START
            targetLine = Integer.MIN_VALUE;
        }//from w  w  w . j ava  2 s.com
    } else {
        if (layoutState.mLayoutDirection == LayoutState.LAYOUT_END) {
            targetLine = layoutState.mEndLine + layoutState.mAvailable;
        } else { // LAYOUT_START
            targetLine = layoutState.mStartLine - layoutState.mAvailable;
        }
    }

    updateAllRemainingSpans(layoutState.mLayoutDirection, targetLine);
    if (DEBUG) {
        Log.d(TAG, "FILLING targetLine: " + targetLine + "," + "remaining spans:" + mRemainingSpans
                + ", state: " + layoutState);
    }

    // the default coordinate to add new view.
    final int defaultNewViewLine = mShouldReverseLayout ? mPrimaryOrientation.getEndAfterPadding()
            : mPrimaryOrientation.getStartAfterPadding();
    boolean added = false;
    while (layoutState.hasMore(state) && (mLayoutState.mInfinite || !mRemainingSpans.isEmpty())) {
        View view = layoutState.next(recycler);
        LayoutParams lp = ((LayoutParams) view.getLayoutParams());
        final int position = lp.getViewLayoutPosition();
        final int spanIndex = mLazySpanLookup.getSpan(position);
        Span currentSpan;
        final boolean assignSpan = spanIndex == LayoutParams.INVALID_SPAN_ID;
        if (assignSpan) {
            currentSpan = lp.mFullSpan ? mSpans[0] : getNextSpan(layoutState);
            mLazySpanLookup.setSpan(position, currentSpan);
            if (DEBUG) {
                Log.d(TAG, "assigned " + currentSpan.mIndex + " for " + position);
            }
        } else {
            if (DEBUG) {
                Log.d(TAG, "using " + spanIndex + " for pos " + position);
            }
            currentSpan = mSpans[spanIndex];
        }
        // assign span before measuring so that item decorators can get updated span index
        lp.mSpan = currentSpan;
        if (layoutState.mLayoutDirection == LayoutState.LAYOUT_END) {
            addView(view);
        } else {
            addView(view, 0);
        }
        measureChildWithDecorationsAndMargin(view, lp, false);

        final int start;
        final int end;
        if (layoutState.mLayoutDirection == LayoutState.LAYOUT_END) {
            start = lp.mFullSpan ? getMaxEnd(defaultNewViewLine) : currentSpan.getEndLine(defaultNewViewLine);
            end = start + mPrimaryOrientation.getDecoratedMeasurement(view);
            if (assignSpan && lp.mFullSpan) {
                LazySpanLookup.FullSpanItem fullSpanItem;
                fullSpanItem = createFullSpanItemFromEnd(start);
                fullSpanItem.mGapDir = LayoutState.LAYOUT_START;
                fullSpanItem.mPosition = position;
                mLazySpanLookup.addFullSpanItem(fullSpanItem);
            }
        } else {
            end = lp.mFullSpan ? getMinStart(defaultNewViewLine) : currentSpan.getStartLine(defaultNewViewLine);
            start = end - mPrimaryOrientation.getDecoratedMeasurement(view);
            if (assignSpan && lp.mFullSpan) {
                LazySpanLookup.FullSpanItem fullSpanItem;
                fullSpanItem = createFullSpanItemFromStart(end);
                fullSpanItem.mGapDir = LayoutState.LAYOUT_END;
                fullSpanItem.mPosition = position;
                mLazySpanLookup.addFullSpanItem(fullSpanItem);
            }
        }

        // check if this item may create gaps in the future
        if (lp.mFullSpan && layoutState.mItemDirection == LayoutState.ITEM_DIRECTION_HEAD) {
            if (assignSpan) {
                mLaidOutInvalidFullSpan = true;
            } else {
                final boolean hasInvalidGap;
                if (layoutState.mLayoutDirection == LayoutState.LAYOUT_END) {
                    hasInvalidGap = !areAllEndsEqual();
                } else { // layoutState.mLayoutDirection == LAYOUT_START
                    hasInvalidGap = !areAllStartsEqual();
                }
                if (hasInvalidGap) {
                    final LazySpanLookup.FullSpanItem fullSpanItem = mLazySpanLookup.getFullSpanItem(position);
                    if (fullSpanItem != null) {
                        fullSpanItem.mHasUnwantedGapAfter = true;
                    }
                    mLaidOutInvalidFullSpan = true;
                }
            }
        }
        attachViewToSpans(view, lp, layoutState);
        final int otherStart;
        final int otherEnd;
        if (isLayoutRTL() && mOrientation == VERTICAL) {
            otherEnd = lp.mFullSpan ? mSecondaryOrientation.getEndAfterPadding()
                    : mSecondaryOrientation.getEndAfterPadding()
                            - (mSpanCount - 1 - currentSpan.mIndex) * mSizePerSpan;
            otherStart = otherEnd - mSecondaryOrientation.getDecoratedMeasurement(view);
        } else {
            otherStart = lp.mFullSpan ? mSecondaryOrientation.getStartAfterPadding()
                    : currentSpan.mIndex * mSizePerSpan + mSecondaryOrientation.getStartAfterPadding();
            otherEnd = otherStart + mSecondaryOrientation.getDecoratedMeasurement(view);
        }

        if (mOrientation == VERTICAL) {
            layoutDecoratedWithMargins(view, otherStart, start, otherEnd, end);
        } else {
            layoutDecoratedWithMargins(view, start, otherStart, end, otherEnd);
        }

        if (lp.mFullSpan) {
            updateAllRemainingSpans(mLayoutState.mLayoutDirection, targetLine);
        } else {
            updateRemainingSpans(currentSpan, mLayoutState.mLayoutDirection, targetLine);
        }
        recycle(recycler, mLayoutState);
        if (mLayoutState.mStopInFocusable && view.isFocusable()) {
            if (lp.mFullSpan) {
                mRemainingSpans.clear();
            } else {
                mRemainingSpans.set(currentSpan.mIndex, false);
            }
        }
        added = true;
    }
    if (!added) {
        recycle(recycler, mLayoutState);
    }
    final int diff;
    if (mLayoutState.mLayoutDirection == LayoutState.LAYOUT_START) {
        final int minStart = getMinStart(mPrimaryOrientation.getStartAfterPadding());
        diff = mPrimaryOrientation.getStartAfterPadding() - minStart;
    } else {
        final int maxEnd = getMaxEnd(mPrimaryOrientation.getEndAfterPadding());
        diff = maxEnd - mPrimaryOrientation.getEndAfterPadding();
    }
    return diff > 0 ? Math.min(layoutState.mAvailable, diff) : 0;
}

From source file:com.b44t.messenger.support.widget.GridLayoutManager.java

@Override
void layoutChunk(RecyclerView.Recycler recycler, RecyclerView.State state, LayoutState layoutState,
        LayoutChunkResult result) {//www . j  a v a  2  s.co m
    final int otherDirSpecMode = mOrientationHelper.getModeInOther();
    final boolean flexibleInOtherDir = otherDirSpecMode != View.MeasureSpec.EXACTLY;
    final int currentOtherDirSize = getChildCount() > 0 ? mCachedBorders[mSpanCount] : 0;
    // if grid layout's dimensions are not specified, let the new row change the measurements
    // This is not perfect since we not covering all rows but still solves an important case
    // where they may have a header row which should be laid out according to children.
    if (flexibleInOtherDir) {
        updateMeasurements(); //  reset measurements
    }
    final boolean layingOutInPrimaryDirection = layoutState.mItemDirection == LayoutState.ITEM_DIRECTION_TAIL;
    int count = 0;
    int consumedSpanCount = 0;
    int remainingSpan = mSpanCount;
    if (!layingOutInPrimaryDirection) {
        int itemSpanIndex = getSpanIndex(recycler, state, layoutState.mCurrentPosition);
        int itemSpanSize = getSpanSize(recycler, state, layoutState.mCurrentPosition);
        remainingSpan = itemSpanIndex + itemSpanSize;
    }
    while (count < mSpanCount && layoutState.hasMore(state) && remainingSpan > 0) {
        int pos = layoutState.mCurrentPosition;
        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) {
            break; // item did not fit into this row or column
        }
        View view = layoutState.next(recycler);
        if (view == null) {
            break;
        }
        consumedSpanCount += spanSize;
        mSet[count] = view;
        count++;
    }

    if (count == 0) {
        result.mFinished = true;
        return;
    }

    int maxSize = 0;
    float maxSizeInOther = 0; // use a float to get size per span

    // we should assign spans before item decor offsets are calculated
    assignSpans(recycler, state, count, consumedSpanCount, layingOutInPrimaryDirection);
    for (int i = 0; i < count; i++) {
        View view = mSet[i];
        if (layoutState.mScrapList == null) {
            if (layingOutInPrimaryDirection) {
                addView(view);
            } else {
                addView(view, 0);
            }
        } else {
            if (layingOutInPrimaryDirection) {
                addDisappearingView(view);
            } else {
                addDisappearingView(view, 0);
            }
        }

        final LayoutParams lp = (LayoutParams) view.getLayoutParams();
        final int spec = getChildMeasureSpec(
                mCachedBorders[lp.mSpanIndex + lp.mSpanSize] - mCachedBorders[lp.mSpanIndex], otherDirSpecMode,
                0, mOrientation == HORIZONTAL ? lp.height : lp.width, false);
        final int mainSpec = getChildMeasureSpec(mOrientationHelper.getTotalSpace(),
                mOrientationHelper.getMode(), 0, mOrientation == VERTICAL ? lp.height : lp.width, true);
        // Unless the child has MATCH_PARENT, measure it from its specs before adding insets.
        if (mOrientation == VERTICAL) {
            @SuppressWarnings("deprecation")
            final boolean applyInsets = lp.height == ViewGroup.LayoutParams.FILL_PARENT;
            measureChildWithDecorationsAndMargin(view, spec, mainSpec, applyInsets, false);
        } else {
            //noinspection deprecation
            final boolean applyInsets = lp.width == ViewGroup.LayoutParams.FILL_PARENT;
            measureChildWithDecorationsAndMargin(view, mainSpec, spec, applyInsets, false);
        }
        final int size = mOrientationHelper.getDecoratedMeasurement(view);
        if (size > maxSize) {
            maxSize = size;
        }
        final float otherSize = 1f * mOrientationHelper.getDecoratedMeasurementInOther(view) / lp.mSpanSize;
        if (otherSize > maxSizeInOther) {
            maxSizeInOther = otherSize;
        }
    }
    if (flexibleInOtherDir) {
        // re-distribute columns
        guessMeasurement(maxSizeInOther, currentOtherDirSize);
        // now we should re-measure any item that was match parent.
        maxSize = 0;
        for (int i = 0; i < count; i++) {
            View view = mSet[i];
            final LayoutParams lp = (LayoutParams) view.getLayoutParams();
            final int spec = getChildMeasureSpec(
                    mCachedBorders[lp.mSpanIndex + lp.mSpanSize] - mCachedBorders[lp.mSpanIndex],
                    View.MeasureSpec.EXACTLY, 0, mOrientation == HORIZONTAL ? lp.height : lp.width, false);
            final int mainSpec = getChildMeasureSpec(mOrientationHelper.getTotalSpace(),
                    mOrientationHelper.getMode(), 0, mOrientation == VERTICAL ? lp.height : lp.width, true);
            if (mOrientation == VERTICAL) {
                measureChildWithDecorationsAndMargin(view, spec, mainSpec, false, true);
            } else {
                measureChildWithDecorationsAndMargin(view, mainSpec, spec, false, true);
            }
            final int size = mOrientationHelper.getDecoratedMeasurement(view);
            if (size > maxSize) {
                maxSize = size;
            }
        }
    }
    // Views that did not measure the maxSize has to be re-measured
    // We will stop doing this once we introduce Gravity in the GLM layout params
    final int maxMeasureSpec = View.MeasureSpec.makeMeasureSpec(maxSize, View.MeasureSpec.EXACTLY);
    for (int i = 0; i < count; i++) {
        final View view = mSet[i];
        if (mOrientationHelper.getDecoratedMeasurement(view) != maxSize) {
            final LayoutParams lp = (LayoutParams) view.getLayoutParams();
            final int spec = getChildMeasureSpec(
                    mCachedBorders[lp.mSpanIndex + lp.mSpanSize] - mCachedBorders[lp.mSpanIndex],
                    View.MeasureSpec.EXACTLY, 0, mOrientation == HORIZONTAL ? lp.height : lp.width, false);
            if (mOrientation == VERTICAL) {
                measureChildWithDecorationsAndMargin(view, spec, maxMeasureSpec, true, true);
            } else {
                measureChildWithDecorationsAndMargin(view, maxMeasureSpec, spec, true, true);
            }
        }
    }

    result.mConsumed = maxSize;

    int left = 0, right = 0, top = 0, bottom = 0;
    if (mOrientation == VERTICAL) {
        if (layoutState.mLayoutDirection == LayoutState.LAYOUT_START) {
            bottom = layoutState.mOffset;
            top = bottom - maxSize;
        } else {
            top = layoutState.mOffset;
            bottom = top + maxSize;
        }
    } else {
        if (layoutState.mLayoutDirection == LayoutState.LAYOUT_START) {
            right = layoutState.mOffset;
            left = right - maxSize;
        } else {
            left = layoutState.mOffset;
            right = left + maxSize;
        }
    }
    for (int i = 0; i < count; i++) {
        View view = mSet[i];
        LayoutParams params = (LayoutParams) view.getLayoutParams();
        if (mOrientation == VERTICAL) {
            if (isLayoutRTL()) {
                right = getPaddingLeft() + mCachedBorders[params.mSpanIndex + params.mSpanSize];
                left = right - mOrientationHelper.getDecoratedMeasurementInOther(view);
            } else {
                left = getPaddingLeft() + mCachedBorders[params.mSpanIndex];
                right = left + mOrientationHelper.getDecoratedMeasurementInOther(view);
            }
        } else {
            top = getPaddingTop() + mCachedBorders[params.mSpanIndex];
            bottom = top + mOrientationHelper.getDecoratedMeasurementInOther(view);
        }
        // We calculate everything with View's bounding box (which includes decor and margins)
        // To calculate correct layout position, we subtract margins.
        layoutDecorated(view, left + params.leftMargin, top + params.topMargin, right - params.rightMargin,
                bottom - params.bottomMargin);
        if (DEBUG) {
            Log.d(TAG,
                    "laid out child at position " + getPosition(view) + ", with l:" + (left + params.leftMargin)
                            + ", t:" + (top + params.topMargin) + ", r:" + (right - params.rightMargin) + ", b:"
                            + (bottom - params.bottomMargin) + ", span:" + params.mSpanIndex + ", spanSize:"
                            + params.mSpanSize);
        }
        // Consume the available space if the view is not removed OR changed
        if (params.isItemRemoved() || params.isItemChanged()) {
            result.mIgnoreConsumed = true;
        }
        result.mFocusable |= view.isFocusable();
    }
    Arrays.fill(mSet, null);
}

From source file:cn.ismartv.tvrecyclerview.widget.RecyclerView.java

private void recoverFocusFromState() {
    if (!mPreserveFocusAfterLayout || mAdapter == null || !hasFocus()) {
        return;//from www .  j  ava  2 s  .co m
    }
    // only recover focus if RV itself has the focus or the focused view is hidden
    if (!isFocused()) {
        final View focusedChild = getFocusedChild();
        if (focusedChild == null || !mChildHelper.isHidden(focusedChild)) {
            return;
        }
    }
    ViewHolder focusTarget = null;
    if (mState.mFocusedItemPosition != NO_POSITION) {
        focusTarget = findViewHolderForAdapterPosition(mState.mFocusedItemPosition);
    }
    if (focusTarget == null && mState.mFocusedItemId != NO_ID && mAdapter.hasStableIds()) {
        focusTarget = findViewHolderForItemId(mState.mFocusedItemId);
    }
    if (focusTarget == null || focusTarget.itemView.hasFocus() || !focusTarget.itemView.hasFocusable()) {
        return;
    }
    // looks like the focused item has been replaced with another view that represents the
    // same item in the adapter. Request focus on that.
    View viewToFocus = focusTarget.itemView;
    if (mState.mFocusedSubChildId != NO_ID) {
        View child = focusTarget.itemView.findViewById(mState.mFocusedSubChildId);
        if (child != null && child.isFocusable()) {
            viewToFocus = child;
        }
    }
    viewToFocus.requestFocus();
}

From source file:com.ferdi2005.secondgram.support.widget.RecyclerView.java

private void recoverFocusFromState() {
    if (!mPreserveFocusAfterLayout || mAdapter == null || !hasFocus()
            || getDescendantFocusability() == FOCUS_BLOCK_DESCENDANTS
            || (getDescendantFocusability() == FOCUS_BEFORE_DESCENDANTS && isFocused())) {
        // No-op if either of these cases happens:
        // 1. RV has no focus, or 2. RV blocks focus to its children, or 3. RV takes focus
        // before its children and is focused (i.e. it already stole the focus away from its
        // descendants).
        return;//from  w w  w  .j  a va  2 s.  com
    }
    // only recover focus if RV itself has the focus or the focused view is hidden
    if (!isFocused()) {
        final View focusedChild = getFocusedChild();
        if (IGNORE_DETACHED_FOCUSED_CHILD && (focusedChild.getParent() == null || !focusedChild.hasFocus())) {
            // Special handling of API 15-. A focused child can be invalid because mFocus is not
            // cleared when the child is detached (mParent = null),
            // This happens because clearFocus on API 15- does not invalidate mFocus of its
            // parent when this child is detached.
            // For API 16+, this is not an issue because requestFocus takes care of clearing the
            // prior detached focused child. For API 15- the problem happens in 2 cases because
            // clearChild does not call clearChildFocus on RV: 1. setFocusable(false) is called
            // for the current focused item which calls clearChild or 2. when the prior focused
            // child is removed, removeDetachedView called in layout step 3 which calls
            // clearChild. We should ignore this invalid focused child in all our calculations
            // for the next view to receive focus, and apply the focus recovery logic instead.
            if (mChildHelper.getChildCount() == 0) {
                // No children left. Request focus on the RV itself since one of its children
                // was holding focus previously.
                requestFocus();
                return;
            }
        } else if (!mChildHelper.isHidden(focusedChild)) {
            // If the currently focused child is hidden, apply the focus recovery logic.
            // Otherwise return, i.e. the currently (unhidden) focused child is good enough :/.
            return;
        }
    }
    ViewHolder focusTarget = null;
    // RV first attempts to locate the previously focused item to request focus on using
    // mFocusedItemId. If such an item no longer exists, it then makes a best-effort attempt to
    // find the next best candidate to request focus on based on mFocusedItemPosition.
    if (mState.mFocusedItemId != NO_ID && mAdapter.hasStableIds()) {
        focusTarget = findViewHolderForItemId(mState.mFocusedItemId);
    }
    View viewToFocus = null;
    if (focusTarget == null || mChildHelper.isHidden(focusTarget.itemView)
            || !focusTarget.itemView.hasFocusable()) {
        if (mChildHelper.getChildCount() > 0) {
            // At this point, RV has focus and either of these conditions are true:
            // 1. There's no previously focused item either because RV received focused before
            // layout, or the previously focused item was removed, or RV doesn't have stable IDs
            // 2. Previous focus child is hidden, or 3. Previous focused child is no longer
            // focusable. In either of these cases, we make sure that RV still passes down the
            // focus to one of its focusable children using a best-effort algorithm.
            viewToFocus = findNextViewToFocus();
        }
    } else {
        // looks like the focused item has been replaced with another view that represents the
        // same item in the adapter. Request focus on that.
        viewToFocus = focusTarget.itemView;
    }

    if (viewToFocus != null) {
        if (mState.mFocusedSubChildId != NO_ID) {
            View child = viewToFocus.findViewById(mState.mFocusedSubChildId);
            if (child != null && child.isFocusable()) {
                viewToFocus = child;
            }
        }
        viewToFocus.requestFocus();
    }
}