Example usage for android.view View getParent

List of usage examples for android.view View getParent

Introduction

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

Prototype

public final ViewParent getParent() 

Source Link

Document

Gets the parent of this view.

Usage

From source file:self.philbrown.droidQuery.$.java

/**
 * Adds an Image over each selected View as a mask.
 * In most cases, this mask can be retrieved by querying siblings. For example:
 * <pre>/*from  w ww. j  av a2  s.  c  o m*/
 * ImageView mask = (ImageView) $.with(myView).parent().selectChildren().selectImages().view(0);
 * </pre>
 * @param mask the bitmap to draw
 * @return this
 */
public $ mask(Bitmap mask) {
    for (View v : views) {
        ImageView image = new ImageView(context);
        image.setImageBitmap(mask);
        image.setScaleType(ScaleType.FIT_XY);
        ViewParent parent = v.getParent();
        if (parent != null && parent instanceof ViewGroup) {
            image.setLayoutParams(v.getLayoutParams());
            ((ViewGroup) parent).addView(image);
        } else if (v instanceof ViewGroup) {
            image.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT));
            ((ViewGroup) v).addView(image);
        }
    }
    return this;
}

From source file:self.philbrown.droidQuery.$.java

/**
 * Adds an Image over each selected View as a mask.
 * In most cases, this mask can be retrieved by querying siblings. For example:
 * <pre>// w w w  .java  2 s .  co  m
 * ImageView mask = (ImageView) $.with(myView).parent().selectChildren().selectImages().view(0);
 * </pre>
 * @param mask the drawable to draw
 * @return this
 */
public $ mask(Drawable mask) {
    for (View v : views) {
        ImageView image = new ImageView(context);
        image.setImageDrawable(mask);
        image.setScaleType(ScaleType.FIT_XY);
        ViewParent parent = v.getParent();
        if (parent != null && parent instanceof ViewGroup) {
            image.setLayoutParams(v.getLayoutParams());
            ((ViewGroup) parent).addView(image);
        } else if (v instanceof ViewGroup) {
            image.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT));
            ((ViewGroup) v).addView(image);
        }
    }
    return this;
}

From source file:self.philbrown.droidQuery.$.java

/**
 * Adds an Image over each selected View as a mask. 
 * In most cases, this mask can be retrieved by querying siblings. For example:
 * <pre>//w w  w . j a v  a  2s.c o m
 * ImageView mask = (ImageView) $.with(myView).parent().selectChildren().selectImages().view(0);
 * </pre>
 * @param resourceId the resource ID of the mask drawable
 * @return this
 */
public $ mask(int resourceId) {
    for (View v : views) {
        ImageView image = new ImageView(context);
        image.setImageResource(resourceId);
        image.setScaleType(ScaleType.FIT_XY);
        ViewParent parent = v.getParent();
        if (parent != null && parent instanceof ViewGroup) {
            image.setLayoutParams(v.getLayoutParams());
            ((ViewGroup) parent).addView(image);
        } else if (v instanceof ViewGroup) {
            image.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT));
            ((ViewGroup) v).addView(image);
        }
    }
    return this;
}

From source file:com.jforce.chapelhillnextbus.ExpandingListView.java

/**
 * This method expands the view that was clicked and animates all the views
 * around it to make room for the expanding view. There are several steps
 * required to do this which are outlined below.
 * <p/>// ww w .j a va  2s . com
 * 1. Store the current top and bottom bounds of each visible item in the
 * listview. 2. Update the layout parameters of the selected view. In the
 * context of this method, the view should be originally collapsed and set
 * to some custom height. The layout parameters are updated so as to wrap
 * the content of the additional text that is to be displayed.
 * <p/>
 * After invoking a layout to take place, the listview will order all the
 * items such that there is space for each view. This layout will be
 * independent of what the bounds of the items were prior to the layout so
 * two pre-draw passes will be made. This is necessary because after the
 * layout takes place, some views that were visible before the layout may
 * now be off bounds but a reference to these views is required so the
 * animation completes as intended.
 * <p/>
 * 3. The first predraw pass will set the bounds of all the visible items to
 * their original location before the layout took place and then force
 * another layout. Since the bounds of the cells cannot be set directly, the
 * method setSelectionFromTop can be used to achieve a very similar effect.
 * 4. The expanding view's bounds are animated to what the final values
 * should be from the original bounds. 5. The bounds above the expanding
 * view are animated upwards while the bounds below the expanding view are
 * animated downwards. 6. The extra text is faded in as its contents become
 * visible throughout the animation process.
 * <p/>
 * It is important to note that the listview is disabled during the
 * animation because the scrolling behaviour is unpredictable if the bounds
 * of the items within the listview are not constant during the scroll.
 */

