FileDocCategorySizeDatePackage
ChildHelper.javaAPI DocAndroid 5.1 API15124Thu Mar 12 22:22:56 GMT 2015android.support.v7.widget

ChildHelper

public class ChildHelper extends Object
Helper class to manage children.

It wraps a RecyclerView and adds ability to hide some children. There are two sets of methods provided by this class. Regular methods are the ones that replicate ViewGroup methods like getChildAt, getChildCount etc. These methods ignore hidden children.

When RecyclerView needs direct access to the view group children, it can call unfiltered methods like get getUnfilteredChildCount or getUnfilteredChildAt.

Fields Summary
private static final boolean
DEBUG
private static final String
TAG
final Callback
mCallback
final Bucket
mBucket
final List
mHiddenViews
Constructors Summary
ChildHelper(Callback callback)


      
        mCallback = callback;
        mBucket = new Bucket();
        mHiddenViews = new ArrayList<View>();
    
Methods Summary
voidaddView(android.view.View child, boolean hidden)
Adds a view to the ViewGroup

param
child View to add.
param
hidden If set to true, this item will be invisible from regular methods.

        addView(child, -1, hidden);
    
voidaddView(android.view.View child, int index, boolean hidden)
Add a view to the ViewGroup at an index

param
child View to add.
param
index Index of the child from the regular perspective (excluding hidden views). ChildHelper offsets this index to actual ViewGroup index.
param
hidden If set to true, this item will be invisible from regular methods.

        final int offset;
        if (index < 0) {
            offset = mCallback.getChildCount();
        } else {
            offset = getOffset(index);
        }
        mCallback.addView(child, offset);
        mBucket.insert(offset, hidden);
        if (hidden) {
            mHiddenViews.add(child);
        }
        if (DEBUG) {
            Log.d(TAG, "addViewAt " + index + ",h:" + hidden + ", " + this);
        }
    
voidattachViewToParent(android.view.View child, int index, ViewGroup.LayoutParams layoutParams, boolean hidden)
Attaches the provided view to the underlying ViewGroup.

param
child Child to attach.
param
index Index of the child to attach in regular perspective.
param
layoutParams LayoutParams for the child.
param
hidden If set to true, this item will be invisible to the regular methods.

        final int offset;
        if (index < 0) {
            offset = mCallback.getChildCount();
        } else {
            offset = getOffset(index);
        }
        mCallback.attachViewToParent(child, offset, layoutParams);
        mBucket.insert(offset, hidden);
        if (hidden) {
            mHiddenViews.add(child);
        }
        if (DEBUG) {
            Log.d(TAG, "attach view to parent index:" + index + ",off:" + offset + "," +
                    "h:" + hidden + ", " + this);
        }
    
voiddetachViewFromParent(int index)
Detaches the view at the provided index.

param
index Index of the child to return in regular perspective.

        final int offset = getOffset(index);
        mCallback.detachViewFromParent(offset);
        mBucket.remove(offset);
        if (DEBUG) {
            Log.d(TAG, "detach view from parent " + index + ", off:" + offset);
        }
    
android.view.ViewfindHiddenNonRemovedView(int position, int type)
This can be used to find a disappearing view by position.

