@Override protected synchronized void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if (mAdapter == null) { return; } if (mDataChanged) { int oldCurrentX = mCurrentX; initView(); removeAllViewsInLayout(); mNextX = oldCurrentX; mDataChanged = false; } if (mScroller.computeScrollOffset()) { int scrollx = mScroller.getCurrX(); mNextX = scrollx; } if (mNextX < 0) { mNextX = 0; mScroller.forceFinished(true); return; } if (mNextX > mMaxX) { mNextX = mMaxX; mScroller.forceFinished(true); return; } int dx = mCurrentX - mNextX; removeNonVisibleItems(dx); fillList(dx); positionItems(dx); mCurrentX = mNextX; if (!mScroller.isFinished()) { post( new Runnable() { @Override public void run() { requestLayout(); } }); } }
@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); for (int i = 0; i < getChildCount(); i++) { boundsRect.set(0, 0, getWidth(), getHeight()); View view = getChildAt(i); int w, h; w = view.getMeasuredWidth(); h = view.getMeasuredHeight(); Gravity.apply(mGravity, w, h, boundsRect, childRect); view.layout(childRect.left, childRect.top, childRect.right, childRect.bottom); } }
/** {@inheritDoc} */ @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); CFUtil.Log("onLayout"); layoutChildren(); // scrollTo(getScrollX(), getScrollY()); // final int parentLeft = getPaddingLeftWithForeground(); // final int parentRight = right - left - getPaddingRightWithForeground(); // // final int parentTop = getPaddingTopWithForeground(); // final int parentBottom = bottom - top - getPaddingBottomWithForeground(); // // mForegroundBoundsChanged = true; // // for (int i = 0; i < count; i++) { // final View child = getChildAt(i); // if (child.getVisibility() != GONE) { // final LayoutParams lp = (LayoutParams) child.getLayoutParams(); // // final int width = child.getMeasuredWidth(); // final int height = child.getMeasuredHeight(); // // int childLeft; // int childTop; // // int gravity = lp.gravity; // if (gravity == -1) { // gravity = DEFAULT_CHILD_GRAVITY; // } // // final int layoutDirection = getLayoutDirection(); // final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, // layoutDirection); // final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK; // // switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) { // case Gravity.LEFT: // childLeft = parentLeft + lp.leftMargin; // break; // case Gravity.CENTER_HORIZONTAL: // childLeft = parentLeft + (parentRight - parentLeft - width) / 2 + // lp.leftMargin - lp.rightMargin; // break; // case Gravity.RIGHT: // childLeft = parentRight - width - lp.rightMargin; // break; // default: // childLeft = parentLeft + lp.leftMargin; // } // // switch (verticalGravity) { // case Gravity.TOP: // childTop = parentTop + lp.topMargin; // break; // case Gravity.CENTER_VERTICAL: // childTop = parentTop + (parentBottom - parentTop - height) / 2 + // lp.topMargin - lp.bottomMargin; // break; // case Gravity.BOTTOM: // childTop = parentBottom - height - lp.bottomMargin; // break; // default: // childTop = parentTop + lp.topMargin; // } // // child.layout(childLeft, childTop, childLeft + width, childTop + height); // } // } }
@Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { Log.i(TAG, "onLayout"); if (!mUserInteracting) { return; } super.onLayout(changed, left, top, right, bottom); View cv = mChildViews.get(mCurrent); Point cvOffset; if (!mResetLayout) { // Move to next or previous if current is sufficiently off center if (cv != null) { cvOffset = subScreenSizeOffset(cv); // cv.getRight() may be out of date with the current scale // so add left to the measured width for the correct position if (cv.getLeft() + cv.getMeasuredWidth() + cvOffset.x + GAP / 2 + mXScroll < getWidth() / 2 && mCurrent + 1 < mAdapter.getCount()) { postUnsettle(cv); // post to invoke test for end of animation // where we must set hq area for the new current view post(this); mCurrent++; onMoveToChild(cv, mCurrent); } if (cv.getLeft() - cvOffset.x - GAP / 2 + mXScroll >= getWidth() / 2 && mCurrent > 0) { postUnsettle(cv); // post to invoke test for end of animation // where we must set hq area for the new current view post(this); mCurrent--; onMoveToChild(cv, mCurrent); } } // Remove not needed children and hold them for reuse int numChildren = mChildViews.size(); int childIndices[] = new int[numChildren]; for (int i = 0; i < numChildren; i++) childIndices[i] = mChildViews.keyAt(i); for (int i = 0; i < numChildren; i++) { int ai = childIndices[i]; if (ai < mCurrent - 1 || ai > mCurrent + 1) { View v = mChildViews.get(ai); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { onNotInUse(v); } mViewCache.add(v); removeViewInLayout(v); mChildViews.remove(ai); } } } else { mResetLayout = false; mXScroll = mYScroll = 0; // Remove all children and hold them for reuse int numChildren = mChildViews.size(); for (int i = 0; i < numChildren; i++) { View v = mChildViews.valueAt(i); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { onNotInUse(v); } mViewCache.add(v); removeViewInLayout(v); } mChildViews.clear(); // post to ensure generation of hq area post(this); } // Ensure current view is present int cvLeft, cvRight, cvTop, cvBottom; boolean notPresent = (mChildViews.get(mCurrent) == null); cv = getOrCreateChild(mCurrent); // When the view is sub-screen-size in either dimension we // offset it to center within the screen area, and to keep // the views spaced out cvOffset = subScreenSizeOffset(cv); if (notPresent) { // Main item not already present. Just place it top left cvLeft = cvOffset.x; cvTop = cvOffset.y; } else { // Main item already present. Adjust by scroll offsets cvLeft = cv.getLeft() + mXScroll; cvTop = cv.getTop() + mYScroll; } // Scroll values have been accounted for mXScroll = mYScroll = 0; cvRight = cvLeft + cv.getMeasuredWidth(); cvBottom = cvTop + cv.getMeasuredHeight(); if (!mUserInteracting && mScroller.isFinished()) { Point corr = getCorrection(getScrollBounds(cvLeft, cvTop, cvRight, cvBottom)); cvRight += corr.x; cvLeft += corr.x; cvTop += corr.y; cvBottom += corr.y; } else if (cv.getMeasuredHeight() <= getHeight()) { // When the current view is as small as the screen in height, clamp // it vertically Point corr = getCorrection(getScrollBounds(cvLeft, cvTop, cvRight, cvBottom)); cvTop += corr.y; cvBottom += corr.y; } cv.layout(cvLeft, cvTop, cvRight, cvBottom); if (mCurrent > 0) { View lv = getOrCreateChild(mCurrent - 1); Point leftOffset = subScreenSizeOffset(lv); int gap = leftOffset.x + GAP + cvOffset.x; lv.layout( cvLeft - lv.getMeasuredWidth() - gap, (cvBottom + cvTop - lv.getMeasuredHeight()) / 2, cvLeft - gap, (cvBottom + cvTop + lv.getMeasuredHeight()) / 2); } if (mCurrent + 1 < mAdapter.getCount()) { View rv = getOrCreateChild(mCurrent + 1); Point rightOffset = subScreenSizeOffset(rv); int gap = cvOffset.x + GAP + rightOffset.x; rv.layout( cvRight + gap, (cvBottom + cvTop - rv.getMeasuredHeight()) / 2, cvRight + rv.getMeasuredWidth() + gap, (cvBottom + cvTop + rv.getMeasuredHeight()) / 2); } invalidate(); }
@SuppressLint("WrongCall") @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if (mAdapter == null) { return; } // Force the OS to redraw this view invalidate(); // If the data changed then reset everything and render from scratch at the same offset as last // time if (mDataChanged) { int oldCurrentX = mCurrentX; initView(); removeAllViewsInLayout(); mNextX = oldCurrentX; mDataChanged = false; } // If restoring from a rotation if (mRestoreX != null) { mNextX = mRestoreX; mRestoreX = null; } // If in a fling if (mFlingTracker.computeScrollOffset()) { // Compute the next position mNextX = mFlingTracker.getCurrX(); } // Prevent scrolling past 0 so you can't scroll past the end of the list to the left if (mNextX < 0) { mNextX = 0; // Show an edge effect absorbing the current velocity if (mEdgeGlowLeft.isFinished()) { mEdgeGlowLeft.onAbsorb((int) determineFlingAbsorbVelocity()); } mFlingTracker.forceFinished(true); setCurrentScrollState(OnScrollStateChangedListener.ScrollState.SCROLL_STATE_IDLE); } else if (mNextX > mMaxX) { // Clip the maximum scroll position at mMaxX so you can't scroll past the end of the list to // the right mNextX = mMaxX; // Show an edge effect absorbing the current velocity if (mEdgeGlowRight.isFinished()) { mEdgeGlowRight.onAbsorb((int) determineFlingAbsorbVelocity()); } mFlingTracker.forceFinished(true); setCurrentScrollState(OnScrollStateChangedListener.ScrollState.SCROLL_STATE_IDLE); } // Calculate our delta from the last time the view was drawn int dx = mCurrentX - mNextX; removeNonVisibleChildren(dx); fillList(dx); positionChildren(dx); // Since the view has now been drawn, update our current position mCurrentX = mNextX; // If we have scrolled enough to lay out all views, then determine the maximum scroll position // now if (determineMaxX()) { // Redo the layout pass since we now know the maximum scroll position onLayout(changed, left, top, right, bottom); return; } // If the fling has finished if (mFlingTracker.isFinished()) { // If the fling just ended if (mCurrentScrollState == OnScrollStateChangedListener.ScrollState.SCROLL_STATE_FLING) { setCurrentScrollState(OnScrollStateChangedListener.ScrollState.SCROLL_STATE_IDLE); } } else { // Still in a fling so schedule the next frame ViewCompat.postOnAnimation(this, mDelayedLayout); } }