private void expandView(final View view) {
    final ExpandableListItem viewObject = (ExpandableListItem) getItemAtPosition(getPositionForView(view));

    /* Store the original top and bottom bounds of all the cells. */
    final int oldTop = view.getTop();
    final int oldBottom = view.getBottom();

    final HashMap<View, int[]> oldCoordinates = new HashMap<View, int[]>();

    int childCount = getChildCount();
    for (int i = 0; i < childCount; i++) {
        View v = getChildAt(i);
        ViewCompat.setHasTransientState(v, true);
        oldCoordinates.put(v, new int[] { v.getTop(), v.getBottom() });
    }

    /* Update the layout so the extra content becomes visible. */
    final View expandingLayout = view.findViewById(R.id.expanding_layout);
    expandingLayout.setVisibility(View.VISIBLE);

    /*
       * Add an onPreDraw Listener to the listview. onPreDraw will get invoked
     * after onLayout and onMeasure have run but before anything has been
     * drawn. This means that the final post layout properties for all the
     * items have already been determined, but still have not been rendered
     * onto the screen.
     */
    final ViewTreeObserver observer = getViewTreeObserver();
    observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {

        @Override
        public boolean onPreDraw() {
            /* Determine if this is the first or second pass. */
            if (!mShouldRemoveObserver) {
                mShouldRemoveObserver = true;

                /*
                 * Calculate what the parameters should be for
                 * setSelectionFromTop. The ListView must be offset in a
                 * way, such that after the animation takes place, all the
                 * cells that remain visible are rendered completely by the
                 * ListView.
                 */
                int newTop = view.getTop();
                int newBottom = view.getBottom();

                int newHeight = newBottom - newTop;
                int oldHeight = oldBottom - oldTop;
                int delta = newHeight - oldHeight;

                mTranslate = getTopAndBottomTranslations(oldTop, oldBottom, delta, true);

                int currentTop = view.getTop();
                int futureTop = oldTop - mTranslate[0];

                int firstChildStartTop = getChildAt(0).getTop();
                int firstVisiblePosition = getFirstVisiblePosition();
                int deltaTop = currentTop - futureTop;

                int i;
                int childCount = getChildCount();
                for (i = 0; i < childCount; i++) {
                    View v = getChildAt(i);
                    int height = v.getBottom() - Math.max(0, v.getTop());
                    if (deltaTop - height > 0) {
                        firstVisiblePosition++;
                        deltaTop -= height;
                    } else {
                        break;
                    }
                }

                if (i > 0) {
                    firstChildStartTop = 0;
                }

                setSelectionFromTop(firstVisiblePosition, firstChildStartTop - deltaTop);

                /*
                 * Request another layout to update the layout parameters of
                 * the cells.
                 */
                requestLayout();

                /*
                 * Return false such that the ListView does not redraw its
                 * contents on this layout but only updates all the
                 * parameters associated with its children.
                 */
                return false;
            }

            /*
             * Remove the predraw listener so this method does not keep
             * getting called.
             */
            mShouldRemoveObserver = false;
            observer.removeOnPreDrawListener(this);

            int yTranslateTop = mTranslate[0];
            int yTranslateBottom = mTranslate[1];

            ArrayList<Animator> animations = new ArrayList<Animator>();

            int index = indexOfChild(view);

            /*
             * Loop through all the views that were on the screen before the
             * cell was expanded. Some cells will still be children of the
             * ListView while others will not. The cells that remain
             * children of the ListView simply have their bounds animated
             * appropriately. The cells that are no longer children of the
             * ListView also have their bounds animated, but must also be
             * added to a list of views which will be drawn in dispatchDraw.
             */
            for (View v : oldCoordinates.keySet()) {
                int[] old = oldCoordinates.get(v);
                v.setTop(old[0]);
                v.setBottom(old[1]);
                if (v.getParent() == null) {
                    mViewsToDraw.add(v);
                    int delta = old[0] < oldTop ? -yTranslateTop : yTranslateBottom;
                    animations.add(getAnimation(v, delta, delta));
                } else {
                    int i = indexOfChild(v);
                    if (v != view) {
                        int delta = i > index ? yTranslateBottom : -yTranslateTop;
                        animations.add(getAnimation(v, delta, delta));
                    }
                    ViewCompat.setHasTransientState(v, false);
                }
            }

            /* Adds animation for expanding the cell that was clicked. */
            animations.add(getAnimation(view, -yTranslateTop, yTranslateBottom));

            /* Adds an animation for fading in the extra content. */
            animations.add(ObjectAnimator.ofFloat(view.findViewById(R.id.expanding_layout), View.ALPHA, 0, 1));

            /* Disabled the ListView for the duration of the animation. */
            setEnabled(false);
            setClickable(false);

            /*
             * Play all the animations created above together at the same
             * time.
             */
            AnimatorSet s = new AnimatorSet();
            s.playTogether(animations);
            s.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    viewObject.setExpanded(true);
                    setEnabled(true);
                    setClickable(true);
                    if (mViewsToDraw.size() > 0) {
                        for (View v : mViewsToDraw) {
                            ViewCompat.setHasTransientState(v, false);
                        }
                    }
                    mViewsToDraw.clear();
                }
            });
            s.start();
            return true;
        }
    });
}

