Source code
package android.support.v7.widget;
import android.content.Context;
import android.graphics.PointF;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable.Creator;
import android.support.v4.media.TransportMediator;
import android.support.v4.view.accessibility.AccessibilityEventCompat;
import android.support.v4.view.accessibility.AccessibilityRecordCompat;
import android.support.v7.widget.RecyclerView.LayoutManager;
import android.support.v7.widget.RecyclerView.LayoutManager.Properties;
import android.support.v7.widget.RecyclerView.LayoutParams;
import android.support.v7.widget.RecyclerView.Recycler;
import android.support.v7.widget.RecyclerView.State;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.support.v7.widget.helper.ItemTouchHelper.ViewDropHandler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import java.util.List;
public class LinearLayoutManager extends LayoutManager implements ViewDropHandler {
private static final boolean DEBUG = false;
public static final int HORIZONTAL = 0;
public static final int INVALID_OFFSET = Integer.MIN_VALUE;
private static final float MAX_SCROLL_FACTOR = 0.33f;
private static final String TAG = "LinearLayoutManager";
public static final int VERTICAL = 1;
final AnchorInfo mAnchorInfo;
private boolean mLastStackFromEnd;
private LayoutState mLayoutState;
int mOrientation;
OrientationHelper mOrientationHelper;
SavedState mPendingSavedState;
int mPendingScrollPosition;
int mPendingScrollPositionOffset;
private boolean mRecycleChildrenOnDetach;
private boolean mReverseLayout;
boolean mShouldReverseLayout;
private boolean mSmoothScrollbarEnabled;
private boolean mStackFromEnd;
class AnchorInfo {
int mCoordinate;
boolean mLayoutFromEnd;
int mPosition;
AnchorInfo() {
}
void reset() {
this.mPosition = -1;
this.mCoordinate = Integer.MIN_VALUE;
this.mLayoutFromEnd = false;
}
void assignCoordinateFromPadding() {
this.mCoordinate = this.mLayoutFromEnd ? LinearLayoutManager.this.mOrientationHelper.getEndAfterPadding() : LinearLayoutManager.this.mOrientationHelper.getStartAfterPadding();
}
public String toString() {
return "AnchorInfo{mPosition=" + this.mPosition + ", mCoordinate=" + this.mCoordinate + ", mLayoutFromEnd=" + this.mLayoutFromEnd + '}';
}
private boolean isViewValidAsAnchor(View child, State state) {
LayoutParams lp = (LayoutParams) child.getLayoutParams();
return !lp.isItemRemoved() && lp.getViewLayoutPosition() >= 0 && lp.getViewLayoutPosition() < state.getItemCount();
}
public void assignFromViewAndKeepVisibleRect(View child) {
int spaceChange = LinearLayoutManager.this.mOrientationHelper.getTotalSpaceChange();
if (spaceChange >= 0) {
assignFromView(child);
return;
}
this.mPosition = LinearLayoutManager.this.getPosition(child);
int startMargin;
if (this.mLayoutFromEnd) {
int previousEndMargin = (LinearLayoutManager.this.mOrientationHelper.getEndAfterPadding() - spaceChange) - LinearLayoutManager.this.mOrientationHelper.getDecoratedEnd(child);
this.mCoordinate = LinearLayoutManager.this.mOrientationHelper.getEndAfterPadding() - previousEndMargin;
if (previousEndMargin > 0) {
int estimatedChildStart = this.mCoordinate - LinearLayoutManager.this.mOrientationHelper.getDecoratedMeasurement(child);
int layoutStart = LinearLayoutManager.this.mOrientationHelper.getStartAfterPadding();
startMargin = estimatedChildStart - (layoutStart + Math.min(LinearLayoutManager.this.mOrientationHelper.getDecoratedStart(child) - layoutStart, 0));
if (startMargin < 0) {
this.mCoordinate += Math.min(previousEndMargin, -startMargin);
return;
}
return;
}
return;
}
int childStart = LinearLayoutManager.this.mOrientationHelper.getDecoratedStart(child);
startMargin = childStart - LinearLayoutManager.this.mOrientationHelper.getStartAfterPadding();
this.mCoordinate = childStart;
if (startMargin > 0) {
int endMargin = (LinearLayoutManager.this.mOrientationHelper.getEndAfterPadding() - Math.min(0, (LinearLayoutManager.this.mOrientationHelper.getEndAfterPadding() - spaceChange) - LinearLayoutManager.this.mOrientationHelper.getDecoratedEnd(child))) - (childStart + LinearLayoutManager.this.mOrientationHelper.getDecoratedMeasurement(child));
if (endMargin < 0) {
this.mCoordinate -= Math.min(startMargin, -endMargin);
}
}
}
public void assignFromView(View child) {
if (this.mLayoutFromEnd) {
this.mCoordinate = LinearLayoutManager.this.mOrientationHelper.getDecoratedEnd(child) + LinearLayoutManager.this.mOrientationHelper.getTotalSpaceChange();
} else {
this.mCoordinate = LinearLayoutManager.this.mOrientationHelper.getDecoratedStart(child);
}
this.mPosition = LinearLayoutManager.this.getPosition(child);
}
}
protected static class LayoutChunkResult {
public int mConsumed;
public boolean mFinished;
public boolean mFocusable;
public boolean mIgnoreConsumed;
protected LayoutChunkResult() {
}
void resetInternal() {
this.mConsumed = 0;
this.mFinished = false;
this.mIgnoreConsumed = false;
this.mFocusable = false;
}
}
static class LayoutState {
static final int INVALID_LAYOUT = Integer.MIN_VALUE;
static final int ITEM_DIRECTION_HEAD = -1;
static final int ITEM_DIRECTION_TAIL = 1;
static final int LAYOUT_END = 1;
static final int LAYOUT_START = -1;
static final int SCOLLING_OFFSET_NaN = Integer.MIN_VALUE;
static final String TAG = "LinearLayoutManager#LayoutState";
int mAvailable;
int mCurrentPosition;
int mExtra = 0;
boolean mIsPreLayout = false;
int mItemDirection;
int mLastScrollDelta;
int mLayoutDirection;
int mOffset;
boolean mRecycle = true;
List<ViewHolder> mScrapList = null;
int mScrollingOffset;
LayoutState() {
}
boolean hasMore(State state) {
return this.mCurrentPosition >= 0 && this.mCurrentPosition < state.getItemCount();
}
View next(Recycler recycler) {
if (this.mScrapList != null) {
return nextViewFromScrapList();
}
View view = recycler.getViewForPosition(this.mCurrentPosition);
this.mCurrentPosition += this.mItemDirection;
return view;
}
private View nextViewFromScrapList() {
int size = this.mScrapList.size();
for (int i = 0; i < size; i++) {
View view = ((ViewHolder) this.mScrapList.get(i)).itemView;
LayoutParams lp = (LayoutParams) view.getLayoutParams();
if (!lp.isItemRemoved() && this.mCurrentPosition == lp.getViewLayoutPosition()) {
assignPositionFromScrapList(view);
return view;
}
}
return null;
}
public void assignPositionFromScrapList() {
assignPositionFromScrapList(null);
}
public void assignPositionFromScrapList(View ignore) {
View closest = nextViewInLimitedList(ignore);
if (closest == null) {
this.mCurrentPosition = -1;
} else {
this.mCurrentPosition = ((LayoutParams) closest.getLayoutParams()).getViewLayoutPosition();
}
}
public View nextViewInLimitedList(View ignore) {
int size = this.mScrapList.size();
View closest = null;
int closestDistance = ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED;
for (int i = 0; i < size; i++) {
View view = ((ViewHolder) this.mScrapList.get(i)).itemView;
LayoutParams lp = (LayoutParams) view.getLayoutParams();
if (!(view == ignore || lp.isItemRemoved())) {
int distance = (lp.getViewLayoutPosition() - this.mCurrentPosition) * this.mItemDirection;
if (distance >= 0 && distance < closestDistance) {
closest = view;
closestDistance = distance;
if (distance == 0) {
break;
}
}
}
}
return closest;
}
void log() {
Log.d(TAG, "avail:" + this.mAvailable + ", ind:" + this.mCurrentPosition + ", dir:" + this.mItemDirection + ", offset:" + this.mOffset + ", layoutDir:" + this.mLayoutDirection);
}
}
public static class SavedState implements Parcelable {
public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
boolean mAnchorLayoutFromEnd;
int mAnchorOffset;
int mAnchorPosition;
SavedState(Parcel in) {
boolean z = true;
this.mAnchorPosition = in.readInt();
this.mAnchorOffset = in.readInt();
if (in.readInt() != 1) {
z = false;
}
this.mAnchorLayoutFromEnd = z;
}
public SavedState(SavedState other) {
this.mAnchorPosition = other.mAnchorPosition;
this.mAnchorOffset = other.mAnchorOffset;
this.mAnchorLayoutFromEnd = other.mAnchorLayoutFromEnd;
}
boolean hasValidAnchor() {
return this.mAnchorPosition >= 0;
}
void invalidateAnchor() {
this.mAnchorPosition = -1;
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.mAnchorPosition);
dest.writeInt(this.mAnchorOffset);
dest.writeInt(this.mAnchorLayoutFromEnd ? 1 : 0);
}
}
public LinearLayoutManager(Context context) {
this(context, 1, false);
}
public LinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
this.mReverseLayout = false;
this.mShouldReverseLayout = false;
this.mStackFromEnd = false;
this.mSmoothScrollbarEnabled = true;
this.mPendingScrollPosition = -1;
this.mPendingScrollPositionOffset = Integer.MIN_VALUE;
this.mPendingSavedState = null;
this.mAnchorInfo = new AnchorInfo();
setOrientation(orientation);
setReverseLayout(reverseLayout);
}
public LinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
this.mReverseLayout = false;
this.mShouldReverseLayout = false;
this.mStackFromEnd = false;
this.mSmoothScrollbarEnabled = true;
this.mPendingScrollPosition = -1;
this.mPendingScrollPositionOffset = Integer.MIN_VALUE;
this.mPendingSavedState = null;
this.mAnchorInfo = new AnchorInfo();
Properties properties = LayoutManager.getProperties(context, attrs, defStyleAttr, defStyleRes);
setOrientation(properties.orientation);
setReverseLayout(properties.reverseLayout);
setStackFromEnd(properties.stackFromEnd);
}
public LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(-2, -2);
}
public boolean getRecycleChildrenOnDetach() {
return this.mRecycleChildrenOnDetach;
}
public void setRecycleChildrenOnDetach(boolean recycleChildrenOnDetach) {
this.mRecycleChildrenOnDetach = recycleChildrenOnDetach;
}
public void onDetachedFromWindow(RecyclerView view, Recycler recycler) {
super.onDetachedFromWindow(view, recycler);
if (this.mRecycleChildrenOnDetach) {
removeAndRecycleAllViews(recycler);
recycler.clear();
}
}
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
if (getChildCount() > 0) {
AccessibilityRecordCompat record = AccessibilityEventCompat.asRecord(event);
record.setFromIndex(findFirstVisibleItemPosition());
record.setToIndex(findLastVisibleItemPosition());
}
}
public Parcelable onSaveInstanceState() {
if (this.mPendingSavedState != null) {
return new SavedState(this.mPendingSavedState);
}
Parcelable state = new SavedState();
if (getChildCount() > 0) {
ensureLayoutState();
boolean didLayoutFromEnd = this.mLastStackFromEnd ^ this.mShouldReverseLayout;
state.mAnchorLayoutFromEnd = didLayoutFromEnd;
View refChild;
if (didLayoutFromEnd) {
refChild = getChildClosestToEnd();
state.mAnchorOffset = this.mOrientationHelper.getEndAfterPadding() - this.mOrientationHelper.getDecoratedEnd(refChild);
state.mAnchorPosition = getPosition(refChild);
return state;
}
refChild = getChildClosestToStart();
state.mAnchorPosition = getPosition(refChild);
state.mAnchorOffset = this.mOrientationHelper.getDecoratedStart(refChild) - this.mOrientationHelper.getStartAfterPadding();
return state;
}
state.invalidateAnchor();
return state;
}
public void onRestoreInstanceState(Parcelable state) {
if (state instanceof SavedState) {
this.mPendingSavedState = (SavedState) state;
requestLayout();
}
}
public boolean canScrollHorizontally() {
return this.mOrientation == 0;
}
public boolean canScrollVertically() {
return this.mOrientation == 1;
}
public void setStackFromEnd(boolean stackFromEnd) {
assertNotInLayoutOrScroll(null);
if (this.mStackFromEnd != stackFromEnd) {
this.mStackFromEnd = stackFromEnd;
requestLayout();
}
}
public boolean getStackFromEnd() {
return this.mStackFromEnd;
}
public int getOrientation() {
return this.mOrientation;
}
public void setOrientation(int orientation) {
if (orientation == 0 || orientation == 1) {
assertNotInLayoutOrScroll(null);
if (orientation != this.mOrientation) {
this.mOrientation = orientation;
this.mOrientationHelper = null;
requestLayout();
return;
}
return;
}
throw new IllegalArgumentException("invalid orientation:" + orientation);
}
private void resolveShouldLayoutReverse() {
boolean z = true;
if (this.mOrientation == 1 || !isLayoutRTL()) {
this.mShouldReverseLayout = this.mReverseLayout;
return;
}
if (this.mReverseLayout) {
z = false;
}
this.mShouldReverseLayout = z;
}
public boolean getReverseLayout() {
return this.mReverseLayout;
}
public void setReverseLayout(boolean reverseLayout) {
assertNotInLayoutOrScroll(null);
if (reverseLayout != this.mReverseLayout) {
this.mReverseLayout = reverseLayout;
requestLayout();
}
}
public View findViewByPosition(int position) {
int childCount = getChildCount();
if (childCount == 0) {
return null;
}
int viewPosition = position - getPosition(getChildAt(0));
if (viewPosition >= 0 && viewPosition < childCount) {
View child = getChildAt(viewPosition);
if (getPosition(child) == position) {
return child;
}
}
return super.findViewByPosition(position);
}
protected int getExtraLayoutSpace(State state) {
if (state.hasTargetScrollPosition()) {
return this.mOrientationHelper.getTotalSpace();
}
return 0;
}
public void smoothScrollToPosition(RecyclerView recyclerView, State state, int position) {
LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext()) {
public PointF computeScrollVectorForPosition(int targetPosition) {
return LinearLayoutManager.this.computeScrollVectorForPosition(targetPosition);
}
};
linearSmoothScroller.setTargetPosition(position);
startSmoothScroll(linearSmoothScroller);
}
public PointF computeScrollVectorForPosition(int targetPosition) {
boolean z = false;
if (getChildCount() == 0) {
return null;
}
int direction;
if (targetPosition < getPosition(getChildAt(0))) {
z = true;
}
if (z != this.mShouldReverseLayout) {
direction = -1;
} else {
direction = 1;
}
if (this.mOrientation == 0) {
return new PointF((float) direction, 0.0f);
}
return new PointF(0.0f, (float) direction);
}
public void onLayoutChildren(Recycler recycler, State state) {
if (!(this.mPendingSavedState == null && this.mPendingScrollPosition == -1) && state.getItemCount() == 0) {
removeAndRecycleAllViews(recycler);
return;
}
int extraForEnd;
int extraForStart;
int startOffset;
int endOffset;
if (this.mPendingSavedState != null && this.mPendingSavedState.hasValidAnchor()) {
this.mPendingScrollPosition = this.mPendingSavedState.mAnchorPosition;
}
ensureLayoutState();
this.mLayoutState.mRecycle = false;
resolveShouldLayoutReverse();
this.mAnchorInfo.reset();
this.mAnchorInfo.mLayoutFromEnd = this.mShouldReverseLayout ^ this.mStackFromEnd;
updateAnchorInfoForLayout(recycler, state, this.mAnchorInfo);
int extra = getExtraLayoutSpace(state);
if (this.mLayoutState.mLastScrollDelta >= 0) {
extraForEnd = extra;
extraForStart = 0;
} else {
extraForStart = extra;
extraForEnd = 0;
}
extraForStart += this.mOrientationHelper.getStartAfterPadding();
extraForEnd += this.mOrientationHelper.getEndPadding();
if (!(!state.isPreLayout() || this.mPendingScrollPosition == -1 || this.mPendingScrollPositionOffset == Integer.MIN_VALUE)) {
View existing = findViewByPosition(this.mPendingScrollPosition);
if (existing != null) {
int upcomingOffset;
if (this.mShouldReverseLayout) {
upcomingOffset = (this.mOrientationHelper.getEndAfterPadding() - this.mOrientationHelper.getDecoratedEnd(existing)) - this.mPendingScrollPositionOffset;
} else {
upcomingOffset = this.mPendingScrollPositionOffset - (this.mOrientationHelper.getDecoratedStart(existing) - this.mOrientationHelper.getStartAfterPadding());
}
if (upcomingOffset > 0) {
extraForStart += upcomingOffset;
} else {
extraForEnd -= upcomingOffset;
}
}
}
onAnchorReady(recycler, state, this.mAnchorInfo);
detachAndScrapAttachedViews(recycler);
this.mLayoutState.mIsPreLayout = state.isPreLayout();
LayoutState layoutState;
if (this.mAnchorInfo.mLayoutFromEnd) {
updateLayoutStateToFillStart(this.mAnchorInfo);
this.mLayoutState.mExtra = extraForStart;
fill(recycler, this.mLayoutState, state, false);
startOffset = this.mLayoutState.mOffset;
int firstElement = this.mLayoutState.mCurrentPosition;
if (this.mLayoutState.mAvailable > 0) {
extraForEnd += this.mLayoutState.mAvailable;
}
updateLayoutStateToFillEnd(this.mAnchorInfo);
this.mLayoutState.mExtra = extraForEnd;
layoutState = this.mLayoutState;
layoutState.mCurrentPosition += this.mLayoutState.mItemDirection;
fill(recycler, this.mLayoutState, state, false);
endOffset = this.mLayoutState.mOffset;
if (this.mLayoutState.mAvailable > 0) {
extraForStart = this.mLayoutState.mAvailable;
updateLayoutStateToFillStart(firstElement, startOffset);
this.mLayoutState.mExtra = extraForStart;
fill(recycler, this.mLayoutState, state, false);
startOffset = this.mLayoutState.mOffset;
}
} else {
updateLayoutStateToFillEnd(this.mAnchorInfo);
this.mLayoutState.mExtra = extraForEnd;
fill(recycler, this.mLayoutState, state, false);
endOffset = this.mLayoutState.mOffset;
int lastElement = this.mLayoutState.mCurrentPosition;
if (this.mLayoutState.mAvailable > 0) {
extraForStart += this.mLayoutState.mAvailable;
}
updateLayoutStateToFillStart(this.mAnchorInfo);
this.mLayoutState.mExtra = extraForStart;
layoutState = this.mLayoutState;
layoutState.mCurrentPosition += this.mLayoutState.mItemDirection;
fill(recycler, this.mLayoutState, state, false);
startOffset = this.mLayoutState.mOffset;
if (this.mLayoutState.mAvailable > 0) {
extraForEnd = this.mLayoutState.mAvailable;
updateLayoutStateToFillEnd(lastElement, endOffset);
this.mLayoutState.mExtra = extraForEnd;
fill(recycler, this.mLayoutState, state, false);
endOffset = this.mLayoutState.mOffset;
}
}
if (getChildCount() > 0) {
int fixOffset;
if ((this.mShouldReverseLayout ^ this.mStackFromEnd) != 0) {
fixOffset = fixLayoutEndGap(endOffset, recycler, state, true);
startOffset += fixOffset;
endOffset += fixOffset;
fixOffset = fixLayoutStartGap(startOffset, recycler, state, false);
startOffset += fixOffset;
endOffset += fixOffset;
} else {
fixOffset = fixLayoutStartGap(startOffset, recycler, state, true);
startOffset += fixOffset;
endOffset += fixOffset;
fixOffset = fixLayoutEndGap(endOffset, recycler, state, false);
startOffset += fixOffset;
endOffset += fixOffset;
}
}
layoutForPredictiveAnimations(recycler, state, startOffset, endOffset);
if (!state.isPreLayout()) {
this.mPendingScrollPosition = -1;
this.mPendingScrollPositionOffset = Integer.MIN_VALUE;
this.mOrientationHelper.onLayoutComplete();
}
this.mLastStackFromEnd = this.mStackFromEnd;
this.mPendingSavedState = null;
}
void onAnchorReady(Recycler recycler, State state, AnchorInfo anchorInfo) {
}
private void layoutForPredictiveAnimations(Recycler recycler, State state, int startOffset, int endOffset) {
if (state.willRunPredictiveAnimations() && getChildCount() != 0 && !state.isPreLayout() && supportsPredictiveItemAnimations()) {
int scrapExtraStart = 0;
int scrapExtraEnd = 0;
List<ViewHolder> scrapList = recycler.getScrapList();
int scrapSize = scrapList.size();
int firstChildPos = getPosition(getChildAt(0));
for (int i = 0; i < scrapSize; i++) {
ViewHolder scrap = (ViewHolder) scrapList.get(i);
if (!scrap.isRemoved()) {
if (((scrap.getLayoutPosition() < firstChildPos) != this.mShouldReverseLayout ? -1 : 1) == -1) {
scrapExtraStart += this.mOrientationHelper.getDecoratedMeasurement(scrap.itemView);
} else {
scrapExtraEnd += this.mOrientationHelper.getDecoratedMeasurement(scrap.itemView);
}
}
}
this.mLayoutState.mScrapList = scrapList;
if (scrapExtraStart > 0) {
updateLayoutStateToFillStart(getPosition(getChildClosestToStart()), startOffset);
this.mLayoutState.mExtra = scrapExtraStart;
this.mLayoutState.mAvailable = 0;
this.mLayoutState.assignPositionFromScrapList();
fill(recycler, this.mLayoutState, state, false);
}
if (scrapExtraEnd > 0) {
updateLayoutStateToFillEnd(getPosition(getChildClosestToEnd()), endOffset);
this.mLayoutState.mExtra = scrapExtraEnd;
this.mLayoutState.mAvailable = 0;
this.mLayoutState.assignPositionFromScrapList();
fill(recycler, this.mLayoutState, state, false);
}
this.mLayoutState.mScrapList = null;
}
}
private void updateAnchorInfoForLayout(Recycler recycler, State state, AnchorInfo anchorInfo) {
if (!updateAnchorFromPendingData(state, anchorInfo) && !updateAnchorFromChildren(recycler, state, anchorInfo)) {
anchorInfo.assignCoordinateFromPadding();
anchorInfo.mPosition = this.mStackFromEnd ? state.getItemCount() - 1 : 0;
}
}
private boolean updateAnchorFromChildren(Recycler recycler, State state, AnchorInfo anchorInfo) {
if (getChildCount() == 0) {
return false;
}
View focused = getFocusedChild();
if (focused != null && anchorInfo.isViewValidAsAnchor(focused, state)) {
anchorInfo.assignFromViewAndKeepVisibleRect(focused);
return true;
} else if (this.mLastStackFromEnd != this.mStackFromEnd) {
return false;
} else {
View referenceChild = anchorInfo.mLayoutFromEnd ? findReferenceChildClosestToEnd(recycler, state) : findReferenceChildClosestToStart(recycler, state);
if (referenceChild == null) {
return false;
}
anchorInfo.assignFromView(referenceChild);
if (!state.isPreLayout() && supportsPredictiveItemAnimations()) {
boolean notVisible;
if (this.mOrientationHelper.getDecoratedStart(referenceChild) >= this.mOrientationHelper.getEndAfterPadding() || this.mOrientationHelper.getDecoratedEnd(referenceChild) < this.mOrientationHelper.getStartAfterPadding()) {
notVisible = true;
} else {
notVisible = false;
}
if (notVisible) {
anchorInfo.mCoordinate = anchorInfo.mLayoutFromEnd ? this.mOrientationHelper.getEndAfterPadding() : this.mOrientationHelper.getStartAfterPadding();
}
}
return true;
}
}
private boolean updateAnchorFromPendingData(State state, AnchorInfo anchorInfo) {
boolean z = false;
if (state.isPreLayout() || this.mPendingScrollPosition == -1) {
return false;
}
if (this.mPendingScrollPosition < 0 || this.mPendingScrollPosition >= state.getItemCount()) {
this.mPendingScrollPosition = -1;
this.mPendingScrollPositionOffset = Integer.MIN_VALUE;
return false;
}
anchorInfo.mPosition = this.mPendingScrollPosition;
if (this.mPendingSavedState != null && this.mPendingSavedState.hasValidAnchor()) {
anchorInfo.mLayoutFromEnd = this.mPendingSavedState.mAnchorLayoutFromEnd;
if (anchorInfo.mLayoutFromEnd) {
anchorInfo.mCoordinate = this.mOrientationHelper.getEndAfterPadding() - this.mPendingSavedState.mAnchorOffset;
return true;
}
anchorInfo.mCoordinate = this.mOrientationHelper.getStartAfterPadding() + this.mPendingSavedState.mAnchorOffset;
return true;
} else if (this.mPendingScrollPositionOffset == Integer.MIN_VALUE) {
View child = findViewByPosition(this.mPendingScrollPosition);
if (child == null) {
if (getChildCount() > 0) {
boolean z2;
if (this.mPendingScrollPosition < getPosition(getChildAt(0))) {
z2 = true;
} else {
z2 = false;
}
if (z2 == this.mShouldReverseLayout) {
z = true;
}
anchorInfo.mLayoutFromEnd = z;
}
anchorInfo.assignCoordinateFromPadding();
return true;
} else if (this.mOrientationHelper.getDecoratedMeasurement(child) > this.mOrientationHelper.getTotalSpace()) {
anchorInfo.assignCoordinateFromPadding();
return true;
} else if (this.mOrientationHelper.getDecoratedStart(child) - this.mOrientationHelper.getStartAfterPadding() < 0) {
anchorInfo.mCoordinate = this.mOrientationHelper.getStartAfterPadding();
anchorInfo.mLayoutFromEnd = false;
return true;
} else if (this.mOrientationHelper.getEndAfterPadding() - this.mOrientationHelper.getDecoratedEnd(child) < 0) {
anchorInfo.mCoordinate = this.mOrientationHelper.getEndAfterPadding();
anchorInfo.mLayoutFromEnd = true;
return true;
} else {
anchorInfo.mCoordinate = anchorInfo.mLayoutFromEnd ? this.mOrientationHelper.getDecoratedEnd(child) + this.mOrientationHelper.getTotalSpaceChange() : this.mOrientationHelper.getDecoratedStart(child);
return true;
}
} else {
anchorInfo.mLayoutFromEnd = this.mShouldReverseLayout;
if (this.mShouldReverseLayout) {
anchorInfo.mCoordinate = this.mOrientationHelper.getEndAfterPadding() - this.mPendingScrollPositionOffset;
return true;
}
anchorInfo.mCoordinate = this.mOrientationHelper.getStartAfterPadding() + this.mPendingScrollPositionOffset;
return true;
}
}
private int fixLayoutEndGap(int endOffset, Recycler recycler, State state, boolean canOffsetChildren) {
int gap = this.mOrientationHelper.getEndAfterPadding() - endOffset;
if (gap <= 0) {
return 0;
}
int fixOffset = -scrollBy(-gap, recycler, state);
endOffset += fixOffset;
if (canOffsetChildren) {
gap = this.mOrientationHelper.getEndAfterPadding() - endOffset;
if (gap > 0) {
this.mOrientationHelper.offsetChildren(gap);
return gap + fixOffset;
}
}
return fixOffset;
}
private int fixLayoutStartGap(int startOffset, Recycler recycler, State state, boolean canOffsetChildren) {
int gap = startOffset - this.mOrientationHelper.getStartAfterPadding();
if (gap <= 0) {
return 0;
}
int fixOffset = -scrollBy(gap, recycler, state);
startOffset += fixOffset;
if (canOffsetChildren) {
gap = startOffset - this.mOrientationHelper.getStartAfterPadding();
if (gap > 0) {
this.mOrientationHelper.offsetChildren(-gap);
return fixOffset - gap;
}
}
return fixOffset;
}
private void updateLayoutStateToFillEnd(AnchorInfo anchorInfo) {
updateLayoutStateToFillEnd(anchorInfo.mPosition, anchorInfo.mCoordinate);
}
private void updateLayoutStateToFillEnd(int itemPosition, int offset) {
this.mLayoutState.mAvailable = this.mOrientationHelper.getEndAfterPadding() - offset;
this.mLayoutState.mItemDirection = this.mShouldReverseLayout ? -1 : 1;
this.mLayoutState.mCurrentPosition = itemPosition;
this.mLayoutState.mLayoutDirection = 1;
this.mLayoutState.mOffset = offset;
this.mLayoutState.mScrollingOffset = Integer.MIN_VALUE;
}
private void updateLayoutStateToFillStart(AnchorInfo anchorInfo) {
updateLayoutStateToFillStart(anchorInfo.mPosition, anchorInfo.mCoordinate);
}
private void updateLayoutStateToFillStart(int itemPosition, int offset) {
this.mLayoutState.mAvailable = offset - this.mOrientationHelper.getStartAfterPadding();
this.mLayoutState.mCurrentPosition = itemPosition;
this.mLayoutState.mItemDirection = this.mShouldReverseLayout ? 1 : -1;
this.mLayoutState.mLayoutDirection = -1;
this.mLayoutState.mOffset = offset;
this.mLayoutState.mScrollingOffset = Integer.MIN_VALUE;
}
protected boolean isLayoutRTL() {
return getLayoutDirection() == 1;
}
void ensureLayoutState() {
if (this.mLayoutState == null) {
this.mLayoutState = createLayoutState();
}
if (this.mOrientationHelper == null) {
this.mOrientationHelper = OrientationHelper.createOrientationHelper(this, this.mOrientation);
}
}
LayoutState createLayoutState() {
return new LayoutState();
}
public void scrollToPosition(int position) {
this.mPendingScrollPosition = position;
this.mPendingScrollPositionOffset = Integer.MIN_VALUE;
if (this.mPendingSavedState != null) {
this.mPendingSavedState.invalidateAnchor();
}
requestLayout();
}
public void scrollToPositionWithOffset(int position, int offset) {
this.mPendingScrollPosition = position;
this.mPendingScrollPositionOffset = offset;
if (this.mPendingSavedState != null) {
this.mPendingSavedState.invalidateAnchor();
}
requestLayout();
}
public int scrollHorizontallyBy(int dx, Recycler recycler, State state) {
if (this.mOrientation == 1) {
return 0;
}
return scrollBy(dx, recycler, state);
}
public int scrollVerticallyBy(int dy, Recycler recycler, State state) {
if (this.mOrientation == 0) {
return 0;
}
return scrollBy(dy, recycler, state);
}
public int computeHorizontalScrollOffset(State state) {
return computeScrollOffset(state);
}
public int computeVerticalScrollOffset(State state) {
return computeScrollOffset(state);
}
public int computeHorizontalScrollExtent(State state) {
return computeScrollExtent(state);
}
public int computeVerticalScrollExtent(State state) {
return computeScrollExtent(state);
}
public int computeHorizontalScrollRange(State state) {
return computeScrollRange(state);
}
public int computeVerticalScrollRange(State state) {
return computeScrollRange(state);
}
private int computeScrollOffset(State state) {
boolean z = false;
if (getChildCount() == 0) {
return 0;
}
ensureLayoutState();
OrientationHelper orientationHelper = this.mOrientationHelper;
View findFirstVisibleChildClosestToStart = findFirstVisibleChildClosestToStart(!this.mSmoothScrollbarEnabled, true);
if (!this.mSmoothScrollbarEnabled) {
z = true;
}
return ScrollbarHelper.computeScrollOffset(state, orientationHelper, findFirstVisibleChildClosestToStart, findFirstVisibleChildClosestToEnd(z, true), this, this.mSmoothScrollbarEnabled, this.mShouldReverseLayout);
}
private int computeScrollExtent(State state) {
boolean z = false;
if (getChildCount() == 0) {
return 0;
}
ensureLayoutState();
OrientationHelper orientationHelper = this.mOrientationHelper;
View findFirstVisibleChildClosestToStart = findFirstVisibleChildClosestToStart(!this.mSmoothScrollbarEnabled, true);
if (!this.mSmoothScrollbarEnabled) {
z = true;
}
return ScrollbarHelper.computeScrollExtent(state, orientationHelper, findFirstVisibleChildClosestToStart, findFirstVisibleChildClosestToEnd(z, true), this, this.mSmoothScrollbarEnabled);
}
private int computeScrollRange(State state) {
boolean z = false;
if (getChildCount() == 0) {
return 0;
}
ensureLayoutState();
OrientationHelper orientationHelper = this.mOrientationHelper;
View findFirstVisibleChildClosestToStart = findFirstVisibleChildClosestToStart(!this.mSmoothScrollbarEnabled, true);
if (!this.mSmoothScrollbarEnabled) {
z = true;
}
return ScrollbarHelper.computeScrollRange(state, orientationHelper, findFirstVisibleChildClosestToStart, findFirstVisibleChildClosestToEnd(z, true), this, this.mSmoothScrollbarEnabled);
}
public void setSmoothScrollbarEnabled(boolean enabled) {
this.mSmoothScrollbarEnabled = enabled;
}
public boolean isSmoothScrollbarEnabled() {
return this.mSmoothScrollbarEnabled;
}
private void updateLayoutState(int layoutDirection, int requiredSpace, boolean canUseExistingSpace, State state) {
int fastScrollSpace;
int i = -1;
int i2 = 1;
this.mLayoutState.mExtra = getExtraLayoutSpace(state);
this.mLayoutState.mLayoutDirection = layoutDirection;
LayoutState layoutState;
View child;
if (layoutDirection == 1) {
layoutState = this.mLayoutState;
layoutState.mExtra += this.mOrientationHelper.getEndPadding();
child = getChildClosestToEnd();
layoutState = this.mLayoutState;
if (!this.mShouldReverseLayout) {
i = 1;
}
layoutState.mItemDirection = i;
this.mLayoutState.mCurrentPosition = getPosition(child) + this.mLayoutState.mItemDirection;
this.mLayoutState.mOffset = this.mOrientationHelper.getDecoratedEnd(child);
fastScrollSpace = this.mOrientationHelper.getDecoratedEnd(child) - this.mOrientationHelper.getEndAfterPadding();
} else {
child = getChildClosestToStart();
layoutState = this.mLayoutState;
layoutState.mExtra += this.mOrientationHelper.getStartAfterPadding();
layoutState = this.mLayoutState;
if (!this.mShouldReverseLayout) {
i2 = -1;
}
layoutState.mItemDirection = i2;
this.mLayoutState.mCurrentPosition = getPosition(child) + this.mLayoutState.mItemDirection;
this.mLayoutState.mOffset = this.mOrientationHelper.getDecoratedStart(child);
fastScrollSpace = (-this.mOrientationHelper.getDecoratedStart(child)) + this.mOrientationHelper.getStartAfterPadding();
}
this.mLayoutState.mAvailable = requiredSpace;
if (canUseExistingSpace) {
LayoutState layoutState2 = this.mLayoutState;
layoutState2.mAvailable -= fastScrollSpace;
}
this.mLayoutState.mScrollingOffset = fastScrollSpace;
}
int scrollBy(int dy, Recycler recycler, State state) {
int i = 0;
if (!(getChildCount() == 0 || dy == 0)) {
this.mLayoutState.mRecycle = true;
ensureLayoutState();
int layoutDirection = dy > 0 ? 1 : -1;
int absDy = Math.abs(dy);
updateLayoutState(layoutDirection, absDy, true, state);
int consumed = this.mLayoutState.mScrollingOffset + fill(recycler, this.mLayoutState, state, false);
if (consumed >= 0) {
if (absDy > consumed) {
i = layoutDirection * consumed;
} else {
i = dy;
}
this.mOrientationHelper.offsetChildren(-i);
this.mLayoutState.mLastScrollDelta = i;
}
}
return i;
}
public void assertNotInLayoutOrScroll(String message) {
if (this.mPendingSavedState == null) {
super.assertNotInLayoutOrScroll(message);
}
}
private void recycleChildren(Recycler recycler, int startIndex, int endIndex) {
if (startIndex != endIndex) {
int i;
if (endIndex > startIndex) {
for (i = endIndex - 1; i >= startIndex; i--) {
removeAndRecycleViewAt(i, recycler);
}
return;
}
for (i = startIndex; i > endIndex; i--) {
removeAndRecycleViewAt(i, recycler);
}
}
}
private void recycleViewsFromStart(Recycler recycler, int dt) {
if (dt >= 0) {
int limit = dt;
int childCount = getChildCount();
int i;
if (this.mShouldReverseLayout) {
for (i = childCount - 1; i >= 0; i--) {
if (this.mOrientationHelper.getDecoratedEnd(getChildAt(i)) > limit) {
recycleChildren(recycler, childCount - 1, i);
return;
}
}
return;
}
for (i = 0; i < childCount; i++) {
if (this.mOrientationHelper.getDecoratedEnd(getChildAt(i)) > limit) {
recycleChildren(recycler, 0, i);
return;
}
}
}
}
private void recycleViewsFromEnd(Recycler recycler, int dt) {
int childCount = getChildCount();
if (dt >= 0) {
int limit = this.mOrientationHelper.getEnd() - dt;
int i;
if (this.mShouldReverseLayout) {
for (i = 0; i < childCount; i++) {
if (this.mOrientationHelper.getDecoratedStart(getChildAt(i)) < limit) {
recycleChildren(recycler, 0, i);
return;
}
}
return;
}
for (i = childCount - 1; i >= 0; i--) {
if (this.mOrientationHelper.getDecoratedStart(getChildAt(i)) < limit) {
recycleChildren(recycler, childCount - 1, i);
return;
}
}
}
}
private void recycleByLayoutState(Recycler recycler, LayoutState layoutState) {
if (!layoutState.mRecycle) {
return;
}
if (layoutState.mLayoutDirection == -1) {
recycleViewsFromEnd(recycler, layoutState.mScrollingOffset);
} else {
recycleViewsFromStart(recycler, layoutState.mScrollingOffset);
}
}
int fill(Recycler recycler, LayoutState layoutState, State state, boolean stopOnFocusable) {
int start = layoutState.mAvailable;
if (layoutState.mScrollingOffset != Integer.MIN_VALUE) {
if (layoutState.mAvailable < 0) {
layoutState.mScrollingOffset += layoutState.mAvailable;
}
recycleByLayoutState(recycler, layoutState);
}
int remainingSpace = layoutState.mAvailable + layoutState.mExtra;
LayoutChunkResult layoutChunkResult = new LayoutChunkResult();
while (remainingSpace > 0 && layoutState.hasMore(state)) {
layoutChunkResult.resetInternal();
layoutChunk(recycler, state, layoutState, layoutChunkResult);
if (!layoutChunkResult.mFinished) {
layoutState.mOffset += layoutChunkResult.mConsumed * layoutState.mLayoutDirection;
if (!(layoutChunkResult.mIgnoreConsumed && this.mLayoutState.mScrapList == null && state.isPreLayout())) {
layoutState.mAvailable -= layoutChunkResult.mConsumed;
remainingSpace -= layoutChunkResult.mConsumed;
}
if (layoutState.mScrollingOffset != Integer.MIN_VALUE) {
layoutState.mScrollingOffset += layoutChunkResult.mConsumed;
if (layoutState.mAvailable < 0) {
layoutState.mScrollingOffset += layoutState.mAvailable;
}
recycleByLayoutState(recycler, layoutState);
}
if (stopOnFocusable && layoutChunkResult.mFocusable) {
break;
}
} else {
break;
}
}
return start - layoutState.mAvailable;
}
void layoutChunk(Recycler recycler, State state, LayoutState layoutState, LayoutChunkResult result) {
View view = layoutState.next(recycler);
if (view == null) {
result.mFinished = true;
return;
}
int right;
int left;
int bottom;
int top;
LayoutParams params = (LayoutParams) view.getLayoutParams();
if (layoutState.mScrapList == null) {
if (this.mShouldReverseLayout == (layoutState.mLayoutDirection == -1)) {
addView(view);
} else {
addView(view, 0);
}
} else {
if (this.mShouldReverseLayout == (layoutState.mLayoutDirection == -1)) {
addDisappearingView(view);
} else {
addDisappearingView(view, 0);
}
}
measureChildWithMargins(view, 0, 0);
result.mConsumed = this.mOrientationHelper.getDecoratedMeasurement(view);
if (this.mOrientation == 1) {
if (isLayoutRTL()) {
right = getWidth() - getPaddingRight();
left = right - this.mOrientationHelper.getDecoratedMeasurementInOther(view);
} else {
left = getPaddingLeft();
right = left + this.mOrientationHelper.getDecoratedMeasurementInOther(view);
}
if (layoutState.mLayoutDirection == -1) {
bottom = layoutState.mOffset;
top = layoutState.mOffset - result.mConsumed;
} else {
top = layoutState.mOffset;
bottom = layoutState.mOffset + result.mConsumed;
}
} else {
top = getPaddingTop();
bottom = top + this.mOrientationHelper.getDecoratedMeasurementInOther(view);
if (layoutState.mLayoutDirection == -1) {
right = layoutState.mOffset;
left = layoutState.mOffset - result.mConsumed;
} else {
left = layoutState.mOffset;
right = layoutState.mOffset + result.mConsumed;
}
}
layoutDecorated(view, left + params.leftMargin, top + params.topMargin, right - params.rightMargin, bottom - params.bottomMargin);
if (params.isItemRemoved() || params.isItemChanged()) {
result.mIgnoreConsumed = true;
}
result.mFocusable = view.isFocusable();
}
private int convertFocusDirectionToLayoutDirection(int focusDirection) {
int i = 1;
int i2 = Integer.MIN_VALUE;
switch (focusDirection) {
case 1:
return -1;
case 2:
return 1;
case 17:
if (this.mOrientation != 0) {
return Integer.MIN_VALUE;
}
return -1;
case 33:
if (this.mOrientation != 1) {
return Integer.MIN_VALUE;
}
return -1;
case 66:
if (this.mOrientation != 0) {
i = Integer.MIN_VALUE;
}
return i;
case TransportMediator.KEYCODE_MEDIA_RECORD /*130*/:
if (this.mOrientation == 1) {
i2 = 1;
}
return i2;
default:
return Integer.MIN_VALUE;
}
}
private View getChildClosestToStart() {
return getChildAt(this.mShouldReverseLayout ? getChildCount() - 1 : 0);
}
private View getChildClosestToEnd() {
return getChildAt(this.mShouldReverseLayout ? 0 : getChildCount() - 1);
}
private View findFirstVisibleChildClosestToStart(boolean completelyVisible, boolean acceptPartiallyVisible) {
if (this.mShouldReverseLayout) {
return findOneVisibleChild(getChildCount() - 1, -1, completelyVisible, acceptPartiallyVisible);
}
return findOneVisibleChild(0, getChildCount(), completelyVisible, acceptPartiallyVisible);
}
private View findFirstVisibleChildClosestToEnd(boolean completelyVisible, boolean acceptPartiallyVisible) {
if (this.mShouldReverseLayout) {
return findOneVisibleChild(0, getChildCount(), completelyVisible, acceptPartiallyVisible);
}
return findOneVisibleChild(getChildCount() - 1, -1, completelyVisible, acceptPartiallyVisible);
}
private View findReferenceChildClosestToEnd(Recycler recycler, State state) {
return this.mShouldReverseLayout ? findFirstReferenceChild(recycler, state) : findLastReferenceChild(recycler, state);
}
private View findReferenceChildClosestToStart(Recycler recycler, State state) {
return this.mShouldReverseLayout ? findLastReferenceChild(recycler, state) : findFirstReferenceChild(recycler, state);
}
private View findFirstReferenceChild(Recycler recycler, State state) {
return findReferenceChild(recycler, state, 0, getChildCount(), state.getItemCount());
}
private View findLastReferenceChild(Recycler recycler, State state) {
return findReferenceChild(recycler, state, getChildCount() - 1, -1, state.getItemCount());
}
View findReferenceChild(Recycler recycler, State state, int start, int end, int itemCount) {
ensureLayoutState();
View invalidMatch = null;
View outOfBoundsMatch = null;
int boundsStart = this.mOrientationHelper.getStartAfterPadding();
int boundsEnd = this.mOrientationHelper.getEndAfterPadding();
int diff = end > start ? 1 : -1;
for (int i = start; i != end; i += diff) {
View childAt = getChildAt(i);
int position = getPosition(childAt);
if (position >= 0 && position < itemCount) {
if (((LayoutParams) childAt.getLayoutParams()).isItemRemoved()) {
if (invalidMatch == null) {
invalidMatch = childAt;
}
} else if (this.mOrientationHelper.getDecoratedStart(childAt) < boundsEnd && this.mOrientationHelper.getDecoratedEnd(childAt) >= boundsStart) {
return childAt;
} else {
if (outOfBoundsMatch == null) {
outOfBoundsMatch = childAt;
}
}
}
}
if (outOfBoundsMatch == null) {
outOfBoundsMatch = invalidMatch;
}
return outOfBoundsMatch;
}
public int findFirstVisibleItemPosition() {
View child = findOneVisibleChild(0, getChildCount(), false, true);
return child == null ? -1 : getPosition(child);
}
public int findFirstCompletelyVisibleItemPosition() {
View child = findOneVisibleChild(0, getChildCount(), true, false);
return child == null ? -1 : getPosition(child);
}
public int findLastVisibleItemPosition() {
View child = findOneVisibleChild(getChildCount() - 1, -1, false, true);
if (child == null) {
return -1;
}
return getPosition(child);
}
public int findLastCompletelyVisibleItemPosition() {
View child = findOneVisibleChild(getChildCount() - 1, -1, true, false);
if (child == null) {
return -1;
}
return getPosition(child);
}
View findOneVisibleChild(int fromIndex, int toIndex, boolean completelyVisible, boolean acceptPartiallyVisible) {
ensureLayoutState();
int start = this.mOrientationHelper.getStartAfterPadding();
int end = this.mOrientationHelper.getEndAfterPadding();
int next = toIndex > fromIndex ? 1 : -1;
View partiallyVisible = null;
for (int i = fromIndex; i != toIndex; i += next) {
View child = getChildAt(i);
int childStart = this.mOrientationHelper.getDecoratedStart(child);
int childEnd = this.mOrientationHelper.getDecoratedEnd(child);
if (childStart < end && childEnd > start) {
if (!completelyVisible) {
return child;
}
if (childStart >= start && childEnd <= end) {
return child;
}
if (acceptPartiallyVisible && partiallyVisible == null) {
partiallyVisible = child;
}
}
}
return partiallyVisible;
}
public View onFocusSearchFailed(View focused, int focusDirection, Recycler recycler, State state) {
resolveShouldLayoutReverse();
if (getChildCount() == 0) {
return null;
}
int layoutDir = convertFocusDirectionToLayoutDirection(focusDirection);
if (layoutDir == Integer.MIN_VALUE) {
return null;
}
View referenceChild;
ensureLayoutState();
if (layoutDir == -1) {
referenceChild = findReferenceChildClosestToStart(recycler, state);
} else {
referenceChild = findReferenceChildClosestToEnd(recycler, state);
}
if (referenceChild == null) {
return null;
}
View nextFocus;
ensureLayoutState();
updateLayoutState(layoutDir, (int) (MAX_SCROLL_FACTOR * ((float) this.mOrientationHelper.getTotalSpace())), false, state);
this.mLayoutState.mScrollingOffset = Integer.MIN_VALUE;
this.mLayoutState.mRecycle = false;
fill(recycler, this.mLayoutState, state, true);
if (layoutDir == -1) {
nextFocus = getChildClosestToStart();
} else {
nextFocus = getChildClosestToEnd();
}
if (nextFocus == referenceChild || !nextFocus.isFocusable()) {
return null;
}
return nextFocus;
}
private void logChildren() {
Log.d(TAG, "internal representation of views on the screen");
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
Log.d(TAG, "item " + getPosition(child) + ", coord:" + this.mOrientationHelper.getDecoratedStart(child));
}
Log.d(TAG, "==============");
}
void validateChildOrder() {
boolean z = true;
Log.d(TAG, "validating child count " + getChildCount());
if (getChildCount() >= 1) {
int lastPos = getPosition(getChildAt(0));
int lastScreenLoc = this.mOrientationHelper.getDecoratedStart(getChildAt(0));
int i;
View child;
int pos;
int screenLoc;
StringBuilder append;
if (this.mShouldReverseLayout) {
i = 1;
while (i < getChildCount()) {
child = getChildAt(i);
pos = getPosition(child);
screenLoc = this.mOrientationHelper.getDecoratedStart(child);
if (pos < lastPos) {
logChildren();
append = new StringBuilder().append("detected invalid position. loc invalid? ");
if (screenLoc >= lastScreenLoc) {
z = false;
}
throw new RuntimeException(append.append(z).toString());
} else if (screenLoc > lastScreenLoc) {
logChildren();
throw new RuntimeException("detected invalid location");
} else {
i++;
}
}
return;
}
i = 1;
while (i < getChildCount()) {
child = getChildAt(i);
pos = getPosition(child);
screenLoc = this.mOrientationHelper.getDecoratedStart(child);
if (pos < lastPos) {
logChildren();
append = new StringBuilder().append("detected invalid position. loc invalid? ");
if (screenLoc >= lastScreenLoc) {
z = false;
}
throw new RuntimeException(append.append(z).toString());
} else if (screenLoc < lastScreenLoc) {
logChildren();
throw new RuntimeException("detected invalid location");
} else {
i++;
}
}
}
}
public boolean supportsPredictiveItemAnimations() {
return this.mPendingSavedState == null && this.mLastStackFromEnd == this.mStackFromEnd;
}
public void prepareForDrop(View view, View target, int x, int y) {
int dropDirection;
assertNotInLayoutOrScroll("Cannot drop a view during a scroll or layout calculation");
ensureLayoutState();
resolveShouldLayoutReverse();
int myPos = getPosition(view);
int targetPos = getPosition(target);
if (myPos < targetPos) {
dropDirection = 1;
} else {
dropDirection = -1;
}
if (this.mShouldReverseLayout) {
if (dropDirection == 1) {
scrollToPositionWithOffset(targetPos, this.mOrientationHelper.getEndAfterPadding() - (this.mOrientationHelper.getDecoratedStart(target) + this.mOrientationHelper.getDecoratedMeasurement(view)));
} else {
scrollToPositionWithOffset(targetPos, this.mOrientationHelper.getEndAfterPadding() - this.mOrientationHelper.getDecoratedEnd(target));
}
} else if (dropDirection == -1) {
scrollToPositionWithOffset(targetPos, this.mOrientationHelper.getDecoratedStart(target));
} else {
scrollToPositionWithOffset(targetPos, this.mOrientationHelper.getDecoratedEnd(target) - this.mOrientationHelper.getDecoratedMeasurement(view));
}
}
}