param
position The adapter position of the item.
param
type View type, can be {@link RecyclerView#INVALID_TYPE}.
return
A hidden view with a valid ViewHolder that matches the position and type.

        final int count = mHiddenViews.size();
        for (int i = 0; i < count; i++) {
            final View view = mHiddenViews.get(i);
            RecyclerView.ViewHolder holder = mCallback.getChildViewHolder(view);
            if (holder.getLayoutPosition() == position && !holder.isInvalid() &&
                    (type == RecyclerView.INVALID_TYPE || holder.getItemViewType() == type)) {
                return view;
            }
        }
        return null;
    
android.view.ViewgetChildAt(int index)
Returns the child at provided index.

param
index Index of the child to return in regular perspective.

        final int offset = getOffset(index);
        return mCallback.getChildAt(offset);
    
intgetChildCount()
Returns the number of children that are not hidden.

return
Number of children that are not hidden.
see
#getChildAt(int)

        return mCallback.getChildCount() - mHiddenViews.size();
    
private intgetOffset(int index)

        if (index < 0) {
            return -1; //anything below 0 won't work as diff will be undefined.
        }
        final int limit = mCallback.getChildCount();
        int offset = index;
        while (offset < limit) {
            final int removedBefore = mBucket.countOnesBefore(offset);
            final int diff = index - (offset - removedBefore);
            if (diff == 0) {
                while (mBucket.get(offset)) { // ensure this offset is not hidden
                    offset ++;
                }
                return offset;
            } else {
                offset += diff;
            }
        }
        return -1;
    
android.view.ViewgetUnfilteredChildAt(int index)
Returns a child by ViewGroup offset. ChildHelper won't offset this index.

param
index ViewGroup index of the child to return.
return
The view in the provided index.

        return mCallback.getChildAt(index);
    
intgetUnfilteredChildCount()
Returns the total number of children.

return
The total number of children including the hidden views.
see
#getUnfilteredChildAt(int)

        return mCallback.getChildCount();
    
voidhide(android.view.View view)
Marks a child view as hidden.

param
view The view to hide.

        final int offset = mCallback.indexOfChild(view);
        if (offset < 0) {
            throw new IllegalArgumentException("view is not a child, cannot hide " + view);
        }
        if (DEBUG && mBucket.get(offset)) {
            throw new RuntimeException("trying to hide same view twice, how come ? " + view);
        }
        mBucket.set(offset);
        mHiddenViews.add(view);
        if (DEBUG) {
            Log.d(TAG, "hiding child " + view + " at offset " + offset+ ", " + this);
        }
    
intindexOfChild(android.view.View child)
Returns the index of the child in regular perspective.

param
child The child whose index will be returned.
return
The regular perspective index of the child or -1 if it does not exists.

        final int index = mCallback.indexOfChild(child);
        if (index == -1) {
            return -1;
        }
        if (mBucket.get(index)) {
            if (DEBUG) {
                throw new IllegalArgumentException("cannot get index of a hidden child");
            } else {
                return -1;
            }
        }
        // reverse the index
        return index - mBucket.countOnesBefore(index);
    
booleanisHidden(android.view.View view)
Returns whether a View is visible to LayoutManager or not.

param
view The child view to check. Should be a child of the Callback.
return
True if the View is not visible to LayoutManager

        return mHiddenViews.contains(view);
    
voidremoveAllViewsUnfiltered()
Removes all views from the ViewGroup including the hidden ones.

        mCallback.removeAllViews();
        mBucket.reset();
        mHiddenViews.clear();
        if (DEBUG) {
            Log.d(TAG, "removeAllViewsUnfiltered");
        }
    
voidremoveView(android.view.View view)
Removes the provided View from underlying RecyclerView.

param
view The view to remove.

        int index = mCallback.indexOfChild(view);
        if (index < 0) {
            return;
        }
        mCallback.removeViewAt(index);
        if (mBucket.remove(index)) {
            mHiddenViews.remove(view);
        }
        if (DEBUG) {
            Log.d(TAG, "remove View off:" + index + "," + this);
        }
    
voidremoveViewAt(int index)
Removes the view at the provided index from RecyclerView.

param
index Index of the child from the regular perspective (excluding hidden views). ChildHelper offsets this index to actual ViewGroup index.

        final int offset = getOffset(index);
        final View view = mCallback.getChildAt(offset);
        if (view == null) {
            return;
        }
        mCallback.removeViewAt(offset);
        if (mBucket.remove(offset)) {
            mHiddenViews.remove(view);
        }
        if (DEBUG) {
            Log.d(TAG, "removeViewAt " + index + ", off:" + offset + ", " + this);
        }
    
booleanremoveViewIfHidden(android.view.View view)
Removes a view from the ViewGroup if it is hidden.

param
view The view to remove.
return
True if the View is found and it is hidden. False otherwise.

        final int index = mCallback.indexOfChild(view);
        if (index == -1) {
            if (mHiddenViews.remove(view) && DEBUG) {
                throw new IllegalStateException("view is in hidden list but not in view group");
            }
            return true;
        }
        if (mBucket.get(index)) {
            mBucket.remove(index);
            mCallback.removeViewAt(index);
            if (!mHiddenViews.remove(view) && DEBUG) {
                throw new IllegalStateException(
                        "removed a hidden view but it is not in hidden views list");
            }
            return true;
        }
        return false;
    
public java.lang.StringtoString()

        return mBucket.toString() + ", hidden list:" + mHiddenViews.size();