From source file:com.android.launcher3.Workspace.java

void startDrag(CellLayout.CellInfo cellInfo) {
    View child = cellInfo.cell;

    // Make sure the drag was started by a long press as opposed to a long click.
    if (!child.isInTouchMode()) {
        return;//from   w  w  w . j  a  va2s  .  c o m
    }

    mDragInfo = cellInfo;
    child.setVisibility(INVISIBLE);
    CellLayout layout = (CellLayout) child.getParent().getParent();
    layout.prepareChildForDrag(child);

    beginDragShared(child, this);
}

From source file:com.example.android.expandingcells.ExpandingListView.java

/**
 * This method expands the view that was clicked and animates all the views
 * around it to make room for the expanding view. There are several steps required
 * to do this which are outlined below.//from www.  jav  a2 s  .c  o  m
 *
 * 1. Store the current top and bottom bounds of each visible item in the listview.
 * 2. Update the layout parameters of the selected view. In the context of this
 *    method, the view should be originally collapsed and set to some custom height.
 *    The layout parameters are updated so as to wrap the content of the additional
 *    text that is to be displayed.
 *
 * After invoking a layout to take place, the listview will order all the items
 * such that there is space for each view. This layout will be independent of what
 * the bounds of the items were prior to the layout so two pre-draw passes will
 * be made. This is necessary because after the layout takes place, some views that
 * were visible before the layout may now be off bounds but a reference to these
 * views is required so the animation completes as intended.
 *
 * 3. The first predraw pass will set the bounds of all the visible items to
 *    their original location before the layout took place and then force another
 *    layout. Since the bounds of the cells cannot be set directly, the method
 *    setSelectionFromTop can be used to achieve a very similar effect.
 * 4. The expanding view's bounds are animated to what the final values should be
 *    from the original bounds.
 * 5. The bounds above the expanding view are animated upwards while the bounds
 *    below the expanding view are animated downwards.
 * 6. The extra text is faded in as its contents become visible throughout the
 *    animation process.
 *
 * It is important to note that the listview is disabled during the animation
 * because the scrolling behaviour is unpredictable if the bounds of the items
 * within the listview are not constant during the scroll.
 */
