RecyclerView version bump
This commit is contained in:
1 parent
2130e7a8dd
commit
ce75c6a67c
6 files changed
+748
-150
No files matched your search
@@ -60,11 +60,14 @@ class LayoutState {
|
||||
int mLayoutDirection;
|
||||
|
||||
/**
|
||||
* Used if you want to pre-layout items that are not yet visible.
|
||||
* The difference with {@link #mAvailable} is that, when recycling, distance rendered for
|
||||
* {@link #mExtra} is not considered not to recycle visible children.
|
||||
* This is the target pixel closest to the start of the layout that we are trying to fill
|
||||
*/
|
||||
int mExtra = 0;
|
||||
int mStartLine = 0;
|
||||
|
||||
/**
|
||||
* This is the target pixel closest to the end of the layout that we are trying to fill
|
||||
*/
|
||||
int mEndLine = 0;
|
||||
|
||||
/**
|
||||
* @return true if there are more items in the data adapter
|
||||
@@ -84,4 +87,16 @@ class LayoutState {
|
||||
mCurrentPosition += mItemDirection;
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LayoutState{" +
|
||||
"mAvailable=" + mAvailable +
|
||||
", mCurrentPosition=" + mCurrentPosition +
|
||||
", mItemDirection=" + mItemDirection +
|
||||
", mLayoutDirection=" + mLayoutDirection +
|
||||
", mStartLine=" + mStartLine +
|
||||
", mEndLine=" + mEndLine +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,8 @@ import android.os.Parcelable;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.support.v4.view.accessibility.AccessibilityEventCompat;
|
||||
import android.support.v4.view.accessibility.AccessibilityRecordCompat;
|
||||
import android.util.AttributeSet;
|
||||
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -36,7 +38,8 @@ import static android.support.v7.widget.RecyclerView.NO_POSITION;
|
||||
* A {@link android.support.v7.widget.RecyclerView.LayoutManager} implementation which provides
|
||||
* similar functionality to {@link android.widget.ListView}.
|
||||
*/
|
||||
public class LinearLayoutManager extends RecyclerView.LayoutManager {
|
||||
public class LinearLayoutManager extends RecyclerView.LayoutManager implements
|
||||
ItemTouchHelper.ViewDropHandler {
|
||||
|
||||
private static final String TAG = "LinearLayoutManager";
|
||||
|
||||
@@ -130,7 +133,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager {
|
||||
* Re-used variable to keep anchor information on re-layout.
|
||||
* Anchor position and coordinate defines the reference point for LLM while doing a layout.
|
||||
* */
|
||||
final AnchorInfo mAnchorInfo;
|
||||
final AnchorInfo mAnchorInfo = new AnchorInfo();
|
||||
|
||||
/**
|
||||
* Creates a vertical LinearLayoutManager
|
||||
@@ -148,11 +151,26 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager {
|
||||
* @param reverseLayout When set to true, layouts from end to start.
|
||||
*/
|
||||
public LinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
|
||||
mAnchorInfo = new AnchorInfo();
|
||||
setOrientation(orientation);
|
||||
setReverseLayout(reverseLayout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used when layout manager is set in XML by RecyclerView attribute
|
||||
* "layoutManager". Defaults to vertical orientation.
|
||||
*
|
||||
* @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_android_orientation
|
||||
* @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_reverseLayout
|
||||
* @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_stackFromEnd
|
||||
*/
|
||||
public LinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr,
|
||||
int defStyleRes) {
|
||||
Properties properties = getProperties(context, attrs, defStyleAttr, defStyleRes);
|
||||
setOrientation(properties.orientation);
|
||||
setReverseLayout(properties.reverseLayout);
|
||||
setStackFromEnd(properties.stackFromEnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@@ -371,9 +389,13 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager {
|
||||
final int firstChild = getPosition(getChildAt(0));
|
||||
final int viewPosition = position - firstChild;
|
||||
if (viewPosition >= 0 && viewPosition < childCount) {
|
||||
return getChildAt(viewPosition);
|
||||
final View child = getChildAt(viewPosition);
|
||||
if (getPosition(child) == position) {
|
||||
return child; // in pre-layout, this may not match
|
||||
}
|
||||
}
|
||||
return null;
|
||||
// fallback to traversal. This might be necessary in pre-layout.
|
||||
return super.findViewByPosition(position);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -796,6 +818,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager {
|
||||
}
|
||||
// override layout from end values for consistency
|
||||
anchorInfo.mLayoutFromEnd = mShouldReverseLayout;
|
||||
// if this changes, we should update prepareForDrop as well
|
||||
if (mShouldReverseLayout) {
|
||||
anchorInfo.mCoordinate = mOrientationHelper.getEndAfterPadding() -
|
||||
mPendingScrollPositionOffset;
|
||||
@@ -941,7 +964,6 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager {
|
||||
* <code>item[10]</code>'s bottom is 20 pixels above the RecyclerView's bottom.
|
||||
* <p>
|
||||
* Note that scroll position change will not be reflected until the next layout call.
|
||||
*
|
||||
* <p>
|
||||
* If you are just trying to make a position visible, use {@link #scrollToPosition(int)}.
|
||||
*
|
||||
@@ -1177,9 +1199,8 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager {
|
||||
*
|
||||
* @param recycler Recycler instance of {@link android.support.v7.widget.RecyclerView}
|
||||
* @param dt This can be used to add additional padding to the visible area. This is used
|
||||
* to
|
||||
* detect children that will go out of bounds after scrolling, without actually
|
||||
* moving them.
|
||||
* to detect children that will go out of bounds after scrolling, without
|
||||
* actually moving them.
|
||||
*/
|
||||
private void recycleViewsFromStart(RecyclerView.Recycler recycler, int dt) {
|
||||
if (dt < 0) {
|
||||
@@ -1788,6 +1809,40 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager {
|
||||
return mPendingSavedState == null && mLastStackFromEnd == mStackFromEnd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide This method should be called by ItemTouchHelper only.
|
||||
*/
|
||||
@Override
|
||||
public void prepareForDrop(View view, View target, int x, int y) {
|
||||
assertNotInLayoutOrScroll("Cannot drop a view during a scroll or layout calculation");
|
||||
ensureLayoutState();
|
||||
resolveShouldLayoutReverse();
|
||||
final int myPos = getPosition(view);
|
||||
final int targetPos = getPosition(target);
|
||||
final int dropDirection = myPos < targetPos ? LayoutState.ITEM_DIRECTION_TAIL :
|
||||
LayoutState.ITEM_DIRECTION_HEAD;
|
||||
if (mShouldReverseLayout) {
|
||||
if (dropDirection == LayoutState.ITEM_DIRECTION_TAIL) {
|
||||
scrollToPositionWithOffset(targetPos,
|
||||
mOrientationHelper.getEndAfterPadding() -
|
||||
(mOrientationHelper.getDecoratedStart(target) +
|
||||
mOrientationHelper.getDecoratedMeasurement(view)));
|
||||
} else {
|
||||
scrollToPositionWithOffset(targetPos,
|
||||
mOrientationHelper.getEndAfterPadding() -
|
||||
mOrientationHelper.getDecoratedEnd(target));
|
||||
}
|
||||
} else {
|
||||
if (dropDirection == LayoutState.ITEM_DIRECTION_HEAD) {
|
||||
scrollToPositionWithOffset(targetPos, mOrientationHelper.getDecoratedStart(target));
|
||||
} else {
|
||||
scrollToPositionWithOffset(targetPos,
|
||||
mOrientationHelper.getDecoratedEnd(target) -
|
||||
mOrientationHelper.getDecoratedMeasurement(view));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class that keeps temporary state while {LayoutManager} is filling out the empty
|
||||
* space.
|
||||
|
||||
@@ -16,10 +16,9 @@
|
||||
|
||||
package android.support.v7.widget;
|
||||
|
||||
import android.support.v7.widget.AdapterHelper.UpdateOp;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import android.support.v7.widget.AdapterHelper.UpdateOp;
|
||||
import static android.support.v7.widget.AdapterHelper.UpdateOp.ADD;
|
||||
import static android.support.v7.widget.AdapterHelper.UpdateOp.MOVE;
|
||||
import static android.support.v7.widget.AdapterHelper.UpdateOp.REMOVE;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package android.support.v7.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.database.Observable;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.PointF;
|
||||
@@ -31,6 +32,8 @@ import android.support.v4.os.TraceCompat;
|
||||
import android.support.v4.util.ArrayMap;
|
||||
import android.support.v4.view.InputDeviceCompat;
|
||||
import android.support.v4.view.MotionEventCompat;
|
||||
import android.support.v4.view.NestedScrollingChild;
|
||||
import android.support.v4.view.NestedScrollingChildHelper;
|
||||
import android.support.v4.view.ScrollingView;
|
||||
import android.support.v4.view.VelocityTrackerCompat;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
@@ -40,9 +43,6 @@ import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
|
||||
import android.support.v4.view.accessibility.AccessibilityRecordCompat;
|
||||
import android.support.v4.widget.EdgeEffectCompat;
|
||||
import android.support.v4.widget.ScrollerCompat;
|
||||
import static android.support.v7.widget.AdapterHelper.UpdateOp;
|
||||
import static android.support.v7.widget.AdapterHelper.Callback;
|
||||
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
@@ -59,10 +59,17 @@ import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static android.support.v7.widget.AdapterHelper.Callback;
|
||||
import static android.support.v7.widget.AdapterHelper.UpdateOp;
|
||||
|
||||
/**
|
||||
* A flexible view for providing a limited window into a large data set.
|
||||
*
|
||||
@@ -127,8 +134,10 @@ import java.util.List;
|
||||
* <p>
|
||||
* When writing a {@link LayoutManager} you almost always want to use layout positions whereas when
|
||||
* writing an {@link Adapter}, you probably want to use adapter positions.
|
||||
*
|
||||
* @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_layoutManager
|
||||
*/
|
||||
public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild {
|
||||
|
||||
private static final String TAG = "RecyclerView";
|
||||
|
||||
@@ -220,6 +229,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
* >Try increasing your pool size and item cache size.
|
||||
*/
|
||||
private static final String TRACE_CREATE_VIEW_TAG = "RV CreateView";
|
||||
private static final Class<?>[] LAYOUT_MANAGER_CONSTRUCTOR_SIGNATURE =
|
||||
new Class[]{Context.class, AttributeSet.class, int.class, int.class};
|
||||
|
||||
private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver();
|
||||
|
||||
@@ -286,6 +297,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
private boolean mAdapterUpdateDuringMeasure;
|
||||
private final boolean mPostUpdatesOnAnimation;
|
||||
private final AccessibilityManager mAccessibilityManager;
|
||||
private List<OnChildAttachStateChangeListener> mOnChildAttachStateListeners;
|
||||
|
||||
/**
|
||||
* Set to true when an adapter data set changed notification is received.
|
||||
@@ -357,11 +369,17 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
new ItemAnimatorRestoreListener();
|
||||
private boolean mPostedAnimatorRunner = false;
|
||||
private RecyclerViewAccessibilityDelegate mAccessibilityDelegate;
|
||||
private ChildDrawingOrderCallback mChildDrawingOrderCallback;
|
||||
|
||||
// simple array to keep min and max child position during a layout calculation
|
||||
// preserved not to create a new one in each layout pass
|
||||
private final int[] mMinMaxLayoutPositions = new int[2];
|
||||
|
||||
private final NestedScrollingChildHelper mScrollingChildHelper;
|
||||
private final int[] mScrollOffset = new int[2];
|
||||
private final int[] mScrollConsumed = new int[2];
|
||||
private final int[] mNestedOffsets = new int[2];
|
||||
|
||||
private Runnable mItemAnimatorRunner = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -411,6 +429,18 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
mAccessibilityManager = (AccessibilityManager) getContext()
|
||||
.getSystemService(Context.ACCESSIBILITY_SERVICE);
|
||||
setAccessibilityDelegateCompat(new RecyclerViewAccessibilityDelegate(this));
|
||||
// Create the layoutManager if specified.
|
||||
if (attrs != null) {
|
||||
int defStyleRes = 0;
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RecyclerView,
|
||||
defStyle, defStyleRes);
|
||||
String layoutManagerName = a.getString(R.styleable.RecyclerView_layoutManager);
|
||||
a.recycle();
|
||||
createLayoutManager(context, layoutManagerName, attrs, defStyle, defStyleRes);
|
||||
}
|
||||
|
||||
mScrollingChildHelper = new NestedScrollingChildHelper(this);
|
||||
setNestedScrollingEnabled(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -431,6 +461,72 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
ViewCompat.setAccessibilityDelegate(this, mAccessibilityDelegate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate and set a LayoutManager, if specified in the attributes.
|
||||
*/
|
||||
private void createLayoutManager(Context context, String className, AttributeSet attrs,
|
||||
int defStyleAttr, int defStyleRes) {
|
||||
if (className != null) {
|
||||
className = className.trim();
|
||||
if (className.length() != 0) { // Can't use isEmpty since it was added in API 9.
|
||||
className = getFullClassName(context, className);
|
||||
try {
|
||||
ClassLoader classLoader;
|
||||
if (isInEditMode()) {
|
||||
// Stupid layoutlib cannot handle simple class loaders.
|
||||
classLoader = this.getClass().getClassLoader();
|
||||
} else {
|
||||
classLoader = context.getClassLoader();
|
||||
}
|
||||
Class<? extends LayoutManager> layoutManagerClass =
|
||||
classLoader.loadClass(className).asSubclass(LayoutManager.class);
|
||||
Constructor<? extends LayoutManager> constructor;
|
||||
Object[] constructorArgs = null;
|
||||
try {
|
||||
constructor = layoutManagerClass
|
||||
.getConstructor(LAYOUT_MANAGER_CONSTRUCTOR_SIGNATURE);
|
||||
constructorArgs = new Object[]{context, attrs, defStyleAttr, defStyleRes};
|
||||
} catch (NoSuchMethodException e) {
|
||||
try {
|
||||
constructor = layoutManagerClass.getConstructor();
|
||||
} catch (NoSuchMethodException e1) {
|
||||
e1.initCause(e);
|
||||
throw new IllegalStateException(attrs.getPositionDescription() +
|
||||
": Error creating LayoutManager " + className, e1);
|
||||
}
|
||||
}
|
||||
constructor.setAccessible(true);
|
||||
setLayoutManager(constructor.newInstance(constructorArgs));
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalStateException(attrs.getPositionDescription()
|
||||
+ ": Unable to find LayoutManager " + className, e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new IllegalStateException(attrs.getPositionDescription()
|
||||
+ ": Could not instantiate the LayoutManager: " + className, e);
|
||||
} catch (InstantiationException e) {
|
||||
throw new IllegalStateException(attrs.getPositionDescription()
|
||||
+ ": Could not instantiate the LayoutManager: " + className, e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalStateException(attrs.getPositionDescription()
|
||||
+ ": Cannot access non-public constructor " + className, e);
|
||||
} catch (ClassCastException e) {
|
||||
throw new IllegalStateException(attrs.getPositionDescription()
|
||||
+ ": Class is not a LayoutManager " + className, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getFullClassName(Context context, String className) {
|
||||
if (className.charAt(0) == '.') {
|
||||
return context.getPackageName() + className;
|
||||
}
|
||||
if (className.contains(".")) {
|
||||
return className;
|
||||
}
|
||||
return RecyclerView.class.getPackage().getName() + '.' + className;
|
||||
}
|
||||
|
||||
private void initChildrenHelper() {
|
||||
mChildHelper = new ChildHelper(new ChildHelper.Callback() {
|
||||
@Override
|
||||
@@ -772,6 +868,46 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a listener that will be notified whenever a child view is attached to or detached
|
||||
* from RecyclerView.
|
||||
*
|
||||
* <p>This listener will be called when a LayoutManager or the RecyclerView decides
|
||||
* that a child view is no longer needed. If an application associates expensive
|
||||
* or heavyweight data with item views, this may be a good place to release
|
||||
* or free those resources.</p>
|
||||
*
|
||||
* @param listener Listener to register
|
||||
*/
|
||||
public void addOnChildAttachStateChangeListener(OnChildAttachStateChangeListener listener) {
|
||||
if (mOnChildAttachStateListeners == null) {
|
||||
mOnChildAttachStateListeners = new ArrayList<OnChildAttachStateChangeListener>();
|
||||
}
|
||||
mOnChildAttachStateListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the provided listener from child attached state listeners list.
|
||||
*
|
||||
* @param listener Listener to unregister
|
||||
*/
|
||||
public void removeOnChildAttachStateChangeListener(OnChildAttachStateChangeListener listener) {
|
||||
if (mOnChildAttachStateListeners == null) {
|
||||
return;
|
||||
}
|
||||
mOnChildAttachStateListeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all listeners that were added via
|
||||
* {@link #addOnChildAttachStateChangeListener(OnChildAttachStateChangeListener)}.
|
||||
*/
|
||||
public void clearOnChildAttachStateChangeListeners() {
|
||||
if (mOnChildAttachStateListeners != null) {
|
||||
mOnChildAttachStateListeners.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link LayoutManager} that this RecyclerView will use.
|
||||
*
|
||||
@@ -1048,6 +1184,26 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link ChildDrawingOrderCallback} to be used for drawing children.
|
||||
* <p>
|
||||
* See {@link ViewGroup#getChildDrawingOrder(int, int)} for details. Calling this method will
|
||||
* always call {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean)}. The parameter will be
|
||||
* true if childDrawingOrderCallback is not null, false otherwise.
|
||||
* <p>
|
||||
* Note that child drawing order may be overridden by View's elevation.
|
||||
*
|
||||
* @param childDrawingOrderCallback The ChildDrawingOrderCallback to be used by the drawing
|
||||
* system.
|
||||
*/
|
||||
public void setChildDrawingOrderCallback(ChildDrawingOrderCallback childDrawingOrderCallback) {
|
||||
if (childDrawingOrderCallback == mChildDrawingOrderCallback) {
|
||||
return;
|
||||
}
|
||||
mChildDrawingOrderCallback = childDrawingOrderCallback;
|
||||
setChildrenDrawingOrderEnabled(mChildDrawingOrderCallback != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a listener that will be notified of any changes in scroll state or position.
|
||||
*
|
||||
@@ -1156,7 +1312,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
final boolean canScrollHorizontal = mLayout.canScrollHorizontally();
|
||||
final boolean canScrollVertical = mLayout.canScrollVertically();
|
||||
if (canScrollHorizontal || canScrollVertical) {
|
||||
scrollByInternal(canScrollHorizontal ? x : 0, canScrollVertical ? y : 0, false, 0, 0);
|
||||
scrollByInternal(canScrollHorizontal ? x : 0, canScrollVertical ? y : 0, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1179,30 +1335,26 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
*
|
||||
* @param x The amount of horizontal scroll request
|
||||
* @param y The amount of vertical scroll request
|
||||
* @param fromMotionEvent If request is originated from a MotionEvent, this should be set to
|
||||
* true and motionX/motionY should be provided, false otherwise.
|
||||
* @param motionX The x coordinate of the MotionEvent which triggered this scroll. Unused if
|
||||
* fromMotionEvent is false.
|
||||
* @param motionY The y coordinate of the MotionEvent which triggered this scroll. Unused if
|
||||
* fromMotionEvent is false.
|
||||
* @param ev The originating MotionEvent, or null if not from a touch event.
|
||||
*
|
||||
* @return Whether any scroll was consumed in either direction.
|
||||
*/
|
||||
boolean scrollByInternal(int x, int y, boolean fromMotionEvent, int motionX, int motionY) {
|
||||
int overscrollX = 0, overscrollY = 0;
|
||||
int hresult = 0, vresult = 0;
|
||||
boolean scrollByInternal(int x, int y, MotionEvent ev) {
|
||||
int unconsumedX = 0, unconsumedY = 0;
|
||||
int consumedX = 0, consumedY = 0;
|
||||
|
||||
consumePendingUpdateOperations();
|
||||
if (mAdapter != null) {
|
||||
eatRequestLayout();
|
||||
onEnterLayoutOrScroll();
|
||||
TraceCompat.beginSection(TRACE_SCROLL_TAG);
|
||||
if (x != 0) {
|
||||
hresult = mLayout.scrollHorizontallyBy(x, mRecycler, mState);
|
||||
overscrollX = x - hresult;
|
||||
consumedX = mLayout.scrollHorizontallyBy(x, mRecycler, mState);
|
||||
unconsumedX = x - consumedX;
|
||||
}
|
||||
if (y != 0) {
|
||||
vresult = mLayout.scrollVerticallyBy(y, mRecycler, mState);
|
||||
overscrollY = y - vresult;
|
||||
consumedY = mLayout.scrollVerticallyBy(y, mRecycler, mState);
|
||||
unconsumedY = y - consumedY;
|
||||
}
|
||||
TraceCompat.endSection();
|
||||
if (supportsChangeAnimations()) {
|
||||
@@ -1232,19 +1384,27 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
if (!mItemDecorations.isEmpty()) {
|
||||
invalidate();
|
||||
}
|
||||
if (ViewCompat.getOverScrollMode(this) != ViewCompat.OVER_SCROLL_NEVER) {
|
||||
if (fromMotionEvent) {
|
||||
pullGlows(motionX, overscrollX, motionY, overscrollY);
|
||||
|
||||
if (dispatchNestedScroll(consumedX, consumedY, unconsumedX, unconsumedY, mScrollOffset)) {
|
||||
// Update the last touch co-ords, taking any scroll offset into account
|
||||
mLastTouchX -= mScrollOffset[0];
|
||||
mLastTouchY -= mScrollOffset[1];
|
||||
ev.offsetLocation(mScrollOffset[0], mScrollOffset[1]);
|
||||
mNestedOffsets[0] += mScrollOffset[0];
|
||||
mNestedOffsets[1] += mScrollOffset[1];
|
||||
} else if (ViewCompat.getOverScrollMode(this) != ViewCompat.OVER_SCROLL_NEVER) {
|
||||
if (ev != null) {
|
||||
pullGlows(ev.getX(), unconsumedX, ev.getY(), unconsumedY);
|
||||
}
|
||||
considerReleasingGlowsOnScroll(x, y);
|
||||
}
|
||||
if (hresult != 0 || vresult != 0) {
|
||||
dispatchOnScrolled(hresult, vresult);
|
||||
if (consumedX != 0 || consumedY != 0) {
|
||||
dispatchOnScrolled(consumedX, consumedY);
|
||||
}
|
||||
if (!awakenScrollBars()) {
|
||||
invalidate();
|
||||
}
|
||||
return hresult != 0 || vresult != 0;
|
||||
return consumedX != 0 || consumedY != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1437,19 +1597,31 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
"Call setLayoutManager with a non-null argument.");
|
||||
return false;
|
||||
}
|
||||
|
||||
final boolean canScrollHorizontal = mLayout.canScrollHorizontally();
|
||||
final boolean canScrollVertical = mLayout.canScrollVertically();
|
||||
|
||||
if (!canScrollHorizontal || Math.abs(velocityX) < mMinFlingVelocity) {
|
||||
velocityX = 0;
|
||||
}
|
||||
if (!canScrollVertical || Math.abs(velocityY) < mMinFlingVelocity) {
|
||||
velocityY = 0;
|
||||
}
|
||||
velocityX = Math.max(-mMaxFlingVelocity, Math.min(velocityX, mMaxFlingVelocity));
|
||||
velocityY = Math.max(-mMaxFlingVelocity, Math.min(velocityY, mMaxFlingVelocity));
|
||||
if (velocityX != 0 || velocityY != 0) {
|
||||
mViewFlinger.fling(velocityX, velocityY);
|
||||
return true;
|
||||
if (velocityX == 0 && velocityY == 0) {
|
||||
// If we don't have any velocity, return false
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!dispatchNestedPreFling(velocityX, velocityY)) {
|
||||
final boolean canScroll = canScrollHorizontal || canScrollVertical;
|
||||
dispatchNestedFling(velocityX, velocityY, canScroll);
|
||||
|
||||
if (canScroll) {
|
||||
velocityX = Math.max(-mMaxFlingVelocity, Math.min(velocityX, mMaxFlingVelocity));
|
||||
velocityY = Math.max(-mMaxFlingVelocity, Math.min(velocityY, mMaxFlingVelocity));
|
||||
mViewFlinger.fling(velocityX, velocityY);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1473,29 +1645,52 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum velocity to start a fling.
|
||||
*
|
||||
* @return The minimum velocity to start a fling
|
||||
*/
|
||||
public int getMinFlingVelocity() {
|
||||
return mMinFlingVelocity;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the maximum fling velocity used by this RecyclerView.
|
||||
*
|
||||
* @return The maximum fling velocity used by this RecyclerView.
|
||||
*/
|
||||
public int getMaxFlingVelocity() {
|
||||
return mMaxFlingVelocity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a pull to relevant overscroll glow effects
|
||||
*/
|
||||
private void pullGlows(int x, int overscrollX, int y, int overscrollY) {
|
||||
private void pullGlows(float x, float overscrollX, float y, float overscrollY) {
|
||||
boolean invalidate = false;
|
||||
if (overscrollX < 0) {
|
||||
ensureLeftGlow();
|
||||
invalidate = mLeftGlow.onPull(-overscrollX / (float) getWidth(),
|
||||
1f - y / (float) getHeight()) || invalidate;
|
||||
if (mLeftGlow.onPull(-overscrollX / getWidth(), 1f - y / getHeight())) {
|
||||
invalidate = true;
|
||||
}
|
||||
} else if (overscrollX > 0) {
|
||||
ensureRightGlow();
|
||||
invalidate = mRightGlow.onPull(overscrollX / (float) getWidth(),
|
||||
y / (float) getHeight()) || invalidate;
|
||||
if (mRightGlow.onPull(overscrollX / getWidth(), y / getHeight())) {
|
||||
invalidate = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (overscrollY < 0) {
|
||||
ensureTopGlow();
|
||||
invalidate = mTopGlow.onPull(-overscrollY / (float) getHeight(),
|
||||
x / (float) getWidth()) || invalidate;
|
||||
if (mTopGlow.onPull(-overscrollY / getHeight(), x / getWidth())) {
|
||||
invalidate = true;
|
||||
}
|
||||
} else if (overscrollY > 0) {
|
||||
ensureBottomGlow();
|
||||
invalidate = mBottomGlow.onPull(overscrollY / (float) getHeight(),
|
||||
1f - x / (float) getWidth()) || invalidate;
|
||||
if (mBottomGlow.onPull(overscrollY / getHeight(), 1f - x / getWidth())) {
|
||||
invalidate = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (invalidate || overscrollX != 0 || overscrollY != 0) {
|
||||
@@ -1698,6 +1893,14 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
removeCallbacks(mItemAnimatorRunner);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if RecyclerView is attached to window.
|
||||
*/
|
||||
// @override
|
||||
public boolean isAttachedToWindow() {
|
||||
return mIsAttached;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if RecyclerView is in the middle of a layout or scroll and throws an
|
||||
* {@link IllegalStateException} if it <b>is not</b>.
|
||||
@@ -1744,6 +1947,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
* for each incoming MotionEvent until the end of the gesture.</p>
|
||||
*
|
||||
* @param listener Listener to add
|
||||
* @see SimpleOnItemTouchListener
|
||||
*/
|
||||
public void addOnItemTouchListener(OnItemTouchListener listener) {
|
||||
mOnItemTouchListeners.add(listener);
|
||||
@@ -1837,6 +2041,15 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
getParent().requestDisallowInterceptTouchEvent(true);
|
||||
setScrollState(SCROLL_STATE_DRAGGING);
|
||||
}
|
||||
|
||||
int nestedScrollAxis = ViewCompat.SCROLL_AXIS_NONE;
|
||||
if (canScrollHorizontally) {
|
||||
nestedScrollAxis |= ViewCompat.SCROLL_AXIS_HORIZONTAL;
|
||||
}
|
||||
if (canScrollVertically) {
|
||||
nestedScrollAxis |= ViewCompat.SCROLL_AXIS_VERTICAL;
|
||||
}
|
||||
startNestedScroll(nestedScrollAxis);
|
||||
break;
|
||||
|
||||
case MotionEventCompat.ACTION_POINTER_DOWN:
|
||||
@@ -1879,6 +2092,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
|
||||
case MotionEvent.ACTION_UP: {
|
||||
mVelocityTracker.clear();
|
||||
stopNestedScroll();
|
||||
} break;
|
||||
|
||||
case MotionEvent.ACTION_CANCEL: {
|
||||
@@ -1888,6 +2102,16 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
return mScrollState == SCROLL_STATE_DRAGGING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
|
||||
final int listenerCount = mOnItemTouchListeners.size();
|
||||
for (int i = 0; i < listenerCount; i++) {
|
||||
final OnItemTouchListener listener = mOnItemTouchListeners.get(i);
|
||||
listener.onRequestDisallowInterceptTouchEvent(disallowIntercept);
|
||||
}
|
||||
super.requestDisallowInterceptTouchEvent(disallowIntercept);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent e) {
|
||||
if (dispatchOnItemTouch(e)) {
|
||||
@@ -1903,14 +2127,29 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
}
|
||||
mVelocityTracker.addMovement(e);
|
||||
|
||||
final MotionEvent vtev = MotionEvent.obtain(e);
|
||||
final int action = MotionEventCompat.getActionMasked(e);
|
||||
final int actionIndex = MotionEventCompat.getActionIndex(e);
|
||||
|
||||
if (action == MotionEvent.ACTION_DOWN) {
|
||||
mNestedOffsets[0] = mNestedOffsets[1] = 0;
|
||||
}
|
||||
vtev.offsetLocation(mNestedOffsets[0], mNestedOffsets[1]);
|
||||
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_DOWN: {
|
||||
mScrollPointerId = MotionEventCompat.getPointerId(e, 0);
|
||||
mInitialTouchX = mLastTouchX = (int) (e.getX() + 0.5f);
|
||||
mInitialTouchY = mLastTouchY = (int) (e.getY() + 0.5f);
|
||||
|
||||
int nestedScrollAxis = ViewCompat.SCROLL_AXIS_NONE;
|
||||
if (canScrollHorizontally) {
|
||||
nestedScrollAxis |= ViewCompat.SCROLL_AXIS_HORIZONTAL;
|
||||
}
|
||||
if (canScrollVertically) {
|
||||
nestedScrollAxis |= ViewCompat.SCROLL_AXIS_VERTICAL;
|
||||
}
|
||||
startNestedScroll(nestedScrollAxis);
|
||||
} break;
|
||||
|
||||
case MotionEventCompat.ACTION_POINTER_DOWN: {
|
||||
@@ -1929,32 +2168,52 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
|
||||
final int x = (int) (MotionEventCompat.getX(e, index) + 0.5f);
|
||||
final int y = (int) (MotionEventCompat.getY(e, index) + 0.5f);
|
||||
int dx = mLastTouchX - x;
|
||||
int dy = mLastTouchY - y;
|
||||
|
||||
if (dispatchNestedPreScroll(dx, dy, mScrollConsumed, mScrollOffset)) {
|
||||
dx -= mScrollConsumed[0];
|
||||
dy -= mScrollConsumed[1];
|
||||
vtev.offsetLocation(mScrollOffset[0], mScrollOffset[1]);
|
||||
// Updated the nested offsets
|
||||
mNestedOffsets[0] += mScrollOffset[0];
|
||||
mNestedOffsets[1] += mScrollOffset[1];
|
||||
}
|
||||
|
||||
if (mScrollState != SCROLL_STATE_DRAGGING) {
|
||||
final int dx = x - mInitialTouchX;
|
||||
final int dy = y - mInitialTouchY;
|
||||
boolean startScroll = false;
|
||||
if (canScrollHorizontally && Math.abs(dx) > mTouchSlop) {
|
||||
mLastTouchX = mInitialTouchX + mTouchSlop * (dx < 0 ? -1 : 1);
|
||||
if (dx > 0) {
|
||||
dx -= mTouchSlop;
|
||||
} else {
|
||||
dx += mTouchSlop;
|
||||
}
|
||||
startScroll = true;
|
||||
}
|
||||
if (canScrollVertically && Math.abs(dy) > mTouchSlop) {
|
||||
mLastTouchY = mInitialTouchY + mTouchSlop * (dy < 0 ? -1 : 1);
|
||||
if (dy > 0) {
|
||||
dy -= mTouchSlop;
|
||||
} else {
|
||||
dy += mTouchSlop;
|
||||
}
|
||||
startScroll = true;
|
||||
}
|
||||
if (startScroll) {
|
||||
setScrollState(SCROLL_STATE_DRAGGING);
|
||||
}
|
||||
}
|
||||
|
||||
if (mScrollState == SCROLL_STATE_DRAGGING) {
|
||||
final int dx = x - mLastTouchX;
|
||||
final int dy = y - mLastTouchY;
|
||||
if (scrollByInternal(canScrollHorizontally ? -dx : 0,
|
||||
canScrollVertically ? -dy : 0, true, x, y)) {
|
||||
mLastTouchX = x - mScrollOffset[0];
|
||||
mLastTouchY = y - mScrollOffset[1];
|
||||
|
||||
if (scrollByInternal(
|
||||
canScrollHorizontally ? dx : 0,
|
||||
canScrollVertically ? dy : 0,
|
||||
vtev)) {
|
||||
getParent().requestDisallowInterceptTouchEvent(true);
|
||||
}
|
||||
}
|
||||
mLastTouchX = x;
|
||||
mLastTouchY = y;
|
||||
} break;
|
||||
|
||||
case MotionEventCompat.ACTION_POINTER_UP: {
|
||||
@@ -1970,6 +2229,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
if (!((xvel != 0 || yvel != 0) && fling((int) xvel, (int) yvel))) {
|
||||
setScrollState(SCROLL_STATE_IDLE);
|
||||
}
|
||||
|
||||
mVelocityTracker.clear();
|
||||
releaseGlows();
|
||||
} break;
|
||||
@@ -1979,6 +2239,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
} break;
|
||||
}
|
||||
|
||||
vtev.recycle();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1986,6 +2248,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
if (mVelocityTracker != null) {
|
||||
mVelocityTracker.clear();
|
||||
}
|
||||
stopNestedScroll();
|
||||
releaseGlows();
|
||||
setScrollState(SCROLL_STATE_IDLE);
|
||||
}
|
||||
@@ -2830,6 +3093,18 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
return mLayout.generateLayoutParams(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if RecyclerView is currently running some animations.
|
||||
* <p>
|
||||
* If you want to be notified when animations are finished, use
|
||||
* {@link ItemAnimator#isRunning(ItemAnimator.ItemAnimatorFinishedListener)}.
|
||||
*
|
||||
* @return True if there are some item animations currently running or waiting to be started.
|
||||
*/
|
||||
public boolean isAnimating() {
|
||||
return mItemAnimator != null && mItemAnimator.isRunning();
|
||||
}
|
||||
|
||||
void saveOldPositions() {
|
||||
final int childCount = mChildHelper.getUnfilteredChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
@@ -3239,6 +3514,11 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawChild(Canvas canvas, View child, long drawingTime) {
|
||||
return super.drawChild(canvas, child, drawingTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Offset the bounds of all child views by <code>dy</code> pixels.
|
||||
* Useful for implementing simple scrolling in {@link LayoutManager LayoutManagers}.
|
||||
@@ -5166,17 +5446,32 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
}
|
||||
|
||||
private void dispatchChildDetached(View child) {
|
||||
if (mAdapter != null) {
|
||||
mAdapter.onViewDetachedFromWindow(getChildViewHolderInt(child));
|
||||
}
|
||||
final ViewHolder viewHolder = getChildViewHolderInt(child);
|
||||
onChildDetachedFromWindow(child);
|
||||
if (mAdapter != null && viewHolder != null) {
|
||||
mAdapter.onViewDetachedFromWindow(viewHolder);
|
||||
}
|
||||
if (mOnChildAttachStateListeners != null) {
|
||||
final int cnt = mOnChildAttachStateListeners.size();
|
||||
for (int i = cnt - 1; i >= 0; i--) {
|
||||
mOnChildAttachStateListeners.get(i).onChildViewDetachedFromWindow(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void dispatchChildAttached(View child) {
|
||||
if (mAdapter != null) {
|
||||
mAdapter.onViewAttachedToWindow(getChildViewHolderInt(child));
|
||||
}
|
||||
final ViewHolder viewHolder = getChildViewHolderInt(child);
|
||||
onChildAttachedToWindow(child);
|
||||
if (mAdapter != null && viewHolder != null) {
|
||||
mAdapter.onViewAttachedToWindow(viewHolder);
|
||||
}
|
||||
if (mOnChildAttachStateListeners != null) {
|
||||
final int cnt = mOnChildAttachStateListeners.size();
|
||||
for (int i = cnt - 1; i >= 0; i--) {
|
||||
mOnChildAttachStateListeners.get(i).onChildViewAttachedToWindow(child);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5186,6 +5481,14 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
* a <code>RecyclerView</code> can be used to implement a standard vertically scrolling list,
|
||||
* a uniform grid, staggered grids, horizontally scrolling collections and more. Several stock
|
||||
* layout managers are provided for general use.
|
||||
* <p/>
|
||||
* If the LayoutManager specifies a default constructor or one with the signature
|
||||
* ({@link Context}, {@link AttributeSet}, {@code int}, {@code int}), RecyclerView will
|
||||
* instantiate and set the LayoutManager when being inflated. Most used properties can
|
||||
* be then obtained from {@link #getProperties(Context, AttributeSet, int, int)}. In case
|
||||
* a LayoutManager specifies both constructors, the non-default constructor will take
|
||||
* precedence.
|
||||
*
|
||||
*/
|
||||
public static abstract class LayoutManager {
|
||||
ChildHelper mChildHelper;
|
||||
@@ -7272,6 +7575,43 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
int action, Bundle args) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the xml attributes to get the most common properties used by layout managers.
|
||||
*
|
||||
* @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_android_orientation
|
||||
* @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_spanCount
|
||||
* @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_reverseLayout
|
||||
* @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_stackFromEnd
|
||||
*
|
||||
* @return an object containing the properties as specified in the attrs.
|
||||
*/
|
||||
public static Properties getProperties(Context context, AttributeSet attrs,
|
||||
int defStyleAttr, int defStyleRes) {
|
||||
Properties properties = new Properties();
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RecyclerView,
|
||||
defStyleAttr, defStyleRes);
|
||||
properties.orientation = a.getInt(R.styleable.RecyclerView_android_orientation, VERTICAL);
|
||||
properties.spanCount = a.getInt(R.styleable.RecyclerView_spanCount, 1);
|
||||
properties.reverseLayout = a.getBoolean(R.styleable.RecyclerView_reverseLayout, false);
|
||||
properties.stackFromEnd = a.getBoolean(R.styleable.RecyclerView_stackFromEnd, false);
|
||||
a.recycle();
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Some general properties that a LayoutManager may want to use.
|
||||
*/
|
||||
public static class Properties {
|
||||
/** @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_android_orientation */
|
||||
public int orientation;
|
||||
/** @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_spanCount */
|
||||
public int spanCount;
|
||||
/** @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_reverseLayout */
|
||||
public boolean reverseLayout;
|
||||
/** @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_stackFromEnd */
|
||||
public boolean stackFromEnd;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -7372,8 +7712,10 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
* manipulation of item views within the RecyclerView. OnItemTouchListeners may intercept
|
||||
* a touch interaction already in progress even if the RecyclerView is already handling that
|
||||
* gesture stream itself for the purposes of scrolling.</p>
|
||||
*
|
||||
* @see SimpleOnItemTouchListener
|
||||
*/
|
||||
public interface OnItemTouchListener {
|
||||
public static interface OnItemTouchListener {
|
||||
/**
|
||||
* Silently observe and/or take over touch events sent to the RecyclerView
|
||||
* before they are handled by either the RecyclerView itself or its child views.
|
||||
@@ -7398,8 +7740,44 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
* the RecyclerView's coordinate system.
|
||||
*/
|
||||
public void onTouchEvent(RecyclerView rv, MotionEvent e);
|
||||
|
||||
/**
|
||||
* Called when a child of RecyclerView does not want RecyclerView and its ancestors to
|
||||
* intercept touch events with
|
||||
* {@link ViewGroup#onInterceptTouchEvent(MotionEvent)}.
|
||||
*
|
||||
* @param disallowIntercept True if the child does not want the parent to
|
||||
* intercept touch events.
|
||||
* @see ViewParent#requestDisallowInterceptTouchEvent(boolean)
|
||||
*/
|
||||
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept);
|
||||
}
|
||||
|
||||
/**
|
||||
* An implementation of {@link RecyclerView.OnItemTouchListener} that has empty method bodies and
|
||||
* default return values.
|
||||
* <p>
|
||||
* You may prefer to extend this class if you don't need to override all methods. Another
|
||||
* benefit of using this class is future compatibility. As the interface may change, we'll
|
||||
* always provide a default implementation on this class so that your code won't break when
|
||||
* you update to a new version of the support library.
|
||||
*/
|
||||
public class SimpleOnItemTouchListener implements RecyclerView.OnItemTouchListener {
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An OnScrollListener can be set on a RecyclerView to receive messages
|
||||
* when a scrolling event has occurred on that RecyclerView.
|
||||
@@ -7412,7 +7790,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
* want your components to be able to easily replace the listener use
|
||||
* RecyclerView#setOnScrollListener.
|
||||
*/
|
||||
abstract static public class OnScrollListener {
|
||||
public abstract static class OnScrollListener {
|
||||
/**
|
||||
* Callback method to be invoked when RecyclerView's scroll state changes.
|
||||
*
|
||||
@@ -7457,6 +7835,27 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
public void onViewRecycled(ViewHolder holder);
|
||||
}
|
||||
|
||||
/**
|
||||
* A Listener interface that can be attached to a RecylcerView to get notified
|
||||
* whenever a ViewHolder is attached to or detached from RecyclerView.
|
||||
*/
|
||||
public interface OnChildAttachStateChangeListener {
|
||||
|
||||
/**
|
||||
* Called when a view is attached to the RecyclerView.
|
||||
*
|
||||
* @param view The View which is attached to the RecyclerView
|
||||
*/
|
||||
public void onChildViewAttachedToWindow(View view);
|
||||
|
||||
/**
|
||||
* Called when a view is detached from RecyclerView.
|
||||
*
|
||||
* @param view The View which is being detached from the RecyclerView
|
||||
*/
|
||||
public void onChildViewDetachedFromWindow(View view);
|
||||
}
|
||||
|
||||
/**
|
||||
* A ViewHolder describes an item view and metadata about its place within the RecyclerView.
|
||||
*
|
||||
@@ -7875,6 +8274,55 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
return mAdapterHelper.applyPendingUpdatesToPosition(viewHolder.mPosition);
|
||||
}
|
||||
|
||||
// NestedScrollingChild
|
||||
|
||||
@Override
|
||||
public void setNestedScrollingEnabled(boolean enabled) {
|
||||
mScrollingChildHelper.setNestedScrollingEnabled(enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNestedScrollingEnabled() {
|
||||
return mScrollingChildHelper.isNestedScrollingEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startNestedScroll(int axes) {
|
||||
return mScrollingChildHelper.startNestedScroll(axes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopNestedScroll() {
|
||||
mScrollingChildHelper.stopNestedScroll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNestedScrollingParent() {
|
||||
return mScrollingChildHelper.hasNestedScrollingParent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed,
|
||||
int dyUnconsumed, int[] offsetInWindow) {
|
||||
return mScrollingChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed,
|
||||
dxUnconsumed, dyUnconsumed, offsetInWindow);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
|
||||
return mScrollingChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
|
||||
return mScrollingChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
|
||||
return mScrollingChildHelper.dispatchNestedPreFling(velocityX, velocityY);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link android.view.ViewGroup.MarginLayoutParams LayoutParams} subclass for children of
|
||||
* {@link RecyclerView}. Custom {@link LayoutManager layout managers} are encouraged
|
||||
@@ -9331,4 +9779,35 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
|
||||
this.bottom = bottom;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getChildDrawingOrder(int childCount, int i) {
|
||||
if (mChildDrawingOrderCallback == null) {
|
||||
return super.getChildDrawingOrder(childCount, i);
|
||||
} else {
|
||||
return mChildDrawingOrderCallback.onGetChildDrawingOrder(childCount, i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A callback interface that can be used to alter the drawing order of RecyclerView children.
|
||||
* <p>
|
||||
* It works using the {@link ViewGroup#getChildDrawingOrder(int, int)} method, so any case
|
||||
* that applies to that method also applies to this callback. For example, changing the drawing
|
||||
* order of two views will not have any effect if their elevation values are different since
|
||||
* elevation overrides the result of this callback.
|
||||
*/
|
||||
public static interface ChildDrawingOrderCallback {
|
||||
/**
|
||||
* Returns the index of the child to draw for this iteration. Override this
|
||||
* if you want to change the drawing order of children. By default, it
|
||||
* returns i.
|
||||
*
|
||||
* @param i The current iteration.
|
||||
* @return The index of the child to draw this iteration.
|
||||
*
|
||||
* @see RecyclerView#setChildDrawingOrderCallback(RecyclerView.ChildDrawingOrderCallback)
|
||||
*/
|
||||
public int onGetChildDrawingOrder(int childCount, int i);
|
||||
}
|
||||
}
|
||||
@@ -201,6 +201,18 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor used when layout manager is set in XML by RecyclerView attribute
|
||||
* "layoutManager". Defaults to single column and vertical.
|
||||
*/
|
||||
public StaggeredGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr,
|
||||
int defStyleRes) {
|
||||
Properties properties = getProperties(context, attrs, defStyleAttr, defStyleRes);
|
||||
setOrientation(properties.orientation);
|
||||
setSpanCount(properties.spanCount);
|
||||
setReverseLayout(properties.reverseLayout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a StaggeredGridLayoutManager with given parameters.
|
||||
*
|
||||
@@ -537,7 +549,6 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager {
|
||||
@Override
|
||||
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||
ensureOrientationHelper();
|
||||
|
||||
final AnchorInfo anchorInfo = mAnchorInfo;
|
||||
anchorInfo.reset();
|
||||
|
||||
@@ -577,21 +588,22 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager {
|
||||
detachAndScrapAttachedViews(recycler);
|
||||
mLaidOutInvalidFullSpan = false;
|
||||
updateMeasureSpecs();
|
||||
updateLayoutState(anchorInfo.mPosition, state);
|
||||
if (anchorInfo.mLayoutFromEnd) {
|
||||
// Layout start.
|
||||
updateLayoutStateToFillStart(anchorInfo.mPosition, state);
|
||||
setLayoutStateDirection(LAYOUT_START);
|
||||
fill(recycler, mLayoutState, state);
|
||||
// Layout end.
|
||||
updateLayoutStateToFillEnd(anchorInfo.mPosition, state);
|
||||
mLayoutState.mCurrentPosition += mLayoutState.mItemDirection;
|
||||
setLayoutStateDirection(LAYOUT_END);
|
||||
mLayoutState.mCurrentPosition = anchorInfo.mPosition + mLayoutState.mItemDirection;
|
||||
fill(recycler, mLayoutState, state);
|
||||
} else {
|
||||
// Layout end.
|
||||
updateLayoutStateToFillEnd(anchorInfo.mPosition, state);
|
||||
setLayoutStateDirection(LAYOUT_END);
|
||||
fill(recycler, mLayoutState, state);
|
||||
// Layout start.
|
||||
updateLayoutStateToFillStart(anchorInfo.mPosition, state);
|
||||
mLayoutState.mCurrentPosition += mLayoutState.mItemDirection;
|
||||
setLayoutStateDirection(LAYOUT_START);
|
||||
mLayoutState.mCurrentPosition = anchorInfo.mPosition + mLayoutState.mItemDirection;
|
||||
fill(recycler, mLayoutState, state);
|
||||
}
|
||||
|
||||
@@ -1254,40 +1266,37 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLayoutStateToFillStart(int anchorPosition, RecyclerView.State state) {
|
||||
private void updateLayoutState(int anchorPosition, RecyclerView.State state) {
|
||||
mLayoutState.mAvailable = 0;
|
||||
mLayoutState.mCurrentPosition = anchorPosition;
|
||||
int startExtra = 0;
|
||||
int endExtra = 0;
|
||||
if (isSmoothScrolling()) {
|
||||
final int targetPos = state.getTargetScrollPosition();
|
||||
if (mShouldReverseLayout == targetPos < anchorPosition) {
|
||||
mLayoutState.mExtra = 0;
|
||||
} else {
|
||||
mLayoutState.mExtra = mPrimaryOrientation.getTotalSpace();
|
||||
if (targetPos != NO_POSITION) {
|
||||
if (mShouldReverseLayout == targetPos < anchorPosition) {
|
||||
endExtra = mPrimaryOrientation.getTotalSpace();
|
||||
} else {
|
||||
startExtra = mPrimaryOrientation.getTotalSpace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mLayoutState.mExtra = 0;
|
||||
}
|
||||
mLayoutState.mLayoutDirection = LAYOUT_START;
|
||||
mLayoutState.mItemDirection = mShouldReverseLayout ? ITEM_DIRECTION_TAIL
|
||||
: ITEM_DIRECTION_HEAD;
|
||||
|
||||
// Line of the furthest row.
|
||||
final boolean clipToPadding = getClipToPadding();
|
||||
if (clipToPadding) {
|
||||
mLayoutState.mStartLine = mPrimaryOrientation.getStartAfterPadding() - startExtra;
|
||||
mLayoutState.mEndLine = mPrimaryOrientation.getEndAfterPadding() + endExtra;
|
||||
} else {
|
||||
mLayoutState.mEndLine = mPrimaryOrientation.getEnd() + endExtra;
|
||||
mLayoutState.mStartLine = -startExtra;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLayoutStateToFillEnd(int anchorPosition, RecyclerView.State state) {
|
||||
mLayoutState.mAvailable = 0;
|
||||
mLayoutState.mCurrentPosition = anchorPosition;
|
||||
if (isSmoothScrolling()) {
|
||||
final int targetPos = state.getTargetScrollPosition();
|
||||
if (mShouldReverseLayout == targetPos > anchorPosition) {
|
||||
mLayoutState.mExtra = 0;
|
||||
} else {
|
||||
mLayoutState.mExtra = mPrimaryOrientation.getTotalSpace();
|
||||
}
|
||||
} else {
|
||||
mLayoutState.mExtra = 0;
|
||||
}
|
||||
mLayoutState.mLayoutDirection = LAYOUT_END;
|
||||
mLayoutState.mItemDirection = mShouldReverseLayout ? ITEM_DIRECTION_HEAD
|
||||
: ITEM_DIRECTION_TAIL;
|
||||
private void setLayoutStateDirection(int direction) {
|
||||
mLayoutState.mLayoutDirection = direction;
|
||||
mLayoutState.mItemDirection = (mShouldReverseLayout == (direction == LAYOUT_START)) ?
|
||||
ITEM_DIRECTION_TAIL : ITEM_DIRECTION_HEAD;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1383,31 +1392,25 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager {
|
||||
mRemainingSpans.set(0, mSpanCount, true);
|
||||
// The target position we are trying to reach.
|
||||
final int targetLine;
|
||||
/*
|
||||
* The line until which we can recycle, as long as we add views.
|
||||
* Keep in mind, it is still the line in layout direction which means; to calculate the
|
||||
* actual recycle line, we should subtract/add the size in orientation.
|
||||
*/
|
||||
final int recycleLine;
|
||||
|
||||
// Line of the furthest row.
|
||||
if (layoutState.mLayoutDirection == LAYOUT_END) {
|
||||
// ignore padding for recycler
|
||||
recycleLine = mPrimaryOrientation.getEndAfterPadding() + mLayoutState.mAvailable;
|
||||
targetLine = recycleLine + mLayoutState.mExtra + mPrimaryOrientation.getEndPadding();
|
||||
|
||||
targetLine = layoutState.mEndLine + layoutState.mAvailable;
|
||||
} else { // LAYOUT_START
|
||||
// ignore padding for recycler
|
||||
recycleLine = mPrimaryOrientation.getStartAfterPadding() - mLayoutState.mAvailable;
|
||||
targetLine = recycleLine - mLayoutState.mExtra -
|
||||
mPrimaryOrientation.getStartAfterPadding();
|
||||
targetLine = layoutState.mStartLine - layoutState.mAvailable;
|
||||
}
|
||||
|
||||
updateAllRemainingSpans(layoutState.mLayoutDirection, targetLine);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "FILLING targetLine: " + targetLine + "," +
|
||||
"remaining spans:" + mRemainingSpans + ", state: " + layoutState);
|
||||
}
|
||||
|
||||
// the default coordinate to add new view.
|
||||
final int defaultNewViewLine = mShouldReverseLayout
|
||||
? mPrimaryOrientation.getEndAfterPadding()
|
||||
: mPrimaryOrientation.getStartAfterPadding();
|
||||
|
||||
boolean added = false;
|
||||
while (layoutState.hasMore(state) && !mRemainingSpans.isEmpty()) {
|
||||
View view = layoutState.next(recycler);
|
||||
LayoutParams lp = ((LayoutParams) view.getLayoutParams());
|
||||
@@ -1500,18 +1503,21 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager {
|
||||
} else {
|
||||
updateRemainingSpans(currentSpan, mLayoutState.mLayoutDirection, targetLine);
|
||||
}
|
||||
recycle(recycler, mLayoutState, currentSpan, recycleLine);
|
||||
recycle(recycler, mLayoutState);
|
||||
added = true;
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "fill, " + getChildCount());
|
||||
if (!added) {
|
||||
recycle(recycler, mLayoutState);
|
||||
}
|
||||
final int diff;
|
||||
if (mLayoutState.mLayoutDirection == LAYOUT_START) {
|
||||
final int minStart = getMinStart(mPrimaryOrientation.getStartAfterPadding());
|
||||
return Math.max(0, mLayoutState.mAvailable + (recycleLine - minStart));
|
||||
diff = mPrimaryOrientation.getStartAfterPadding() - minStart;
|
||||
} else {
|
||||
final int max = getMaxEnd(mPrimaryOrientation.getEndAfterPadding());
|
||||
return Math.max(0, mLayoutState.mAvailable + (max - recycleLine));
|
||||
final int maxEnd = getMaxEnd(mPrimaryOrientation.getEndAfterPadding());
|
||||
diff = maxEnd - mPrimaryOrientation.getEndAfterPadding();
|
||||
}
|
||||
return diff > 0 ? Math.min(layoutState.mAvailable, diff) : 0;
|
||||
}
|
||||
|
||||
private LazySpanLookup.FullSpanItem createFullSpanItemFromEnd(int newItemTop) {
|
||||
@@ -1548,19 +1554,40 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void recycle(RecyclerView.Recycler recycler, LayoutState layoutState,
|
||||
Span updatedSpan, int recycleLine) {
|
||||
if (layoutState.mLayoutDirection == LAYOUT_START) {
|
||||
// calculate recycle line
|
||||
int maxStart = getMaxStart(updatedSpan.getStartLine());
|
||||
recycleFromEnd(recycler, Math.max(recycleLine, maxStart) +
|
||||
(mPrimaryOrientation.getEnd() - mPrimaryOrientation.getStartAfterPadding()));
|
||||
private void recycle(RecyclerView.Recycler recycler, LayoutState layoutState) {
|
||||
if (layoutState.mAvailable == 0) {
|
||||
// easy, recycle line is still valid
|
||||
if (layoutState.mLayoutDirection == LAYOUT_START) {
|
||||
recycleFromEnd(recycler, layoutState.mEndLine);
|
||||
} else {
|
||||
recycleFromStart(recycler, layoutState.mStartLine);
|
||||
}
|
||||
} else {
|
||||
// calculate recycle line
|
||||
int minEnd = getMinEnd(updatedSpan.getEndLine());
|
||||
recycleFromStart(recycler, Math.min(recycleLine, minEnd) -
|
||||
(mPrimaryOrientation.getEnd() - mPrimaryOrientation.getStartAfterPadding()));
|
||||
// scrolling case, recycle line can be shifted by how much space we could cover
|
||||
// by adding new views
|
||||
if (layoutState.mLayoutDirection == LAYOUT_START) {
|
||||
// calculate recycle line
|
||||
int scrolled = layoutState.mStartLine - getMaxStart(layoutState.mStartLine);
|
||||
final int line;
|
||||
if (scrolled < 0) {
|
||||
line = layoutState.mEndLine;
|
||||
} else {
|
||||
line = layoutState.mEndLine - Math.min(scrolled, layoutState.mAvailable);
|
||||
}
|
||||
recycleFromEnd(recycler, line);
|
||||
} else {
|
||||
// calculate recycle line
|
||||
int scrolled = getMinEnd(layoutState.mEndLine) - layoutState.mEndLine;
|
||||
final int line;
|
||||
if (scrolled < 0) {
|
||||
line = layoutState.mStartLine;
|
||||
} else {
|
||||
line = layoutState.mStartLine + Math.min(scrolled, layoutState.mAvailable);
|
||||
}
|
||||
recycleFromStart(recycler, line);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void appendViewToAllSpans(View view) {
|
||||
@@ -1602,12 +1629,12 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager {
|
||||
final int deletedSize = span.getDeletedSize();
|
||||
if (layoutDir == LAYOUT_START) {
|
||||
final int line = span.getStartLine();
|
||||
if (line + deletedSize < targetLine) {
|
||||
if (line + deletedSize <= targetLine) {
|
||||
mRemainingSpans.set(span.mIndex, false);
|
||||
}
|
||||
} else {
|
||||
final int line = span.getEndLine();
|
||||
if (line - deletedSize > targetLine) {
|
||||
if (line - deletedSize >= targetLine) {
|
||||
mRemainingSpans.set(span.mIndex, false);
|
||||
}
|
||||
}
|
||||
@@ -1678,18 +1705,24 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager {
|
||||
}
|
||||
|
||||
private void recycleFromStart(RecyclerView.Recycler recycler, int line) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "recycling from start for line " + line);
|
||||
}
|
||||
while (getChildCount() > 0) {
|
||||
View child = getChildAt(0);
|
||||
if (mPrimaryOrientation.getDecoratedEnd(child) < line) {
|
||||
if (mPrimaryOrientation.getDecoratedEnd(child) <= line) {
|
||||
LayoutParams lp = (LayoutParams) child.getLayoutParams();
|
||||
// Don't recycle the last View in a span not to lose span's start/end lines
|
||||
if (lp.mFullSpan) {
|
||||
for (int j = 0; j < mSpanCount; j++) {
|
||||
if (mSpans[j].mViews.size() == 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < mSpanCount; j++) {
|
||||
mSpans[j].popStart();
|
||||
}
|
||||
} else {
|
||||
if (lp.mSpan.mViews.size() == 1) {
|
||||
return;
|
||||
}
|
||||
lp.mSpan.popStart();
|
||||
}
|
||||
removeAndRecycleView(child, recycler);
|
||||
@@ -1704,13 +1737,22 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager {
|
||||
int i;
|
||||
for (i = childCount - 1; i >= 0; i--) {
|
||||
View child = getChildAt(i);
|
||||
if (mPrimaryOrientation.getDecoratedStart(child) > line) {
|
||||
if (mPrimaryOrientation.getDecoratedStart(child) >= line) {
|
||||
LayoutParams lp = (LayoutParams) child.getLayoutParams();
|
||||
// Don't recycle the last View in a span not to lose span's start/end lines
|
||||
if (lp.mFullSpan) {
|
||||
for (int j = 0; j < mSpanCount; j++) {
|
||||
if (mSpans[j].mViews.size() == 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < mSpanCount; j++) {
|
||||
mSpans[j].popEnd();
|
||||
}
|
||||
} else {
|
||||
if (lp.mSpan.mViews.size() == 1) {
|
||||
return;
|
||||
}
|
||||
lp.mSpan.popEnd();
|
||||
}
|
||||
removeAndRecycleView(child, recycler);
|
||||
@@ -1860,21 +1902,19 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager {
|
||||
int scrollBy(int dt, RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||
ensureOrientationHelper();
|
||||
final int referenceChildPosition;
|
||||
final int layoutDir;
|
||||
if (dt > 0) { // layout towards end
|
||||
mLayoutState.mLayoutDirection = LAYOUT_END;
|
||||
mLayoutState.mItemDirection = mShouldReverseLayout ? ITEM_DIRECTION_HEAD
|
||||
: ITEM_DIRECTION_TAIL;
|
||||
layoutDir = LAYOUT_END;
|
||||
referenceChildPosition = getLastChildPosition();
|
||||
} else {
|
||||
mLayoutState.mLayoutDirection = LAYOUT_START;
|
||||
mLayoutState.mItemDirection = mShouldReverseLayout ? ITEM_DIRECTION_TAIL
|
||||
: ITEM_DIRECTION_HEAD;
|
||||
layoutDir = LAYOUT_START;
|
||||
referenceChildPosition = getFirstChildPosition();
|
||||
}
|
||||
updateLayoutState(referenceChildPosition, state);
|
||||
setLayoutStateDirection(layoutDir);
|
||||
mLayoutState.mCurrentPosition = referenceChildPosition + mLayoutState.mItemDirection;
|
||||
final int absDt = Math.abs(dt);
|
||||
mLayoutState.mAvailable = absDt;
|
||||
mLayoutState.mExtra = isSmoothScrolling() ? mPrimaryOrientation.getTotalSpace() : 0;
|
||||
int consumed = fill(recycler, mLayoutState, state);
|
||||
final int totalScroll;
|
||||
if (absDt < consumed) {
|
||||
|
||||
Reference in new issue
Block a user