private void expandView(final View view) {
    final ExpandableListItem viewObject = (ExpandableListItem) getItemAtPosition(getPositionForView(view));

    /* Store the original top and bottom bounds of all the cells.*/
    final int oldTop = view.getTop();
    final int oldBottom = view.getBottom();

    final HashMap<View, int[]> oldCoordinates = new HashMap<View, int[]>();

    int childCount = getChildCount();
    for (int i = 0; i < childCount; i++) {
        View v = getChildAt(i);
        ViewCompat.setHasTransientState(v, true);
        oldCoordinates.put(v, new int[] { v.getTop(), v.getBottom() });
    }

    /* Update the layout so the extra content becomes visible.*/
    final View expandingLayout = view.findViewById(R.id.expanding_layout);
    if (expandingLayout == null) {
        throw new IllegalStateException("Layout must have a ExpandingLayout called expanding_layout.");
    }
    expandingLayout.setVisibility(View.VISIBLE);

    /* Add an onPreDraw Listener to the listview. onPreDraw will get invoked after onLayout
     * and onMeasure have run but before anything has been drawn. This
     * means that the final post layout properties for all the items have already been
     * determined, but still have not been rendered onto the screen.*/
    final ViewTreeObserver observer = getViewTreeObserver();
    observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {

        @Override
        public boolean onPreDraw() {
            /* Determine if this is the first or second pass.*/
            if (!mShouldRemoveObserver) {
                mShouldRemoveObserver = true;

                /* Calculate what the parameters should be for setSelectionFromTop.
                 * The ListView must be offset in a way, such that after the animation
                 * takes place, all the cells that remain visible are rendered completely
                 * by the ListView.*/
                int newTop = view.getTop();
                int newBottom = view.getBottom();

                int newHeight = newBottom - newTop;
                int oldHeight = oldBottom - oldTop;
                int delta = newHeight - oldHeight;

                mTranslate = getExpandingTopAndBottomTranslations(getPositionForView(view), oldTop, oldBottom,
                        delta);

                int currentTop = view.getTop();
                int futureTop = oldTop - mTranslate[0];

                int firstChildStartTop = getChildAt(0).getTop();
                int firstVisiblePosition = getFirstVisiblePosition();
                int deltaTop = currentTop - futureTop;

                int i;
                int childCount = getChildCount();
                for (i = 0; i < childCount; i++) {
                    View v = getChildAt(i);
                    int height = v.getBottom() - Math.max(0, v.getTop());
                    if (deltaTop - height > 0) {
                        firstVisiblePosition++;
                        deltaTop -= height;
                    } else {
                        break;
                    }
                }

                if (i > 0) {
                    firstChildStartTop = 0;
                }

                setSelectionFromTop(firstVisiblePosition, firstChildStartTop - deltaTop);

                /* Request another layout to update the layout parameters of the cells.*/
                requestLayout();

                /* Return false such that the ListView does not redraw its contents on
                 * this layout but only updates all the parameters associated with its
                 * children.*/
                return false;
            }

            /* Remove the predraw listener so this method does not keep getting called. */
            mShouldRemoveObserver = false;
            observer.removeOnPreDrawListener(this);

            int yTranslateTop = mTranslate[0];
            int yTranslateBottom = mTranslate[1];

            ArrayList<Animator> animations = new ArrayList<Animator>();

            int index = indexOfChild(view);

            /* Loop through all the views that were on the screen before the cell was
             *  expanded. Some cells will still be children of the ListView while
             *  others will not. The cells that remain children of the ListView
             *  simply have their bounds animated appropriately. The cells that are no
             *  longer children of the ListView also have their bounds animated, but
             *  must also be added to a list of views which will be drawn in dispatchDraw.*/
            for (View v : oldCoordinates.keySet()) {
                int[] old = oldCoordinates.get(v);

                handleSetTopAndBottom(v, old[0], old[1]);

                if (v == view) {
                    continue;
                } else if (v.getParent() == null) {
                    mViewsToDraw.add(v);
                    int delta = old[0] < oldTop ? -yTranslateTop : yTranslateBottom;
                    animations.add(getAnimation(v, old[0], old[1], delta, delta));

                } else {
                    int i = indexOfChild(v);
                    if (v != view) {
                        int delta = i > index ? yTranslateBottom : -yTranslateTop;
                        animations.add(getAnimation(v, old[0], old[1], delta, delta));
                    }
                    ViewCompat.setHasTransientState(v, false);
                }
            }

            /* Adds animation for expanding the cell that was clicked. */
            int[] old = oldCoordinates.get(view);
            animations.add(getAnimation(view, old[0], old[1], -yTranslateTop, yTranslateBottom));

            /* Adds an animation for fading in the extra content. */
            animations.add(ObjectAnimator.ofFloat(view.findViewById(R.id.expanding_layout), "alpha", 0, 1));

            /* Disabled the ListView for the duration of the animation.*/
            setEnabled(false);
            setClickable(false);

            /* Play all the animations created above together at the same time. */
            AnimatorSet s = new AnimatorSet();
            s.playTogether(animations);
            s.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    viewObject.setExpanded(true);
                    setEnabled(true);
                    setClickable(true);
                    if (mViewsToDraw.size() > 0) {
                        for (View v : mViewsToDraw) {
                            ViewCompat.setHasTransientState(v, false);
                        }
                    }
                    mViewsToDraw.clear();

                    if (mOnExpandingListener != null) {
                        mOnExpandingListener.onExpanded(view);
                    }
                }
            });
            s.start();
            return true;
        }
    });
}

From source file:self.philbrown.droidQuery.$.java

/**
 * Selects all views within the given current selection that are the single 
 * children of their parent views/*from  w  w w.  java 2 s .c  om*/
 * @param v the view whose hierarchy will be checked
 * @return a list of the found views.
 */
private List<View> recursivelySelectOnlyChilds(View v) {
    List<View> list = new ArrayList<View>();
    if (v instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) v).getChildCount(); i++) {
            list.addAll(recursivelySelectOnlyChilds(((ViewGroup) v).getChildAt(i)));
        }
    }
    if (v.getParent() instanceof ViewGroup && ((ViewGroup) v.getParent()).getChildCount() == 1)
        list.add(v);
    return list;
}

From source file:self.philbrown.droidQuery.$.java

/**
 * Adds an Image over each selected View as a mask.
 * In most cases, this mask can be retrieved by querying siblings. For example:
 * <pre>/*from   w w  w .  j a  va 2s . co  m*/
 * ImageView mask = (ImageView) $.with(myView).parent().selectChildren().selectImages().view(0);
 * </pre>
 * @param source asset path, file path (starting with "file://") or URL to image
 * @param width specifies the output bitmap width
 * @param height specifies the output bitmap height
 * @param error if the given source is a file or asset, this receives a droidQuery wrapping the 
 * current context and the {@code Throwable} error. Otherwise, this will receive an
 * Ajax error.
 * @return this
 * @see AjaxOptions#error(Function)
 */
public $ mask(String source, int width, int height, Function error) {
    if (source.startsWith("file://")) {
        try {
            BitmapFactory.Options opt = new BitmapFactory.Options();
            opt.inPreferredConfig = Bitmap.Config.ARGB_8888;
            if (width >= 0)
                opt.outWidth = width;
            if (height >= 0)
                opt.outHeight = height;
            Bitmap bitmap = BitmapFactory.decodeFile(source.substring(6), opt);
            for (View v : views) {
                ImageView image = new ImageView(context);
                image.setImageBitmap(Bitmap.createBitmap(bitmap));
                image.setScaleType(ScaleType.FIT_XY);
                ViewParent parent = v.getParent();
                if (parent != null && parent instanceof ViewGroup) {
                    image.setLayoutParams(v.getLayoutParams());
                    ((ViewGroup) parent).addView(image);
                } else if (v instanceof ViewGroup) {
                    image.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                            ViewGroup.LayoutParams.MATCH_PARENT));
                    ((ViewGroup) v).addView(image);
                }
            }
        } catch (Throwable t) {
            if (error != null) {
                error.invoke($.with(context), t);
            }
        }
    } else if (URLUtil.isValidUrl(source)) {
        AjaxOptions options = new AjaxOptions().url(source).type("GET").dataType("image").context(context)
                .global(false).success(new Function() {
                    @Override
                    public void invoke($ droidQuery, Object... params) {
                        Bitmap bitmap = (Bitmap) params[0];
                        for (View v : views) {
                            ImageView image = new ImageView(context);
                            image.setImageBitmap(Bitmap.createBitmap(bitmap));
                            image.setScaleType(ScaleType.FIT_XY);
                            ViewParent parent = v.getParent();
                            if (parent != null && parent instanceof ViewGroup) {
                                image.setLayoutParams(v.getLayoutParams());
                                ((ViewGroup) parent).addView(image);
                            } else if (v instanceof ViewGroup) {
                                image.setLayoutParams(
                                        new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                                                ViewGroup.LayoutParams.MATCH_PARENT));
                                ((ViewGroup) v).addView(image);
                            }
                        }
                    }
                });

        if (error != null) {
            options.error(error);
        }
        if (width >= 0) {
            options.imageWidth(width);
        }
        if (height >= 0) {
            options.imageHeight(height);
        }
        $.ajax(options);
    } else {
        try {
            BitmapFactory.Options opt = new BitmapFactory.Options();
            opt.inSampleSize = 1;
            opt.inPurgeable = true;
            opt.inInputShareable = false;
            if (width >= 0)
                opt.outWidth = width;
            if (height >= 0)
                opt.outHeight = height;
            Bitmap bitmap = BitmapFactory.decodeStream(context.getAssets().open(source), new Rect(0, 0, 0, 0),
                    opt);
            for (View v : views) {
                ImageView image = new ImageView(context);
                image.setImageBitmap(Bitmap.createBitmap(bitmap));
                image.setScaleType(ScaleType.FIT_XY);
                ViewParent parent = v.getParent();
                if (parent != null && parent instanceof ViewGroup) {
                    image.setLayoutParams(v.getLayoutParams());
                    ((ViewGroup) parent).addView(image);
                } else if (v instanceof ViewGroup) {
                    image.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                            ViewGroup.LayoutParams.MATCH_PARENT));
                    ((ViewGroup) v).addView(image);
                }
            }

        } catch (Throwable t) {
            if (error != null) {
                error.invoke($.with(context), t);
            }
        }

    }
    return this;
}

From source file:app.umitems.greenclock.widget.sgv.StaggeredGridView.java

/**
 * Measure and layout all currently visible children.
 *
 * @param queryAdapter true to requery the adapter for view data
 *///ww  w . j  a v a 2 s.  co  m
final void layoutChildren(boolean queryAdapter) {
    final int paddingLeft = getPaddingLeft();
    final int paddingRight = getPaddingRight();
    final int itemMargin = mItemMargin;
    final int availableWidth = (getWidth() - paddingLeft - paddingRight - itemMargin * (mColCount - 1));
    final int colWidth = availableWidth / mColCount;
    // The availableWidth may not be divisible by mColCount. Keep the
    // remainder. It will be added to the width of the last view in the row.
    final int remainder = availableWidth % mColCount;

    boolean viewsRemovedInLayout = false;

    // If we're animating out stale views, then we want to defer recycling of views.
    final boolean deferRecyclingForAnimation = mAnimationOutMode != AnimationOut.NONE;

    if (!deferRecyclingForAnimation) {
        final int childCount = getChildCount();
        // If the latest data set has fewer data items than mFirstPosition, don't keep any
        // views on screen, and just let the layout logic below retrieve appropriate views
        // from the recycler.
        final int viewsToKeepOnScreen = (mItemCount <= mFirstPosition) ? 0 : mItemCount - mFirstPosition;

        if (childCount > viewsToKeepOnScreen) {
            // If there are more views laid out than the number of data items remaining to be
            // laid out, recycle the extraneous views.
            recycleViewsInRange(viewsToKeepOnScreen, childCount - 1);
            viewsRemovedInLayout = true;
        }
    } else {
        mViewsToAnimateOut.clear();
    }

    for (int i = 0; i < getChildCount(); i++) {
        final int position = mFirstPosition + i;
        View child = getChildAt(i);

        final int highestAvailableLayoutPosition = mItemBottoms[getNextColumnDown()];
        if (deferRecyclingForAnimation
                && (position >= mItemCount || highestAvailableLayoutPosition >= getHeight())) {
            // For the remainder of views on screen, they should not be on screen, so we can
            // skip layout.  Add them to the list of views to animate out.
            // We should only get in this position if deferRecyclingForAnimation = true,
            // otherwise, we should've recycled all views before getting into this layout loop.
            mViewsToAnimateOut.add(child);
            continue;
        }

        LayoutParams lp = null;
        int col = -1;

        if (child != null) {
            lp = (LayoutParams) child.getLayoutParams();
            col = lp.column;
        }

        final boolean needsLayout = queryAdapter || child == null || child.isLayoutRequested();
        if (queryAdapter) {
            View newView = null;
            if (deferRecyclingForAnimation) {
                // If we are deferring recycling for animation, then we don't want to pass the
                // current child in to obtainView for re-use.  obtainView() in this case should
                // try to find the view belonging to this item on screen, or populate a fresh
                // one from the recycler.
                newView = obtainView(position);
            } else {
                newView = obtainView(position, child);
            }

            // Update layout params since they may have changed
            lp = (LayoutParams) newView.getLayoutParams();

            if (newView != child) {
                if (child != null && !deferRecyclingForAnimation) {
                    mRecycler.addScrap(child);
                    removeViewInLayout(child);
                    viewsRemovedInLayout = true;
                }

                // If this view is already in the layout hierarchy, we can just detach it
                // from the parent and re-attach it at the correct index.  If the view has
                // already been removed from the layout hierarchy, getParent() == null.
                if (newView.getParent() == this) {
                    detachViewFromParent(newView);
                    attachViewToParent(newView, i, lp);
                } else {
                    addViewInLayout(newView, i, lp);
                }
            }

            child = newView;

            // Since the data has changed, we need to make sure the next child is in the
            // right column. We choose the next column down (vs. next column up) because we
            // are filling from the top of the screen downwards as we iterate through
            // visible children. (We take span into account below.)
            lp.column = getNextColumnDown();
            col = lp.column;
        }

        setReorderingArea(lp);

        final int span = Math.min(mColCount, lp.span);

        // Given the span, check if there's enough space to put this view at this column.
        // IMPORTANT Propagate the same logic to {@link #calculateLayoutStartOffsets}.
        if (span > 1) {
            if (mIsRtlLayout) {
                // For RTL layout, if the current column index is less than the span of the
                // child, then we know that there is not enough room remaining to lay this
                // child out (e.g., if col == 0, but span == 2, then laying this child down
                // at column = col would put us out of bound into a negative column index.).
                // For this scenario, reset the index back to the right-most column, and lay
                // out the child at this position where we can ensure that we can display as
                // much of the child as possible.
                if (col + 1 < span) {
                    col = mColCount - 1;
                }
            } else {
                if (mColCount - col < span) {
                    // If not, reset the col to 0.
                    col = 0;
                }
            }

            lp.column = col;
        }

        int widthSize = (colWidth * span + itemMargin * (span - 1));
        // If it is rtl, we layout the view from col to col - span +
        // 1. If it reaches the most left column, i.e. we added the
        // additional width. So the check it span == col +1
        if ((mIsRtlLayout && span == col + 1) || (!mIsRtlLayout && span + col == mColCount)) {
            widthSize += remainder;
        }
        if (needsLayout) {
            final int widthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);

            final int heightSpec;
            if (lp.height == LayoutParams.WRAP_CONTENT) {
                heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
            } else {
                heightSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY);
            }

            child.measure(widthSpec, heightSpec);
        }

        // Place the top of this child beneath the last by finding the lowest coordinate across
        // the columns that this child will span.  For LTR layout, we scan across from left to
        // right, and for RTL layout, we scan from right to left.
        // TODO:  Consolidate this logic with getNextRecordDown() in the future, as that method
        // already calculates the margins for us.  This will keep the implementation consistent
        // with fillUp() and fillDown().
        int childTop = mItemBottoms[col] + mItemMargin;
        if (span > 1) {
            int lowest = childTop;
            for (int spanIndex = 0; spanIndex < span; spanIndex++) {
                final int index = mIsRtlLayout ? col - spanIndex : col + spanIndex;
                final int bottom = mItemBottoms[index] + mItemMargin;
                if (bottom > lowest) {
                    lowest = bottom;
                }
            }

            childTop = lowest;
        }

        final int childHeight = child.getMeasuredHeight();
        final int childBottom = childTop + childHeight;
        int childLeft = 0;
        int childRight = 0;
        if (mIsRtlLayout) {
            childRight = (getWidth() - paddingRight) - (mColCount - col - 1) * (colWidth + itemMargin);
            childLeft = childRight - child.getMeasuredWidth();
        } else {
            childLeft = paddingLeft + col * (colWidth + itemMargin);
            childRight = childLeft + child.getMeasuredWidth();
        }

        /*    Log.v(TAG, "[layoutChildren] height: " + childHeight
            + " top: " + childTop + " bottom: " + childBottom
            + " left: " + childLeft
            + " column: " + col
            + " position: " + position
            + " id: " + lp.id);
        */
        child.layout(childLeft, childTop, childRight, childBottom);
        if (lp.id == mFocusedChildIdToScrollIntoView) {
            child.requestFocus();
        }

        for (int spanIndex = 0; spanIndex < span; spanIndex++) {
            final int index = mIsRtlLayout ? col - spanIndex : col + spanIndex;
            mItemBottoms[index] = childBottom;
        }

        // Whether or not LayoutRecords may have already existed for the view at this position
        // on screen, we'll update it after we lay out to ensure that the LayoutRecord
        // has the most updated information about the view at this position.  We can be assured
        // that all views before those on screen (views with adapter position < mFirstPosition)
        // have the correct LayoutRecords because calculateLayoutStartOffsets() would have
        // set them appropriately.
        LayoutRecord rec = mLayoutRecords.get(position);
        if (rec == null) {
            rec = new LayoutRecord();
            mLayoutRecords.put(position, rec);
        }

        rec.column = lp.column;
        rec.height = childHeight;
        rec.id = lp.id;
        rec.span = span;
    }

    // It appears that removeViewInLayout() does not invalidate.  So if we make use of this
    // method during layout, we should invalidate explicitly.
    if (viewsRemovedInLayout || deferRecyclingForAnimation) {
        invalidate();
    }
}

From source file:com.deepak.myclock.widget.sgv.StaggeredGridView.java

/**
 * Measure and layout all currently visible children.
 *
 * @param queryAdapter true to requery the adapter for view data
 *///from   w w  w  . j  a  v  a2s .  c  o m
final void layoutChildren(boolean queryAdapter) {
    final int paddingLeft = getPaddingLeft();
    final int paddingRight = getPaddingRight();
    final int itemMargin = mItemMargin;
    final int availableWidth = (getWidth() - paddingLeft - paddingRight - itemMargin * (mColCount - 1));
    final int colWidth = availableWidth / mColCount;
    // The availableWidth may not be divisible by mColCount. Keep the
    // remainder. It will be added to the width of the last view in the row.
    final int remainder = availableWidth % mColCount;

    boolean viewsRemovedInLayout = false;

    // If we're animating out stale views, then we want to defer recycling of views.
    final boolean deferRecyclingForAnimation = mAnimationOutMode != SgvAnimationHelper.AnimationOut.NONE;

    if (!deferRecyclingForAnimation) {
        final int childCount = getChildCount();
        // If the latest data set has fewer data items than mFirstPosition, don't keep any
        // views on screen, and just let the layout logic below retrieve appropriate views
        // from the recycler.
        final int viewsToKeepOnScreen = (mItemCount <= mFirstPosition) ? 0 : mItemCount - mFirstPosition;

        if (childCount > viewsToKeepOnScreen) {
            // If there are more views laid out than the number of data items remaining to be
            // laid out, recycle the extraneous views.
            recycleViewsInRange(viewsToKeepOnScreen, childCount - 1);
            viewsRemovedInLayout = true;
        }
    } else {
        mViewsToAnimateOut.clear();
    }

    for (int i = 0; i < getChildCount(); i++) {
        final int position = mFirstPosition + i;
        View child = getChildAt(i);

        final int highestAvailableLayoutPosition = mItemBottoms[getNextColumnDown()];
        if (deferRecyclingForAnimation
                && (position >= mItemCount || highestAvailableLayoutPosition >= getHeight())) {
            // For the remainder of views on screen, they should not be on screen, so we can
            // skip layout.  Add them to the list of views to animate out.
            // We should only get in this position if deferRecyclingForAnimation = true,
            // otherwise, we should've recycled all views before getting into this layout loop.
            mViewsToAnimateOut.add(child);
            continue;
        }

        LayoutParams lp = null;
        int col = -1;

        if (child != null) {
            lp = (LayoutParams) child.getLayoutParams();
            col = lp.column;
        }

        final boolean needsLayout = queryAdapter || child == null || child.isLayoutRequested();
        if (queryAdapter) {
            View newView = null;
            if (deferRecyclingForAnimation) {
                // If we are deferring recycling for animation, then we don't want to pass the
                // current child in to obtainView for re-use.  obtainView() in this case should
                // try to find the view belonging to this item on screen, or populate a fresh
                // one from the recycler.
                newView = obtainView(position);
            } else {
                newView = obtainView(position, child);
            }

            // Update layout params since they may have changed
            lp = (LayoutParams) newView.getLayoutParams();

            if (newView != child) {
                if (child != null && !deferRecyclingForAnimation) {
                    mRecycler.addScrap(child);
                    removeViewInLayout(child);
                    viewsRemovedInLayout = true;
                }

                // If this view is already in the layout hierarchy, we can just detach it
                // from the parent and re-attach it at the correct index.  If the view has
                // already been removed from the layout hierarchy, getParent() == null.
                if (newView.getParent() == this) {
                    detachViewFromParent(newView);
                    attachViewToParent(newView, i, lp);
                } else {
                    addViewInLayout(newView, i, lp);
                }
            }

            child = newView;

            // Since the data has changed, we need to make sure the next child is in the
            // right column. We choose the next column down (vs. next column up) because we
            // are filling from the top of the screen downwards as we iterate through
            // visible children. (We take span into account below.)
            lp.column = getNextColumnDown();
            col = lp.column;
        }

        setReorderingArea(lp);

        final int span = Math.min(mColCount, lp.span);

        // Given the span, check if there's enough space to put this view at this column.
        // IMPORTANT Propagate the same logic to {@link #calculateLayoutStartOffsets}.
        if (span > 1) {
            if (mIsRtlLayout) {
                // For RTL layout, if the current column index is less than the span of the
                // child, then we know that there is not enough room remaining to lay this
                // child out (e.g., if col == 0, but span == 2, then laying this child down
                // at column = col would put us out of bound into a negative column index.).
                // For this scenario, reset the index back to the right-most column, and lay
                // out the child at this position where we can ensure that we can display as
                // much of the child as possible.
                if (col + 1 < span) {
                    col = mColCount - 1;
                }
            } else {
                if (mColCount - col < span) {
                    // If not, reset the col to 0.
                    col = 0;
                }
            }

            lp.column = col;
        }

        int widthSize = (colWidth * span + itemMargin * (span - 1));
        // If it is rtl, we layout the view from col to col - span +
        // 1. If it reaches the most left column, i.e. we added the
        // additional width. So the check it span == col +1
        if ((mIsRtlLayout && span == col + 1) || (!mIsRtlLayout && span + col == mColCount)) {
            widthSize += remainder;
        }
        if (needsLayout) {
            final int widthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);

            final int heightSpec;
            if (lp.height == LayoutParams.WRAP_CONTENT) {
                heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
            } else {
                heightSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY);
            }

            child.measure(widthSpec, heightSpec);
        }

        // Place the top of this child beneath the last by finding the lowest coordinate across
        // the columns that this child will span.  For LTR layout, we scan across from left to
        // right, and for RTL layout, we scan from right to left.
        // TODO:  Consolidate this logic with getNextRecordDown() in the future, as that method
        // already calculates the margins for us.  This will keep the implementation consistent
        // with fillUp() and fillDown().
        int childTop = mItemBottoms[col] + mItemMargin;
        if (span > 1) {
            int lowest = childTop;
            for (int spanIndex = 0; spanIndex < span; spanIndex++) {
                final int index = mIsRtlLayout ? col - spanIndex : col + spanIndex;
                final int bottom = mItemBottoms[index] + mItemMargin;
                if (bottom > lowest) {
                    lowest = bottom;
                }
            }

            childTop = lowest;
        }

        final int childHeight = child.getMeasuredHeight();
        final int childBottom = childTop + childHeight;
        int childLeft = 0;
        int childRight = 0;
        if (mIsRtlLayout) {
            childRight = (getWidth() - paddingRight) - (mColCount - col - 1) * (colWidth + itemMargin);
            childLeft = childRight - child.getMeasuredWidth();
        } else {
            childLeft = paddingLeft + col * (colWidth + itemMargin);
            childRight = childLeft + child.getMeasuredWidth();
        }

        /*    Log.v(TAG, "[layoutChildren] height: " + childHeight
            + " top: " + childTop + " bottom: " + childBottom
            + " left: " + childLeft
            + " column: " + col
            + " position: " + position
            + " id: " + lp.id);
        */
        child.layout(childLeft, childTop, childRight, childBottom);
        if (lp.id == mFocusedChildIdToScrollIntoView) {
            child.requestFocus();
        }

        for (int spanIndex = 0; spanIndex < span; spanIndex++) {
            final int index = mIsRtlLayout ? col - spanIndex : col + spanIndex;
            mItemBottoms[index] = childBottom;
        }

        // Whether or not LayoutRecords may have already existed for the view at this position
        // on screen, we'll update it after we lay out to ensure that the LayoutRecord
        // has the most updated information about the view at this position.  We can be assured
        // that all views before those on screen (views with adapter position < mFirstPosition)
        // have the correct LayoutRecords because calculateLayoutStartOffsets() would have
        // set them appropriately.
        LayoutRecord rec = mLayoutRecords.get(position);
        if (rec == null) {
            rec = new LayoutRecord();
            mLayoutRecords.put(position, rec);
        }

        rec.column = lp.column;
        rec.height = childHeight;
        rec.id = lp.id;
        rec.span = span;
    }

    // It appears that removeViewInLayout() does not invalidate.  So if we make use of this
    // method during layout, we should invalidate explicitly.
    if (viewsRemovedInLayout || deferRecyclingForAnimation) {
        invalidate();
    }
}