17149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas/* 27149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Copyright (C) 2017 The Android Open Source Project 37149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 47149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Licensed under the Apache License, Version 2.0 (the "License"); 57149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * you may not use this file except in compliance with the License. 67149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * You may obtain a copy of the License at 77149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 87149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * http://www.apache.org/licenses/LICENSE-2.0 97149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Unless required by applicable law or agreed to in writing, software 117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * distributed under the License is distributed on an "AS IS" BASIS, 127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * See the License for the specific language governing permissions and 147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * limitations under the License. 157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikaspackage com.android.internal.widget; 187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.annotation.CallSuper; 207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.annotation.IntDef; 217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.annotation.NonNull; 227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.annotation.Nullable; 237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.content.Context; 247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.content.res.TypedArray; 257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.database.Observable; 267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.graphics.Canvas; 277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.graphics.Matrix; 287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.graphics.PointF; 297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.graphics.Rect; 307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.graphics.RectF; 317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.os.Build; 327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.os.Bundle; 337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.os.Parcel; 347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.os.Parcelable; 357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.os.SystemClock; 367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.os.Trace; 377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.util.AttributeSet; 387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.util.Log; 397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.util.SparseArray; 407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.util.TypedValue; 417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.view.AbsSavedState; 427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.view.Display; 437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.view.FocusFinder; 447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.view.InputDevice; 457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.view.MotionEvent; 467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.view.VelocityTracker; 477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.view.View; 487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.view.ViewConfiguration; 497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.view.ViewGroup; 507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.view.ViewParent; 517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.view.accessibility.AccessibilityEvent; 527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.view.accessibility.AccessibilityManager; 537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.view.accessibility.AccessibilityNodeInfo; 547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.view.animation.Interpolator; 557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.widget.EdgeEffect; 567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport android.widget.OverScroller; 577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport com.android.internal.R; 597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport com.android.internal.annotations.VisibleForTesting; 607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport com.android.internal.widget.RecyclerView.ItemAnimator.ItemHolderInfo; 617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport java.lang.annotation.Retention; 637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport java.lang.annotation.RetentionPolicy; 647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport java.lang.ref.WeakReference; 657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport java.lang.reflect.Constructor; 667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport java.lang.reflect.InvocationTargetException; 677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport java.util.ArrayList; 687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport java.util.Collections; 697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikasimport java.util.List; 707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas/** 727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * A flexible view for providing a limited window into a large data set. 737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <h3>Glossary of terms:</h3> 757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <ul> 777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li><em>Adapter:</em> A subclass of {@link Adapter} responsible for providing views 787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * that represent items in a data set.</li> 797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li><em>Position:</em> The position of a data item within an <em>Adapter</em>.</li> 807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li><em>Index:</em> The index of an attached child view as used in a call to 817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link ViewGroup#getChildAt}. Contrast with <em>Position.</em></li> 827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li><em>Binding:</em> The process of preparing a child view to display data corresponding 837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to a <em>position</em> within the adapter.</li> 847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li><em>Recycle (view):</em> A view previously used to display data for a specific adapter 857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * position may be placed in a cache for later reuse to display the same type of data again 867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * later. This can drastically improve performance by skipping initial layout inflation 877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * or construction.</li> 887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li><em>Scrap (view):</em> A child view that has entered into a temporarily detached 897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * state during layout. Scrap views may be reused without becoming fully detached 907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * from the parent RecyclerView, either unmodified if no rebinding is required or modified 917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * by the adapter if the view was considered <em>dirty</em>.</li> 927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li><em>Dirty (view):</em> A child view that must be rebound by the adapter before 937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * being displayed.</li> 947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * </ul> 957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <h4>Positions in RecyclerView:</h4> 977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView introduces an additional level of abstraction between the {@link Adapter} and 997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link LayoutManager} to be able to detect data set changes in batches during a layout 1007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * calculation. This saves LayoutManager from tracking adapter changes to calculate animations. 1017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * It also helps with performance because all view bindings happen at the same time and unnecessary 1027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * bindings are avoided. 1037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 1047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * For this reason, there are two types of <code>position</code> related methods in RecyclerView: 1057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <ul> 1067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>layout position: Position of an item in the latest layout calculation. This is the 1077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * position from the LayoutManager's perspective.</li> 1087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>adapter position: Position of an item in the adapter. This is the position from 1097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the Adapter's perspective.</li> 1107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * </ul> 1117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 1127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * These two positions are the same except the time between dispatching <code>adapter.notify* 1137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * </code> events and calculating the updated layout. 1147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 1157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Methods that return or receive <code>*LayoutPosition*</code> use position as of the latest 1167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * layout calculation (e.g. {@link ViewHolder#getLayoutPosition()}, 1177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #findViewHolderForLayoutPosition(int)}). These positions include all changes until the 1187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * last layout calculation. You can rely on these positions to be consistent with what user is 1197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * currently seeing on the screen. For example, if you have a list of items on the screen and user 1207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * asks for the 5<sup>th</sup> element, you should use these methods as they'll match what user 1217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * is seeing. 1227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 1237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The other set of position related methods are in the form of 1247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <code>*AdapterPosition*</code>. (e.g. {@link ViewHolder#getAdapterPosition()}, 1257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #findViewHolderForAdapterPosition(int)}) You should use these methods when you need to 1267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * work with up-to-date adapter positions even if they may not have been reflected to layout yet. 1277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * For example, if you want to access the item in the adapter on a ViewHolder click, you should use 1287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link ViewHolder#getAdapterPosition()}. Beware that these methods may not be able to calculate 1297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * adapter positions if {@link Adapter#notifyDataSetChanged()} has been called and new layout has 1307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * not yet been calculated. For this reasons, you should carefully handle {@link #NO_POSITION} or 1317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <code>null</code> results from these methods. 1327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 1337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * When writing a {@link LayoutManager} you almost always want to use layout positions whereas when 1347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * writing an {@link Adapter}, you probably want to use adapter positions. 1357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 1367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikaspublic class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild { 1377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 1387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final String TAG = "RecyclerView"; 1397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 1407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final boolean DEBUG = false; 1417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 1427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private static final int[] NESTED_SCROLLING_ATTRS = { android.R.attr.nestedScrollingEnabled }; 1437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 1447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private static final int[] CLIP_TO_PADDING_ATTR = {android.R.attr.clipToPadding}; 1457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 1467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 1477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * On Kitkat and JB MR2, there is a bug which prevents DisplayList from being invalidated if 1487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * a View is two levels deep(wrt to ViewHolder.itemView). DisplayList can be invalidated by 1497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * setting View's visibility to INVISIBLE when View is detached. On Kitkat and JB MR2, Recycler 1507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * recursively traverses itemView and invalidates display list for each ViewGroup that matches 1517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * this criteria. 1527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 1537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final boolean FORCE_INVALIDATE_DISPLAY_LIST = Build.VERSION.SDK_INT == 18 1547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || Build.VERSION.SDK_INT == 19 || Build.VERSION.SDK_INT == 20; 1557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 1567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * On M+, an unspecified measure spec may include a hint which we can use. On older platforms, 1577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * this value might be garbage. To save LayoutManagers from it, RecyclerView sets the size to 1587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 0 when mode is unspecified. 1597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 1607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final boolean ALLOW_SIZE_IN_UNSPECIFIED_SPEC = Build.VERSION.SDK_INT >= 23; 1617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 1627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final boolean POST_UPDATES_ON_ANIMATION = Build.VERSION.SDK_INT >= 16; 1637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 1647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 1657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * On L+, with RenderThread, the UI thread has idle time after it has passed a frame off to 1667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RenderThread but before the next frame begins. We schedule prefetch work in this window. 1677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 1687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private static final boolean ALLOW_THREAD_GAP_WORK = Build.VERSION.SDK_INT >= 21; 1697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 1707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 1717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * FocusFinder#findNextFocus is broken on ICS MR1 and older for View.FOCUS_BACKWARD direction. 1727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * We convert it to an absolute direction such as FOCUS_DOWN or FOCUS_LEFT. 1737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 1747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private static final boolean FORCE_ABS_FOCUS_SEARCH_DIRECTION = Build.VERSION.SDK_INT <= 15; 1757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 1767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 1777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * on API 15-, a focused child can still be considered a focused child of RV even after 1787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * it's being removed or its focusable flag is set to false. This is because when this focused 1797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * child is detached, the reference to this child is not removed in clearFocus. API 16 and above 1807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * properly handle this case by calling ensureInputFocusOnFirstFocusable or rootViewRequestFocus 1817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to request focus on a new child, which will clear the focus on the old (detached) child as a 1827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * side-effect. 1837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 1847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private static final boolean IGNORE_DETACHED_FOCUSED_CHILD = Build.VERSION.SDK_INT <= 15; 1857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 1867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final boolean DISPATCH_TEMP_DETACH = false; 1877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static final int HORIZONTAL = 0; 1887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static final int VERTICAL = 1; 1897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 1907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static final int NO_POSITION = -1; 1917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static final long NO_ID = -1; 1927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static final int INVALID_TYPE = -1; 1937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 1947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 1957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Constant for use with {@link #setScrollingTouchSlop(int)}. Indicates 1967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * that the RecyclerView should use the standard touch slop for smooth, 1977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * continuous scrolling. 1987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 1997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static final int TOUCH_SLOP_DEFAULT = 0; 2007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 2017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 2027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Constant for use with {@link #setScrollingTouchSlop(int)}. Indicates 2037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * that the RecyclerView should use the standard touch slop for scrolling 2047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * widgets that snap to a page or other coarse-grained barrier. 2057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 2067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static final int TOUCH_SLOP_PAGING = 1; 2077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 2087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final int MAX_SCROLL_DURATION = 2000; 2097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 2107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 2117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView is calculating a scroll. 2127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If there are too many of these in Systrace, some Views inside RecyclerView might be causing 2137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * it. Try to avoid using EditText, focusable views or handle them with care. 2147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 2157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final String TRACE_SCROLL_TAG = "RV Scroll"; 2167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 2177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 2187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * OnLayout has been called by the View system. 2197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If this shows up too many times in Systrace, make sure the children of RecyclerView do not 2207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * update themselves directly. This will cause a full re-layout but when it happens via the 2217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Adapter notifyItemChanged, RecyclerView can avoid full layout calculation. 2227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 2237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private static final String TRACE_ON_LAYOUT_TAG = "RV OnLayout"; 2247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 2257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 2267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * NotifyDataSetChanged or equal has been called. 2277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If this is taking a long time, try sending granular notify adapter changes instead of just 2287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * calling notifyDataSetChanged or setAdapter / swapAdapter. Adding stable ids to your adapter 2297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * might help. 2307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 2317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private static final String TRACE_ON_DATA_SET_CHANGE_LAYOUT_TAG = "RV FullInvalidate"; 2327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 2337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 2347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView is doing a layout for partial adapter updates (we know what has changed) 2357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If this is taking a long time, you may have dispatched too many Adapter updates causing too 2367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * many Views being rebind. Make sure all are necessary and also prefer using notify*Range 2377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * methods. 2387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 2397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private static final String TRACE_HANDLE_ADAPTER_UPDATES_TAG = "RV PartialInvalidate"; 2407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 2417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 2427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView is rebinding a View. 2437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If this is taking a lot of time, consider optimizing your layout or make sure you are not 2447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * doing extra operations in onBindViewHolder call. 2457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 2467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final String TRACE_BIND_VIEW_TAG = "RV OnBindView"; 2477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 2487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 2497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView is attempting to pre-populate off screen views. 2507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 2517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final String TRACE_PREFETCH_TAG = "RV Prefetch"; 2527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 2537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 2547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView is attempting to pre-populate off screen itemviews within an off screen 2557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView. 2567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 2577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final String TRACE_NESTED_PREFETCH_TAG = "RV Nested Prefetch"; 2587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 2597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 2607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView is creating a new View. 2617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If too many of these present in Systrace: 2627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * - There might be a problem in Recycling (e.g. custom Animations that set transient state and 2637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * prevent recycling or ItemAnimator not implementing the contract properly. ({@link 2647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * > Adapter#onFailedToRecycleView(ViewHolder)}) 2657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 2667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * - There might be too many item view types. 2677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * > Try merging them 2687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 2697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * - There might be too many itemChange animations and not enough space in RecyclerPool. 2707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * >Try increasing your pool size and item cache size. 2717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 2727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final String TRACE_CREATE_VIEW_TAG = "RV CreateView"; 2737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private static final Class<?>[] LAYOUT_MANAGER_CONSTRUCTOR_SIGNATURE = 2747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas new Class[]{Context.class, AttributeSet.class, int.class, int.class}; 2757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 2767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver(); 2777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 2787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final Recycler mRecycler = new Recycler(); 2797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 2807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private SavedState mPendingSavedState; 2817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 2827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 2837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Handles adapter updates 2847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 2857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas AdapterHelper mAdapterHelper; 2867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 2877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 2887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Handles abstraction between LayoutManager children and RecyclerView children 2897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 2907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ChildHelper mChildHelper; 2917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 2927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 2937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Keeps data about views to be used for animations 2947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 2957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewInfoStore mViewInfoStore = new ViewInfoStore(); 2967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 2977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 2987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Prior to L, there is no way to query this variable which is why we override the setter and 2997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * track it here. 3007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 3017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean mClipToPadding; 3027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 3037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 3047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note: this Runnable is only ever posted if: 3057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 1) We've been through first layout 3067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 2) We know we have a fixed size (mHasFixedSize) 3077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 3) We're attached 3087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 3097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final Runnable mUpdateChildViewsRunnable = new Runnable() { 3107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 3117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void run() { 3127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!mFirstLayoutComplete || isLayoutRequested()) { 3137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // a layout request will happen, we should not do layout here. 3147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 3157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 3167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!mIsAttached) { 3177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas requestLayout(); 3187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // if we are not attached yet, mark us as requiring layout and skip 3197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 3207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 3217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayoutFrozen) { 3227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayoutRequestEaten = true; 3237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; //we'll process updates when ice age ends. 3247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 3257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas consumePendingUpdateOperations(); 3267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 3277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas }; 3287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 3297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final Rect mTempRect = new Rect(); 3307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private final Rect mTempRect2 = new Rect(); 3317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final RectF mTempRectF = new RectF(); 3327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Adapter mAdapter; 3337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @VisibleForTesting LayoutManager mLayout; 3347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas RecyclerListener mRecyclerListener; 3357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ArrayList<ItemDecoration> mItemDecorations = new ArrayList<>(); 3367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private final ArrayList<OnItemTouchListener> mOnItemTouchListeners = 3377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas new ArrayList<>(); 3387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private OnItemTouchListener mActiveOnItemTouchListener; 3397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean mIsAttached; 3407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean mHasFixedSize; 3417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @VisibleForTesting boolean mFirstLayoutComplete; 3427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 3437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Counting lock to control whether we should ignore requestLayout calls from children or not. 3447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mEatRequestLayout = 0; 3457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 3467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean mLayoutRequestEaten; 3477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean mLayoutFrozen; 3487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private boolean mIgnoreMotionEventTillDown; 3497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 3507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // binary OR of change events that were eaten during a layout or scroll. 3517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mEatenAccessibilityChangeFlags; 3527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean mAdapterUpdateDuringMeasure; 3537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 3547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private final AccessibilityManager mAccessibilityManager; 3557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private List<OnChildAttachStateChangeListener> mOnChildAttachStateListeners; 3567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 3577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 3587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Set to true when an adapter data set changed notification is received. 3597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * In that case, we cannot run any animations since we don't know what happened until layout. 3607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 3617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Attached items are invalid until next layout, at which point layout will animate/replace 3627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * items as necessary, building up content from the (effectively) new adapter from scratch. 3637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 3647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Cached items must be discarded when setting this to true, so that the cache may be freely 3657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * used by prefetching until the next layout occurs. 3667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 3677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #setDataSetChangedAfterLayout() 3687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 3697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean mDataSetHasChangedAfterLayout = false; 3707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 3717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 3727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This variable is incremented during a dispatchLayout and/or scroll. 3737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Some methods should not be called during these periods (e.g. adapter data change). 3747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Doing so will create hard to find bugs so we better check it and throw an exception. 3757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 3767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #assertInLayoutOrScroll(String) 3777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #assertNotInLayoutOrScroll(String) 3787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 3797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mLayoutOrScrollCounter = 0; 3807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 3817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 3827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Similar to mLayoutOrScrollCounter but logs a warning instead of throwing an exception 3837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * (for API compatibility). 3847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 3857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * It is a bad practice for a developer to update the data in a scroll callback since it is 3867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * potentially called during a layout. 3877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 3887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mDispatchScrollCounter = 0; 3897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 3907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private EdgeEffect mLeftGlow, mTopGlow, mRightGlow, mBottomGlow; 3917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 3927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ItemAnimator mItemAnimator = new DefaultItemAnimator(); 3937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 3947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private static final int INVALID_POINTER = -1; 3957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 3967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 3977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The RecyclerView is not currently scrolling. 3987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #getScrollState() 3997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 4007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static final int SCROLL_STATE_IDLE = 0; 4017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 4027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 4037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The RecyclerView is currently being dragged by outside input such as user touch input. 4047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #getScrollState() 4057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 4067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static final int SCROLL_STATE_DRAGGING = 1; 4077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 4087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 4097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The RecyclerView is currently animating to a final position while not under 4107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * outside control. 4117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #getScrollState() 4127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 4137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static final int SCROLL_STATE_SETTLING = 2; 4147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 4157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final long FOREVER_NS = Long.MAX_VALUE; 4167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 4177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Touch/scrolling handling 4187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 4197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mScrollState = SCROLL_STATE_IDLE; 4207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mScrollPointerId = INVALID_POINTER; 4217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private VelocityTracker mVelocityTracker; 4227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mInitialTouchX; 4237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mInitialTouchY; 4247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mLastTouchX; 4257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mLastTouchY; 4267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mTouchSlop; 4277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private OnFlingListener mOnFlingListener; 4287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private final int mMinFlingVelocity; 4297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private final int mMaxFlingVelocity; 4307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // This value is used when handling generic motion events. 4317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private float mScrollFactor = Float.MIN_VALUE; 4327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private boolean mPreserveFocusAfterLayout = true; 4337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 4347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewFlinger mViewFlinger = new ViewFlinger(); 4357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 4367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas GapWorker mGapWorker; 4377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas GapWorker.LayoutPrefetchRegistryImpl mPrefetchRegistry = 4387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ALLOW_THREAD_GAP_WORK ? new GapWorker.LayoutPrefetchRegistryImpl() : null; 4397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 4407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final State mState = new State(); 4417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 4427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private OnScrollListener mScrollListener; 4437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private List<OnScrollListener> mScrollListeners; 4447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 4457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // For use in item animations 4467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean mItemsAddedOrRemoved = false; 4477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean mItemsChanged = false; 4487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private ItemAnimator.ItemAnimatorListener mItemAnimatorListener = 4497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas new ItemAnimatorRestoreListener(); 4507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean mPostedAnimatorRunner = false; 4517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas RecyclerViewAccessibilityDelegate mAccessibilityDelegate; 4527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private ChildDrawingOrderCallback mChildDrawingOrderCallback; 4537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 4547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // simple array to keep min and max child position during a layout calculation 4557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // preserved not to create a new one in each layout pass 4567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private final int[] mMinMaxLayoutPositions = new int[2]; 4577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 4587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private final int[] mScrollOffset = new int[2]; 4597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private final int[] mScrollConsumed = new int[2]; 4607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private final int[] mNestedOffsets = new int[2]; 4617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 4627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 4637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * These are views that had their a11y importance changed during a layout. We defer these events 4647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * until the end of the layout because a11y service may make sync calls back to the RV while 4657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the View's state is undefined. 4667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 4677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @VisibleForTesting 4687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final List<ViewHolder> mPendingAccessibilityImportanceChange = new ArrayList(); 4697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 4707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private Runnable mItemAnimatorRunner = new Runnable() { 4717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 4727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void run() { 4737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mItemAnimator != null) { 4747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemAnimator.runPendingAnimations(); 4757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 4767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPostedAnimatorRunner = false; 4777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 4787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas }; 4797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 4807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final Interpolator sQuinticInterpolator = new Interpolator() { 4817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 4827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public float getInterpolation(float t) { 4837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas t -= 1.0f; 4847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return t * t * t * t * t + 1.0f; 4857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 4867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas }; 4877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 4887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 4897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The callback to convert view info diffs into animations. 4907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 4917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private final ViewInfoStore.ProcessCallback mViewInfoProcessCallback = 4927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas new ViewInfoStore.ProcessCallback() { 4937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 4947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void processDisappeared(ViewHolder viewHolder, @NonNull ItemHolderInfo info, 4957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Nullable ItemHolderInfo postInfo) { 4967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.unscrapView(viewHolder); 4977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas animateDisappearance(viewHolder, info, postInfo); 4987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 4997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 5007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void processAppeared(ViewHolder viewHolder, 5017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ItemHolderInfo preInfo, ItemHolderInfo info) { 5027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas animateAppearance(viewHolder, preInfo, info); 5037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 5047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 5057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 5067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void processPersistent(ViewHolder viewHolder, 5077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @NonNull ItemHolderInfo preInfo, @NonNull ItemHolderInfo postInfo) { 5087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas viewHolder.setIsRecyclable(false); 5097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mDataSetHasChangedAfterLayout) { 5107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // since it was rebound, use change instead as we'll be mapping them from 5117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // stable ids. If stable ids were false, we would not be running any 5127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // animations 5137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mItemAnimator.animateChange(viewHolder, viewHolder, preInfo, postInfo)) { 5147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas postAnimationRunner(); 5157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 5167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (mItemAnimator.animatePersistence(viewHolder, preInfo, postInfo)) { 5177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas postAnimationRunner(); 5187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 5197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 5207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 5217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void unused(ViewHolder viewHolder) { 5227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.removeAndRecycleView(viewHolder.itemView, mRecycler); 5237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 5247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas }; 5257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 5267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public RecyclerView(Context context) { 5277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas this(context, null); 5287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 5297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 5307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public RecyclerView(Context context, @Nullable AttributeSet attrs) { 5317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas this(context, attrs, 0); 5327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 5337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 5347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public RecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { 5357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super(context, attrs, defStyle); 5367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (attrs != null) { 5377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas TypedArray a = context.obtainStyledAttributes(attrs, CLIP_TO_PADDING_ATTR, defStyle, 0); 5387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mClipToPadding = a.getBoolean(0, true); 5397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas a.recycle(); 5407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 5417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mClipToPadding = true; 5427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 5437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setScrollContainer(true); 5447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setFocusableInTouchMode(true); 5457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 5467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewConfiguration vc = ViewConfiguration.get(context); 5477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTouchSlop = vc.getScaledTouchSlop(); 5487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mMinFlingVelocity = vc.getScaledMinimumFlingVelocity(); 5497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity(); 5507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setWillNotDraw(getOverScrollMode() == View.OVER_SCROLL_NEVER); 5517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 5527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemAnimator.setListener(mItemAnimatorListener); 5537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas initAdapterManager(); 5547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas initChildrenHelper(); 5557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // If not explicitly specified this view is important for accessibility. 5567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) { 5577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); 5587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 5597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAccessibilityManager = (AccessibilityManager) getContext() 5607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas .getSystemService(Context.ACCESSIBILITY_SERVICE); 5617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setAccessibilityDelegateCompat(new RecyclerViewAccessibilityDelegate(this)); 5627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Create the layoutManager if specified. 5637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 5647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean nestedScrollingEnabled = true; 5657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 5667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (attrs != null) { 5677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int defStyleRes = 0; 5687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RecyclerView, 5697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas defStyle, defStyleRes); 5707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas String layoutManagerName = a.getString(R.styleable.RecyclerView_layoutManager); 5717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int descendantFocusability = a.getInt( 5727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas R.styleable.RecyclerView_descendantFocusability, -1); 5737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (descendantFocusability == -1) { 5747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); 5757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 5767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas a.recycle(); 5777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas createLayoutManager(context, layoutManagerName, attrs, defStyle, defStyleRes); 5787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 5797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (Build.VERSION.SDK_INT >= 21) { 5807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas a = context.obtainStyledAttributes(attrs, NESTED_SCROLLING_ATTRS, 5817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas defStyle, defStyleRes); 5827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas nestedScrollingEnabled = a.getBoolean(0, true); 5837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas a.recycle(); 5847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 5857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 5867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); 5877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 5887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 5897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Re-set whether nested scrolling is enabled so that it is set on all API levels 5907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setNestedScrollingEnabled(nestedScrollingEnabled); 5917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 5927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 5937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 5947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the accessibility delegate compatibility implementation used by the RecyclerView. 5957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return An instance of AccessibilityDelegateCompat used by RecyclerView 5967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 5977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public RecyclerViewAccessibilityDelegate getCompatAccessibilityDelegate() { 5987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mAccessibilityDelegate; 5997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 6007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 6017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 6027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Sets the accessibility delegate compatibility implementation used by RecyclerView. 6037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param accessibilityDelegate The accessibility delegate to be used by RecyclerView. 6047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 6057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setAccessibilityDelegateCompat( 6067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas RecyclerViewAccessibilityDelegate accessibilityDelegate) { 6077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAccessibilityDelegate = accessibilityDelegate; 6087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setAccessibilityDelegate(mAccessibilityDelegate); 6097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 6107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 6117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 6127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Instantiate and set a LayoutManager, if specified in the attributes. 6137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 6147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void createLayoutManager(Context context, String className, AttributeSet attrs, 6157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int defStyleAttr, int defStyleRes) { 6167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (className != null) { 6177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas className = className.trim(); 6187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (className.length() != 0) { // Can't use isEmpty since it was added in API 9. 6197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas className = getFullClassName(context, className); 6207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas try { 6217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ClassLoader classLoader; 6227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (isInEditMode()) { 6237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Stupid layoutlib cannot handle simple class loaders. 6247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas classLoader = this.getClass().getClassLoader(); 6257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 6267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas classLoader = context.getClassLoader(); 6277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 6287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Class<? extends LayoutManager> layoutManagerClass = 6297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas classLoader.loadClass(className).asSubclass(LayoutManager.class); 6307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Constructor<? extends LayoutManager> constructor; 6317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Object[] constructorArgs = null; 6327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas try { 6337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas constructor = layoutManagerClass 6347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas .getConstructor(LAYOUT_MANAGER_CONSTRUCTOR_SIGNATURE); 6357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas constructorArgs = new Object[]{context, attrs, defStyleAttr, defStyleRes}; 6367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } catch (NoSuchMethodException e) { 6377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas try { 6387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas constructor = layoutManagerClass.getConstructor(); 6397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } catch (NoSuchMethodException e1) { 6407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas e1.initCause(e); 6417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException(attrs.getPositionDescription() 6427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + ": Error creating LayoutManager " + className, e1); 6437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 6447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 6457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas constructor.setAccessible(true); 6467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setLayoutManager(constructor.newInstance(constructorArgs)); 6477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } catch (ClassNotFoundException e) { 6487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException(attrs.getPositionDescription() 6497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + ": Unable to find LayoutManager " + className, e); 6507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } catch (InvocationTargetException e) { 6517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException(attrs.getPositionDescription() 6527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + ": Could not instantiate the LayoutManager: " + className, e); 6537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } catch (InstantiationException e) { 6547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException(attrs.getPositionDescription() 6557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + ": Could not instantiate the LayoutManager: " + className, e); 6567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } catch (IllegalAccessException e) { 6577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException(attrs.getPositionDescription() 6587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + ": Cannot access non-public constructor " + className, e); 6597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } catch (ClassCastException e) { 6607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException(attrs.getPositionDescription() 6617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + ": Class is not a LayoutManager " + className, e); 6627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 6637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 6647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 6657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 6667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 6677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private String getFullClassName(Context context, String className) { 6687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (className.charAt(0) == '.') { 6697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return context.getPackageName() + className; 6707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 6717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (className.contains(".")) { 6727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return className; 6737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 6747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return RecyclerView.class.getPackage().getName() + '.' + className; 6757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 6767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 6777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void initChildrenHelper() { 6787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChildHelper = new ChildHelper(new ChildHelper.Callback() { 6797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 6807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getChildCount() { 6817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return RecyclerView.this.getChildCount(); 6827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 6837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 6847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 6857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void addView(View child, int index) { 6867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas RecyclerView.this.addView(child, index); 6877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchChildAttached(child); 6887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 6897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 6907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 6917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int indexOfChild(View view) { 6927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return RecyclerView.this.indexOfChild(view); 6937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 6947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 6957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 6967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void removeViewAt(int index) { 6977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View child = RecyclerView.this.getChildAt(index); 6987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (child != null) { 6997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchChildDetached(child); 7007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas RecyclerView.this.removeViewAt(index); 7027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 7047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 7057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public View getChildAt(int offset) { 7067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return RecyclerView.this.getChildAt(offset); 7077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 7097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 7107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void removeAllViews() { 7117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int count = getChildCount(); 7127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < count; i++) { 7137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchChildDetached(getChildAt(i)); 7147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas RecyclerView.this.removeAllViews(); 7167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 7187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 7197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public ViewHolder getChildViewHolder(View view) { 7207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return getChildViewHolderInt(view); 7217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 7237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 7247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void attachViewToParent(View child, int index, 7257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewGroup.LayoutParams layoutParams) { 7267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder vh = getChildViewHolderInt(child); 7277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (vh != null) { 7287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!vh.isTmpDetached() && !vh.shouldIgnore()) { 7297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalArgumentException("Called attach on a child which is not" 7307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " detached: " + vh); 7317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 7337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.d(TAG, "reAttach " + vh); 7347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas vh.clearTmpDetachFlag(); 7367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas RecyclerView.this.attachViewToParent(child, index, layoutParams); 7387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 7407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 7417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void detachViewFromParent(int offset) { 7427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View view = getChildAt(offset); 7437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (view != null) { 7447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder vh = getChildViewHolderInt(view); 7457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (vh != null) { 7467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (vh.isTmpDetached() && !vh.shouldIgnore()) { 7477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalArgumentException("called detach on an already" 7487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " detached child " + vh); 7497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 7517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.d(TAG, "tmpDetach " + vh); 7527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas vh.addFlags(ViewHolder.FLAG_TMP_DETACHED); 7547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas RecyclerView.this.detachViewFromParent(offset); 7577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 7597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 7607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onEnteredHiddenState(View child) { 7617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder vh = getChildViewHolderInt(child); 7627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (vh != null) { 7637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas vh.onEnteredHiddenState(RecyclerView.this); 7647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 7677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 7687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onLeftHiddenState(View child) { 7697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder vh = getChildViewHolderInt(child); 7707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (vh != null) { 7717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas vh.onLeftHiddenState(RecyclerView.this); 7727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas }); 7757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 7777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void initAdapterManager() { 7787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAdapterHelper = new AdapterHelper(new AdapterHelper.Callback() { 7797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 7807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public ViewHolder findViewHolder(int position) { 7817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder vh = findViewHolderForPosition(position, true); 7827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (vh == null) { 7837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 7847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // ensure it is not hidden because for adapter helper, the only thing matter is that 7867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // LM thinks view is a child. 7877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mChildHelper.isHidden(vh.itemView)) { 7887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 7897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.d(TAG, "assuming view holder cannot be find because it is hidden"); 7907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 7927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return vh; 7947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 7957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 7967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 7977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void offsetPositionsForRemovingInvisible(int start, int count) { 7987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas offsetPositionRecordsForRemove(start, count, true); 7997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemsAddedOrRemoved = true; 8007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mDeletedInvisibleItemCountSincePreviousLayout += count; 8017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 8027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 8037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 8047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void offsetPositionsForRemovingLaidOutOrNewView( 8057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int positionStart, int itemCount) { 8067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas offsetPositionRecordsForRemove(positionStart, itemCount, false); 8077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemsAddedOrRemoved = true; 8087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 8097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 8107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 8117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void markViewHoldersUpdated(int positionStart, int itemCount, Object payload) { 8127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas viewRangeUpdate(positionStart, itemCount, payload); 8137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemsChanged = true; 8147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 8157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 8167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 8177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onDispatchFirstPass(AdapterHelper.UpdateOp op) { 8187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchUpdate(op); 8197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 8207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 8217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void dispatchUpdate(AdapterHelper.UpdateOp op) { 8227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas switch (op.cmd) { 8237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case AdapterHelper.UpdateOp.ADD: 8247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.onItemsAdded(RecyclerView.this, op.positionStart, op.itemCount); 8257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas break; 8267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case AdapterHelper.UpdateOp.REMOVE: 8277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.onItemsRemoved(RecyclerView.this, op.positionStart, op.itemCount); 8287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas break; 8297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case AdapterHelper.UpdateOp.UPDATE: 8307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.onItemsUpdated(RecyclerView.this, op.positionStart, op.itemCount, 8317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas op.payload); 8327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas break; 8337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case AdapterHelper.UpdateOp.MOVE: 8347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.onItemsMoved(RecyclerView.this, op.positionStart, op.itemCount, 1); 8357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas break; 8367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 8377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 8387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 8397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 8407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onDispatchSecondPass(AdapterHelper.UpdateOp op) { 8417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchUpdate(op); 8427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 8437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 8447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 8457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void offsetPositionsForAdd(int positionStart, int itemCount) { 8467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas offsetPositionRecordsForInsert(positionStart, itemCount); 8477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemsAddedOrRemoved = true; 8487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 8497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 8507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 8517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void offsetPositionsForMove(int from, int to) { 8527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas offsetPositionRecordsForMove(from, to); 8537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // should we create mItemsMoved ? 8547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemsAddedOrRemoved = true; 8557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 8567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas }); 8577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 8587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 8597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 8607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView can perform several optimizations if it can know in advance that RecyclerView's 8617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * size is not affected by the adapter contents. RecyclerView can still change its size based 8627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * on other factors (e.g. its parent's size) but this size calculation cannot depend on the 8637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * size of its children or contents of its adapter (except the number of items in the adapter). 8647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 8657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If your use of RecyclerView falls into this category, set this to {@code true}. It will allow 8667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView to avoid invalidating the whole layout when its adapter contents change. 8677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 8687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param hasFixedSize true if adapter changes cannot affect the size of the RecyclerView. 8697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 8707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setHasFixedSize(boolean hasFixedSize) { 8717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mHasFixedSize = hasFixedSize; 8727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 8737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 8747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 8757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if the app has specified that changes in adapter content cannot change 8767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the size of the RecyclerView itself. 8777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 8787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean hasFixedSize() { 8797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mHasFixedSize; 8807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 8817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 8827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 8837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setClipToPadding(boolean clipToPadding) { 8847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (clipToPadding != mClipToPadding) { 8857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas invalidateGlows(); 8867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 8877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mClipToPadding = clipToPadding; 8887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super.setClipToPadding(clipToPadding); 8897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mFirstLayoutComplete) { 8907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas requestLayout(); 8917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 8927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 8937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 8947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 8957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns whether this RecyclerView will clip its children to its padding, and resize (but 8967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * not clip) any EdgeEffect to the padded region, if padding is present. 8977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 8987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * By default, children are clipped to the padding of their parent 8997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView. This clipping behavior is only enabled if padding is non-zero. 9007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 9017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if this RecyclerView clips children to its padding and resizes (but doesn't 9027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * clip) any EdgeEffect to the padded region, false otherwise. 9037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 9047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @attr name android:clipToPadding 9057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 9067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 9077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean getClipToPadding() { 9087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mClipToPadding; 9097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 9107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 9117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 9127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Configure the scrolling touch slop for a specific use case. 9137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 9147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Set up the RecyclerView's scrolling motion threshold based on common usages. 9157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Valid arguments are {@link #TOUCH_SLOP_DEFAULT} and {@link #TOUCH_SLOP_PAGING}. 9167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 9177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param slopConstant One of the <code>TOUCH_SLOP_</code> constants representing 9187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the intended usage of this RecyclerView 9197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 9207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setScrollingTouchSlop(int slopConstant) { 9217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewConfiguration vc = ViewConfiguration.get(getContext()); 9227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas switch (slopConstant) { 9237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas default: 9247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.w(TAG, "setScrollingTouchSlop(): bad argument constant " 9257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + slopConstant + "; using default value"); 9267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // fall-through 9277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case TOUCH_SLOP_DEFAULT: 9287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTouchSlop = vc.getScaledTouchSlop(); 9297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas break; 9307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 9317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case TOUCH_SLOP_PAGING: 9327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTouchSlop = vc.getScaledPagingTouchSlop(); 9337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas break; 9347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 9357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 9367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 9377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 9387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Swaps the current adapter with the provided one. It is similar to 9397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #setAdapter(Adapter)} but assumes existing adapter and the new adapter uses the same 9407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link ViewHolder} and does not clear the RecycledViewPool. 9417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 9427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that it still calls onAdapterChanged callbacks. 9437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 9447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param adapter The new adapter to set, or null to set no adapter. 9457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param removeAndRecycleExistingViews If set to true, RecyclerView will recycle all existing 9467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Views. If adapters have stable ids and/or you want to 9477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animate the disappearing views, you may prefer to set 9487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * this to false. 9497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #setAdapter(Adapter) 9507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 9517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void swapAdapter(Adapter adapter, boolean removeAndRecycleExistingViews) { 9527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // bail out if layout is frozen 9537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setLayoutFrozen(false); 9547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setAdapterInternal(adapter, true, removeAndRecycleExistingViews); 9557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setDataSetChangedAfterLayout(); 9567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas requestLayout(); 9577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 9587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 9597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Set a new adapter to provide child views on demand. 9607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 9617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * When adapter is changed, all existing views are recycled back to the pool. If the pool has 9627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * only one adapter, it will be cleared. 9637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 9647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param adapter The new adapter to set, or null to set no adapter. 9657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #swapAdapter(Adapter, boolean) 9667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 9677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setAdapter(Adapter adapter) { 9687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // bail out if layout is frozen 9697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setLayoutFrozen(false); 9707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setAdapterInternal(adapter, false, true); 9717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas requestLayout(); 9727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 9737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 9747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 9757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Removes and recycles all views - both those currently attached, and those in the Recycler. 9767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 9777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void removeAndRecycleViews() { 9787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // end all running animations 9797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mItemAnimator != null) { 9807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemAnimator.endAnimations(); 9817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 9827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Since animations are ended, mLayout.children should be equal to 9837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // recyclerView.children. This may not be true if item animator's end does not work as 9847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // expected. (e.g. not release children instantly). It is safer to use mLayout's child 9857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // count. 9867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout != null) { 9877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.removeAndRecycleAllViews(mRecycler); 9887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.removeAndRecycleScrapInt(mRecycler); 9897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 9907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // we should clear it here before adapters are swapped to ensure correct callbacks. 9917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.clear(); 9927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 9937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 9947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 9957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Replaces the current adapter with the new one and triggers listeners. 9967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param adapter The new adapter 9977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param compatibleWithPrevious If true, the new adapter is using the same View Holders and 9987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * item types with the current adapter (helps us avoid cache 9997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * invalidation). 10007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param removeAndRecycleViews If true, we'll remove and recycle all existing views. If 10017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * compatibleWithPrevious is false, this parameter is ignored. 10027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 10037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void setAdapterInternal(Adapter adapter, boolean compatibleWithPrevious, 10047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean removeAndRecycleViews) { 10057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mAdapter != null) { 10067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAdapter.unregisterAdapterDataObserver(mObserver); 10077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAdapter.onDetachedFromRecyclerView(this); 10087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 10097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!compatibleWithPrevious || removeAndRecycleViews) { 10107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas removeAndRecycleViews(); 10117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 10127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAdapterHelper.reset(); 10137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final Adapter oldAdapter = mAdapter; 10147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAdapter = adapter; 10157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (adapter != null) { 10167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas adapter.registerAdapterDataObserver(mObserver); 10177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas adapter.onAttachedToRecyclerView(this); 10187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 10197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout != null) { 10207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.onAdapterChanged(oldAdapter, mAdapter); 10217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 10227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.onAdapterChanged(oldAdapter, mAdapter, compatibleWithPrevious); 10237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mStructureChanged = true; 10247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas markKnownViewsInvalid(); 10257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 10267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 10277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 10287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Retrieves the previously set adapter or null if no adapter is set. 10297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 10307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The previously set adapter 10317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #setAdapter(Adapter) 10327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 10337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public Adapter getAdapter() { 10347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mAdapter; 10357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 10367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 10377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 10387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Register a listener that will be notified whenever a child view is recycled. 10397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 10407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>This listener will be called when a LayoutManager or the RecyclerView decides 10417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * that a child view is no longer needed. If an application associates expensive 10427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * or heavyweight data with item views, this may be a good place to release 10437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * or free those resources.</p> 10447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 10457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param listener Listener to register, or null to clear 10467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 10477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setRecyclerListener(RecyclerListener listener) { 10487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerListener = listener; 10497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 10507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 10517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 10527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Return the offset of the RecyclerView's text baseline from the its top 10537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * boundary. If the LayoutManager of this RecyclerView does not support baseline alignment, 10547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * this method returns -1.</p> 10557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 10567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return the offset of the baseline within the RecyclerView's bounds or -1 10577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * if baseline alignment is not supported 10587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 10597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 10607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getBaseline() { 10617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout != null) { 10627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mLayout.getBaseline(); 10637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 10647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return super.getBaseline(); 10657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 10667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 10677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 10687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 10697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Register a listener that will be notified whenever a child view is attached to or detached 10707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * from RecyclerView. 10717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 10727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>This listener will be called when a LayoutManager or the RecyclerView decides 10737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * that a child view is no longer needed. If an application associates expensive 10747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * or heavyweight data with item views, this may be a good place to release 10757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * or free those resources.</p> 10767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 10777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param listener Listener to register 10787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 10797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void addOnChildAttachStateChangeListener(OnChildAttachStateChangeListener listener) { 10807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mOnChildAttachStateListeners == null) { 10817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mOnChildAttachStateListeners = new ArrayList<>(); 10827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 10837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mOnChildAttachStateListeners.add(listener); 10847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 10857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 10867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 10877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Removes the provided listener from child attached state listeners list. 10887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 10897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param listener Listener to unregister 10907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 10917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void removeOnChildAttachStateChangeListener(OnChildAttachStateChangeListener listener) { 10927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mOnChildAttachStateListeners == null) { 10937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 10947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 10957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mOnChildAttachStateListeners.remove(listener); 10967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 10977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 10987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 10997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Removes all listeners that were added via 11007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #addOnChildAttachStateChangeListener(OnChildAttachStateChangeListener)}. 11017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 11027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void clearOnChildAttachStateChangeListeners() { 11037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mOnChildAttachStateListeners != null) { 11047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mOnChildAttachStateListeners.clear(); 11057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 11067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 11077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 11087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 11097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Set the {@link LayoutManager} that this RecyclerView will use. 11107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 11117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>In contrast to other adapter-backed views such as {@link android.widget.ListView} 11127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * or {@link android.widget.GridView}, RecyclerView allows client code to provide custom 11137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * layout arrangements for child views. These arrangements are controlled by the 11147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link LayoutManager}. A LayoutManager must be provided for RecyclerView to function.</p> 11157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 11167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Several default strategies are provided for common uses such as lists and grids.</p> 11177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 11187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param layout LayoutManager to use 11197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 11207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setLayoutManager(LayoutManager layout) { 11217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (layout == mLayout) { 11227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 11237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 11247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas stopScroll(); 11257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // TODO We should do this switch a dispatchLayout pass and animate children. There is a good 11267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // chance that LayoutManagers will re-use views. 11277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout != null) { 11287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // end all running animations 11297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mItemAnimator != null) { 11307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemAnimator.endAnimations(); 11317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 11327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.removeAndRecycleAllViews(mRecycler); 11337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.removeAndRecycleScrapInt(mRecycler); 11347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.clear(); 11357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 11367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mIsAttached) { 11377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.dispatchDetachedFromWindow(this, mRecycler); 11387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 11397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.setRecyclerView(null); 11407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout = null; 11417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 11427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.clear(); 11437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 11447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // this is just a defensive measure for faulty item animators. 11457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChildHelper.removeAllViewsUnfiltered(); 11467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout = layout; 11477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (layout != null) { 11487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (layout.mRecyclerView != null) { 11497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalArgumentException("LayoutManager " + layout 11507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " is already attached to a RecyclerView: " + layout.mRecyclerView); 11517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 11527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.setRecyclerView(this); 11537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mIsAttached) { 11547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.dispatchAttachedToWindow(this); 11557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 11567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 11577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.updateViewCacheSize(); 11587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas requestLayout(); 11597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 11607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 11617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 11627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Set a {@link OnFlingListener} for this {@link RecyclerView}. 11637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 11647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If the {@link OnFlingListener} is set then it will receive 11657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * calls to {@link #fling(int,int)} and will be able to intercept them. 11667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 11677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param onFlingListener The {@link OnFlingListener} instance. 11687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 11697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setOnFlingListener(@Nullable OnFlingListener onFlingListener) { 11707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mOnFlingListener = onFlingListener; 11717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 11727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 11737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 11747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Get the current {@link OnFlingListener} from this {@link RecyclerView}. 11757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 11767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The {@link OnFlingListener} instance currently set (can be null). 11777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 11787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Nullable 11797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public OnFlingListener getOnFlingListener() { 11807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mOnFlingListener; 11817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 11827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 11837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 11847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas protected Parcelable onSaveInstanceState() { 11857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas SavedState state = new SavedState(super.onSaveInstanceState()); 11867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mPendingSavedState != null) { 11877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas state.copyFrom(mPendingSavedState); 11887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (mLayout != null) { 11897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas state.mLayoutState = mLayout.onSaveInstanceState(); 11907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 11917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas state.mLayoutState = null; 11927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 11937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 11947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return state; 11957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 11967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 11977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 11987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas protected void onRestoreInstanceState(Parcelable state) { 11997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!(state instanceof SavedState)) { 12007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super.onRestoreInstanceState(state); 12017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 12027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 12037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 12047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPendingSavedState = (SavedState) state; 12057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super.onRestoreInstanceState(mPendingSavedState.getSuperState()); 12067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout != null && mPendingSavedState.mLayoutState != null) { 12077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.onRestoreInstanceState(mPendingSavedState.mLayoutState); 12087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 12097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 12107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 12117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 12127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Override to prevent freezing of any views created by the adapter. 12137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 12147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 12157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) { 12167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchFreezeSelfOnly(container); 12177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 12187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 12197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 12207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Override to prevent thawing of any views created by the adapter. 12217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 12227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 12237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) { 12247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchThawSelfOnly(container); 12257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 12267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 12277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 12287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Adds a view to the animatingViews list. 12297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * mAnimatingViews holds the child views that are currently being kept around 12307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * purely for the purpose of being animated out of view. They are drawn as a regular 12317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * part of the child list of the RecyclerView, but they are invisible to the LayoutManager 12327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * as they are managed separately from the regular child views. 12337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param viewHolder The ViewHolder to be removed 12347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 12357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void addAnimatingView(ViewHolder viewHolder) { 12367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View view = viewHolder.itemView; 12377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean alreadyParented = view.getParent() == this; 12387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.unscrapView(getChildViewHolder(view)); 12397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (viewHolder.isTmpDetached()) { 12407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // re-attach 12417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChildHelper.attachViewToParent(view, -1, view.getLayoutParams(), true); 12427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (!alreadyParented) { 12437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChildHelper.addView(view, true); 12447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 12457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChildHelper.hide(view); 12467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 12477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 12487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 12497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 12507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Removes a view from the animatingViews list. 12517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param view The view to be removed 12527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #addAnimatingView(RecyclerView.ViewHolder) 12537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if an animating view is removed 12547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 12557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean removeAnimatingView(View view) { 12567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas eatRequestLayout(); 12577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean removed = mChildHelper.removeViewIfHidden(view); 12587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (removed) { 12597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder viewHolder = getChildViewHolderInt(view); 12607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.unscrapView(viewHolder); 12617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.recycleViewHolderInternal(viewHolder); 12627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 12637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.d(TAG, "after removing animated view: " + view + ", " + this); 12647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 12657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 12667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // only clear request eaten flag if we removed the view. 12677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resumeRequestLayout(!removed); 12687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return removed; 12697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 12707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 12717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 12727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Return the {@link LayoutManager} currently responsible for 12737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * layout policy for this RecyclerView. 12747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 12757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The currently bound LayoutManager 12767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 12777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public LayoutManager getLayoutManager() { 12787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mLayout; 12797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 12807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 12817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 12827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Retrieve this RecyclerView's {@link RecycledViewPool}. This method will never return null; 12837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * if no pool is set for this view a new one will be created. See 12847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #setRecycledViewPool(RecycledViewPool) setRecycledViewPool} for more information. 12857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 12867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The pool used to store recycled item views for reuse. 12877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #setRecycledViewPool(RecycledViewPool) 12887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 12897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public RecycledViewPool getRecycledViewPool() { 12907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mRecycler.getRecycledViewPool(); 12917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 12927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 12937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 12947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Recycled view pools allow multiple RecyclerViews to share a common pool of scrap views. 12957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This can be useful if you have multiple RecyclerViews with adapters that use the same 12967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * view types, for example if you have several data sets with the same kinds of item views 12977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * displayed by a {@link android.support.v4.view.ViewPager ViewPager}. 12987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 12997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param pool Pool to set. If this parameter is null a new pool will be created and used. 13007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 13017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setRecycledViewPool(RecycledViewPool pool) { 13027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.setRecycledViewPool(pool); 13037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 13047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 13057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 13067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Sets a new {@link ViewCacheExtension} to be used by the Recycler. 13077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 13087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param extension ViewCacheExtension to be used or null if you want to clear the existing one. 13097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 13107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see {@link ViewCacheExtension#getViewForPositionAndType(Recycler, int, int)} 13117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 13127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setViewCacheExtension(ViewCacheExtension extension) { 13137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.setViewCacheExtension(extension); 13147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 13157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 13167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 13177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Set the number of offscreen views to retain before adding them to the potentially shared 13187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #getRecycledViewPool() recycled view pool}. 13197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 13207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>The offscreen view cache stays aware of changes in the attached adapter, allowing 13217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * a LayoutManager to reuse those views unmodified without needing to return to the adapter 13227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to rebind them.</p> 13237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 13247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param size Number of views to cache offscreen before returning them to the general 13257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * recycled view pool 13267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 13277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setItemViewCacheSize(int size) { 13287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.setViewCacheSize(size); 13297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 13307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 13317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 13327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Return the current scrolling state of the RecyclerView. 13337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 13347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return {@link #SCROLL_STATE_IDLE}, {@link #SCROLL_STATE_DRAGGING} or 13357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #SCROLL_STATE_SETTLING} 13367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 13377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getScrollState() { 13387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mScrollState; 13397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 13407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 13417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void setScrollState(int state) { 13427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (state == mScrollState) { 13437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 13447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 13457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 13467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.d(TAG, "setting scroll state to " + state + " from " + mScrollState, 13477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas new Exception()); 13487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 13497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScrollState = state; 13507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (state != SCROLL_STATE_SETTLING) { 13517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas stopScrollersInternal(); 13527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 13537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchOnScrollStateChanged(state); 13547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 13557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 13567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 13577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Add an {@link ItemDecoration} to this RecyclerView. Item decorations can 13587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * affect both measurement and drawing of individual item views. 13597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 13607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Item decorations are ordered. Decorations placed earlier in the list will 13617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * be run/queried/drawn first for their effects on item views. Padding added to views 13627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * will be nested; a padding added by an earlier decoration will mean further 13637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * item decorations in the list will be asked to draw/pad within the previous decoration's 13647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * given area.</p> 13657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 13667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param decor Decoration to add 13677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param index Position in the decoration chain to insert this decoration at. If this value 13687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * is negative the decoration will be added at the end. 13697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 13707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void addItemDecoration(ItemDecoration decor, int index) { 13717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout != null) { 13727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.assertNotInLayoutOrScroll("Cannot add item decoration during a scroll or" 13737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " layout"); 13747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 13757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mItemDecorations.isEmpty()) { 13767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setWillNotDraw(false); 13777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 13787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (index < 0) { 13797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemDecorations.add(decor); 13807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 13817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemDecorations.add(index, decor); 13827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 13837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas markItemDecorInsetsDirty(); 13847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas requestLayout(); 13857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 13867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 13877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 13887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Add an {@link ItemDecoration} to this RecyclerView. Item decorations can 13897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * affect both measurement and drawing of individual item views. 13907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 13917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Item decorations are ordered. Decorations placed earlier in the list will 13927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * be run/queried/drawn first for their effects on item views. Padding added to views 13937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * will be nested; a padding added by an earlier decoration will mean further 13947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * item decorations in the list will be asked to draw/pad within the previous decoration's 13957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * given area.</p> 13967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 13977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param decor Decoration to add 13987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 13997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void addItemDecoration(ItemDecoration decor) { 14007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas addItemDecoration(decor, -1); 14017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 14027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 14037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 14047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Remove an {@link ItemDecoration} from this RecyclerView. 14057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 14067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>The given decoration will no longer impact the measurement and drawing of 14077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * item views.</p> 14087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 14097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param decor Decoration to remove 14107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #addItemDecoration(ItemDecoration) 14117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 14127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void removeItemDecoration(ItemDecoration decor) { 14137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout != null) { 14147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.assertNotInLayoutOrScroll("Cannot remove item decoration during a scroll or" 14157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " layout"); 14167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 14177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemDecorations.remove(decor); 14187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mItemDecorations.isEmpty()) { 14197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setWillNotDraw(getOverScrollMode() == View.OVER_SCROLL_NEVER); 14207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 14217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas markItemDecorInsetsDirty(); 14227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas requestLayout(); 14237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 14247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 14257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 14267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Sets the {@link ChildDrawingOrderCallback} to be used for drawing children. 14277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 14287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * See {@link ViewGroup#getChildDrawingOrder(int, int)} for details. Calling this method will 14297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * always call {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean)}. The parameter will be 14307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * true if childDrawingOrderCallback is not null, false otherwise. 14317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 14327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that child drawing order may be overridden by View's elevation. 14337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 14347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param childDrawingOrderCallback The ChildDrawingOrderCallback to be used by the drawing 14357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * system. 14367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 14377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setChildDrawingOrderCallback(ChildDrawingOrderCallback childDrawingOrderCallback) { 14387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (childDrawingOrderCallback == mChildDrawingOrderCallback) { 14397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 14407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 14417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChildDrawingOrderCallback = childDrawingOrderCallback; 14427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setChildrenDrawingOrderEnabled(mChildDrawingOrderCallback != null); 14437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 14447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 14457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 14467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Set a listener that will be notified of any changes in scroll state or position. 14477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 14487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param listener Listener to set or null to clear 14497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 14507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @deprecated Use {@link #addOnScrollListener(OnScrollListener)} and 14517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #removeOnScrollListener(OnScrollListener)} 14527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 14537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Deprecated 14547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setOnScrollListener(OnScrollListener listener) { 14557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScrollListener = listener; 14567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 14577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 14587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 14597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Add a listener that will be notified of any changes in scroll state or position. 14607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 14617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Components that add a listener should take care to remove it when finished. 14627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Other components that take ownership of a view may call {@link #clearOnScrollListeners()} 14637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to remove all attached listeners.</p> 14647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 14657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param listener listener to set or null to clear 14667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 14677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void addOnScrollListener(OnScrollListener listener) { 14687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mScrollListeners == null) { 14697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScrollListeners = new ArrayList<>(); 14707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 14717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScrollListeners.add(listener); 14727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 14737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 14747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 14757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Remove a listener that was notified of any changes in scroll state or position. 14767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 14777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param listener listener to set or null to clear 14787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 14797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void removeOnScrollListener(OnScrollListener listener) { 14807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mScrollListeners != null) { 14817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScrollListeners.remove(listener); 14827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 14837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 14847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 14857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 14867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Remove all secondary listener that were notified of any changes in scroll state or position. 14877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 14887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void clearOnScrollListeners() { 14897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mScrollListeners != null) { 14907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScrollListeners.clear(); 14917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 14927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 14937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 14947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 14957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Convenience method to scroll to a certain position. 14967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 14977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView does not implement scrolling logic, rather forwards the call to 14987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link com.android.internal.widget.RecyclerView.LayoutManager#scrollToPosition(int)} 14997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param position Scroll to this adapter position 15007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see com.android.internal.widget.RecyclerView.LayoutManager#scrollToPosition(int) 15017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 15027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void scrollToPosition(int position) { 15037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayoutFrozen) { 15047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 15057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 15067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas stopScroll(); 15077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout == null) { 15087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.e(TAG, "Cannot scroll to position a LayoutManager set. " 15097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "Call setLayoutManager with a non-null argument."); 15107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 15117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 15127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.scrollToPosition(position); 15137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas awakenScrollBars(); 15147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 15157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 15167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void jumpToPositionForSmoothScroller(int position) { 15177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout == null) { 15187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 15197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 15207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.scrollToPosition(position); 15217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas awakenScrollBars(); 15227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 15237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 15247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 15257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Starts a smooth scroll to an adapter position. 15267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 15277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * To support smooth scrolling, you must override 15287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link LayoutManager#smoothScrollToPosition(RecyclerView, State, int)} and create a 15297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link SmoothScroller}. 15307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 15317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link LayoutManager} is responsible for creating the actual scroll action. If you want to 15327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * provide a custom smooth scroll logic, override 15337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link LayoutManager#smoothScrollToPosition(RecyclerView, State, int)} in your 15347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManager. 15357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 15367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param position The adapter position to scroll to 15377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see LayoutManager#smoothScrollToPosition(RecyclerView, State, int) 15387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 15397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void smoothScrollToPosition(int position) { 15407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayoutFrozen) { 15417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 15427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 15437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout == null) { 15447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.e(TAG, "Cannot smooth scroll without a LayoutManager set. " 15457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "Call setLayoutManager with a non-null argument."); 15467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 15477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 15487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.smoothScrollToPosition(this, mState, position); 15497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 15507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 15517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 15527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void scrollTo(int x, int y) { 15537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.w(TAG, "RecyclerView does not support scrolling to an absolute position. " 15547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "Use scrollToPosition instead"); 15557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 15567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 15577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 15587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void scrollBy(int x, int y) { 15597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout == null) { 15607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.e(TAG, "Cannot scroll without a LayoutManager set. " 15617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "Call setLayoutManager with a non-null argument."); 15627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 15637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 15647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayoutFrozen) { 15657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 15667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 15677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean canScrollHorizontal = mLayout.canScrollHorizontally(); 15687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean canScrollVertical = mLayout.canScrollVertically(); 15697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (canScrollHorizontal || canScrollVertical) { 15707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas scrollByInternal(canScrollHorizontal ? x : 0, canScrollVertical ? y : 0, null); 15717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 15727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 15737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 15747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 15757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Helper method reflect data changes to the state. 15767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 15777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Adapter changes during a scroll may trigger a crash because scroll assumes no data change 15787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * but data actually changed. 15797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 15807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method consumes all deferred changes to avoid that case. 15817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 15827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void consumePendingUpdateOperations() { 15837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!mFirstLayoutComplete || mDataSetHasChangedAfterLayout) { 15847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Trace.beginSection(TRACE_ON_DATA_SET_CHANGE_LAYOUT_TAG); 15857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchLayout(); 15867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Trace.endSection(); 15877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 15887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 15897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!mAdapterHelper.hasPendingUpdates()) { 15907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 15917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 15927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 15937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // if it is only an item change (no add-remove-notifyDataSetChanged) we can check if any 15947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // of the visible items is affected and if not, just ignore the change. 15957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mAdapterHelper.hasAnyUpdateTypes(AdapterHelper.UpdateOp.UPDATE) && !mAdapterHelper 15967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas .hasAnyUpdateTypes(AdapterHelper.UpdateOp.ADD | AdapterHelper.UpdateOp.REMOVE 15977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas | AdapterHelper.UpdateOp.MOVE)) { 15987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Trace.beginSection(TRACE_HANDLE_ADAPTER_UPDATES_TAG); 15997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas eatRequestLayout(); 16007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onEnterLayoutOrScroll(); 16017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAdapterHelper.preProcess(); 16027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!mLayoutRequestEaten) { 16037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (hasUpdatedView()) { 16047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchLayout(); 16057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 16067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // no need to layout, clean state 16077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAdapterHelper.consumePostponedUpdates(); 16087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 16097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 16107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resumeRequestLayout(true); 16117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onExitLayoutOrScroll(); 16127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Trace.endSection(); 16137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (mAdapterHelper.hasPendingUpdates()) { 16147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Trace.beginSection(TRACE_ON_DATA_SET_CHANGE_LAYOUT_TAG); 16157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchLayout(); 16167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Trace.endSection(); 16177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 16187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 16197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 16207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 16217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return True if an existing view holder needs to be updated 16227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 16237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private boolean hasUpdatedView() { 16247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childCount = mChildHelper.getChildCount(); 16257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < childCount; i++) { 16267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = getChildViewHolderInt(mChildHelper.getChildAt(i)); 16277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder == null || holder.shouldIgnore()) { 16287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas continue; 16297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 16307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.isUpdated()) { 16317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return true; 16327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 16337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 16347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 16357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 16367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 16377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 16387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Does not perform bounds checking. Used by internal methods that have already validated input. 16397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 16407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * It also reports any unused scroll request to the related EdgeEffect. 16417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 16427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param x The amount of horizontal scroll request 16437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param y The amount of vertical scroll request 16447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param ev The originating MotionEvent, or null if not from a touch event. 16457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 16467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Whether any scroll was consumed in either direction. 16477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 16487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean scrollByInternal(int x, int y, MotionEvent ev) { 16497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int unconsumedX = 0, unconsumedY = 0; 16507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int consumedX = 0, consumedY = 0; 16517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 16527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas consumePendingUpdateOperations(); 16537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mAdapter != null) { 16547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas eatRequestLayout(); 16557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onEnterLayoutOrScroll(); 16567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Trace.beginSection(TRACE_SCROLL_TAG); 16577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (x != 0) { 16587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas consumedX = mLayout.scrollHorizontallyBy(x, mRecycler, mState); 16597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas unconsumedX = x - consumedX; 16607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 16617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (y != 0) { 16627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas consumedY = mLayout.scrollVerticallyBy(y, mRecycler, mState); 16637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas unconsumedY = y - consumedY; 16647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 16657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Trace.endSection(); 16667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas repositionShadowingViews(); 16677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onExitLayoutOrScroll(); 16687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resumeRequestLayout(false); 16697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 16707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!mItemDecorations.isEmpty()) { 16717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas invalidate(); 16727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 16737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 16747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (dispatchNestedScroll(consumedX, consumedY, unconsumedX, unconsumedY, mScrollOffset)) { 16757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Update the last touch co-ords, taking any scroll offset into account 16767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLastTouchX -= mScrollOffset[0]; 16777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLastTouchY -= mScrollOffset[1]; 16787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (ev != null) { 16797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ev.offsetLocation(mScrollOffset[0], mScrollOffset[1]); 16807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 16817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mNestedOffsets[0] += mScrollOffset[0]; 16827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mNestedOffsets[1] += mScrollOffset[1]; 16837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (getOverScrollMode() != View.OVER_SCROLL_NEVER) { 16847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (ev != null) { 16857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas pullGlows(ev.getX(), unconsumedX, ev.getY(), unconsumedY); 16867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 16877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas considerReleasingGlowsOnScroll(x, y); 16887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 16897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (consumedX != 0 || consumedY != 0) { 16907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchOnScrolled(consumedX, consumedY); 16917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 16927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!awakenScrollBars()) { 16937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas invalidate(); 16947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 16957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return consumedX != 0 || consumedY != 0; 16967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 16977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 16987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 16997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Compute the horizontal offset of the horizontal scrollbar's thumb within the horizontal 17007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * range. This value is used to compute the length of the thumb within the scrollbar's track. 17017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * </p> 17027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 17037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>The range is expressed in arbitrary units that must be the same as the units used by 17047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #computeHorizontalScrollRange()} and {@link #computeHorizontalScrollExtent()}.</p> 17057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 17067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Default implementation returns 0.</p> 17077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 17087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>If you want to support scroll bars, override 17097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecyclerView.LayoutManager#computeHorizontalScrollOffset(RecyclerView.State)} in your 17107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManager. </p> 17117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 17127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The horizontal offset of the scrollbar's thumb 17137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see com.android.internal.widget.RecyclerView.LayoutManager#computeHorizontalScrollOffset 17147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * (RecyclerView.State) 17157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 17167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 17177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int computeHorizontalScrollOffset() { 17187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout == null) { 17197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return 0; 17207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 17217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mLayout.canScrollHorizontally() ? mLayout.computeHorizontalScrollOffset(mState) : 0; 17227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 17237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 17247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 17257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Compute the horizontal extent of the horizontal scrollbar's thumb within the 17267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * horizontal range. This value is used to compute the length of the thumb within the 17277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * scrollbar's track.</p> 17287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 17297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>The range is expressed in arbitrary units that must be the same as the units used by 17307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #computeHorizontalScrollRange()} and {@link #computeHorizontalScrollOffset()}.</p> 17317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 17327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Default implementation returns 0.</p> 17337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 17347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>If you want to support scroll bars, override 17357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecyclerView.LayoutManager#computeHorizontalScrollExtent(RecyclerView.State)} in your 17367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManager.</p> 17377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 17387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The horizontal extent of the scrollbar's thumb 17397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see RecyclerView.LayoutManager#computeHorizontalScrollExtent(RecyclerView.State) 17407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 17417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 17427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int computeHorizontalScrollExtent() { 17437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout == null) { 17447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return 0; 17457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 17467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mLayout.canScrollHorizontally() ? mLayout.computeHorizontalScrollExtent(mState) : 0; 17477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 17487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 17497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 17507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Compute the horizontal range that the horizontal scrollbar represents.</p> 17517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 17527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>The range is expressed in arbitrary units that must be the same as the units used by 17537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #computeHorizontalScrollExtent()} and {@link #computeHorizontalScrollOffset()}.</p> 17547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 17557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Default implementation returns 0.</p> 17567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 17577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>If you want to support scroll bars, override 17587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecyclerView.LayoutManager#computeHorizontalScrollRange(RecyclerView.State)} in your 17597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManager.</p> 17607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 17617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The total horizontal range represented by the vertical scrollbar 17627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see RecyclerView.LayoutManager#computeHorizontalScrollRange(RecyclerView.State) 17637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 17647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 17657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int computeHorizontalScrollRange() { 17667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout == null) { 17677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return 0; 17687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 17697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mLayout.canScrollHorizontally() ? mLayout.computeHorizontalScrollRange(mState) : 0; 17707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 17717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 17727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 17737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Compute the vertical offset of the vertical scrollbar's thumb within the vertical range. 17747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This value is used to compute the length of the thumb within the scrollbar's track. </p> 17757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 17767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>The range is expressed in arbitrary units that must be the same as the units used by 17777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #computeVerticalScrollRange()} and {@link #computeVerticalScrollExtent()}.</p> 17787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 17797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Default implementation returns 0.</p> 17807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 17817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>If you want to support scroll bars, override 17827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecyclerView.LayoutManager#computeVerticalScrollOffset(RecyclerView.State)} in your 17837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManager.</p> 17847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 17857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The vertical offset of the scrollbar's thumb 17867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see com.android.internal.widget.RecyclerView.LayoutManager#computeVerticalScrollOffset 17877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * (RecyclerView.State) 17887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 17897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 17907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int computeVerticalScrollOffset() { 17917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout == null) { 17927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return 0; 17937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 17947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mLayout.canScrollVertically() ? mLayout.computeVerticalScrollOffset(mState) : 0; 17957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 17967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 17977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 17987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Compute the vertical extent of the vertical scrollbar's thumb within the vertical range. 17997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This value is used to compute the length of the thumb within the scrollbar's track.</p> 18007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 18017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>The range is expressed in arbitrary units that must be the same as the units used by 18027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #computeVerticalScrollRange()} and {@link #computeVerticalScrollOffset()}.</p> 18037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 18047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Default implementation returns 0.</p> 18057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 18067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>If you want to support scroll bars, override 18077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecyclerView.LayoutManager#computeVerticalScrollExtent(RecyclerView.State)} in your 18087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManager.</p> 18097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 18107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The vertical extent of the scrollbar's thumb 18117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see RecyclerView.LayoutManager#computeVerticalScrollExtent(RecyclerView.State) 18127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 18137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 18147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int computeVerticalScrollExtent() { 18157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout == null) { 18167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return 0; 18177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 18187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mLayout.canScrollVertically() ? mLayout.computeVerticalScrollExtent(mState) : 0; 18197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 18207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 18217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 18227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Compute the vertical range that the vertical scrollbar represents.</p> 18237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 18247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>The range is expressed in arbitrary units that must be the same as the units used by 18257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #computeVerticalScrollExtent()} and {@link #computeVerticalScrollOffset()}.</p> 18267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 18277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Default implementation returns 0.</p> 18287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 18297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>If you want to support scroll bars, override 18307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecyclerView.LayoutManager#computeVerticalScrollRange(RecyclerView.State)} in your 18317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManager.</p> 18327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 18337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The total vertical range represented by the vertical scrollbar 18347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see RecyclerView.LayoutManager#computeVerticalScrollRange(RecyclerView.State) 18357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 18367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 18377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int computeVerticalScrollRange() { 18387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout == null) { 18397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return 0; 18407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 18417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mLayout.canScrollVertically() ? mLayout.computeVerticalScrollRange(mState) : 0; 18427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 18437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 18447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 18457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void eatRequestLayout() { 18467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mEatRequestLayout++; 18477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mEatRequestLayout == 1 && !mLayoutFrozen) { 18487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayoutRequestEaten = false; 18497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 18507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 18517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 18527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void resumeRequestLayout(boolean performLayoutChildren) { 18537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mEatRequestLayout < 1) { 18547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas //noinspection PointlessBooleanExpression 18557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 18567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException("invalid eat request layout count"); 18577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 18587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mEatRequestLayout = 1; 18597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 18607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!performLayoutChildren) { 18617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Reset the layout request eaten counter. 18627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // This is necessary since eatRequest calls can be nested in which case the other 18637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // call will override the inner one. 18647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // for instance: 18657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // eat layout for process adapter updates 18667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // eat layout for dispatchLayout 18677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // a bunch of req layout calls arrive 18687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 18697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayoutRequestEaten = false; 18707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 18717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mEatRequestLayout == 1) { 18727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // when layout is frozen we should delay dispatchLayout() 18737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (performLayoutChildren && mLayoutRequestEaten && !mLayoutFrozen 18747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && mLayout != null && mAdapter != null) { 18757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchLayout(); 18767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 18777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!mLayoutFrozen) { 18787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayoutRequestEaten = false; 18797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 18807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 18817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mEatRequestLayout--; 18827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 18837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 18847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 18857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Enable or disable layout and scroll. After <code>setLayoutFrozen(true)</code> is called, 18867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Layout requests will be postponed until <code>setLayoutFrozen(false)</code> is called; 18877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * child views are not updated when RecyclerView is frozen, {@link #smoothScrollBy(int, int)}, 18887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #scrollBy(int, int)}, {@link #scrollToPosition(int)} and 18897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #smoothScrollToPosition(int)} are dropped; TouchEvents and GenericMotionEvents are 18907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * dropped; {@link LayoutManager#onFocusSearchFailed(View, int, Recycler, State)} will not be 18917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * called. 18927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 18937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 18947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <code>setLayoutFrozen(true)</code> does not prevent app from directly calling {@link 18957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManager#scrollToPosition(int)}, {@link LayoutManager#smoothScrollToPosition( 18967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView, State, int)}. 18977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 18987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #setAdapter(Adapter)} and {@link #swapAdapter(Adapter, boolean)} will automatically 18997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * stop frozen. 19007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 19017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note: Running ItemAnimator is not stopped automatically, it's caller's 19027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * responsibility to call ItemAnimator.end(). 19037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 19047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param frozen true to freeze layout and scroll, false to re-enable. 19057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 19067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setLayoutFrozen(boolean frozen) { 19077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (frozen != mLayoutFrozen) { 19087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas assertNotInLayoutOrScroll("Do not setLayoutFrozen in layout or scroll"); 19097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!frozen) { 19107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayoutFrozen = false; 19117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayoutRequestEaten && mLayout != null && mAdapter != null) { 19127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas requestLayout(); 19137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 19147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayoutRequestEaten = false; 19157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 19167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final long now = SystemClock.uptimeMillis(); 19177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas MotionEvent cancelEvent = MotionEvent.obtain(now, now, 19187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0); 19197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onTouchEvent(cancelEvent); 19207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayoutFrozen = true; 19217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mIgnoreMotionEventTillDown = true; 19227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas stopScroll(); 19237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 19247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 19257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 19267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 19277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 19287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns true if layout and scroll are frozen. 19297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 19307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if layout and scroll are frozen 19317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #setLayoutFrozen(boolean) 19327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 19337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean isLayoutFrozen() { 19347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mLayoutFrozen; 19357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 19367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 19377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 19387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Animate a scroll by the given amount of pixels along either axis. 19397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 19407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dx Pixels to scroll horizontally 19417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dy Pixels to scroll vertically 19427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 19437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void smoothScrollBy(int dx, int dy) { 19447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas smoothScrollBy(dx, dy, null); 19457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 19467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 19477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 19487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Animate a scroll by the given amount of pixels along either axis. 19497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 19507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dx Pixels to scroll horizontally 19517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dy Pixels to scroll vertically 19527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param interpolator {@link Interpolator} to be used for scrolling. If it is 19537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@code null}, RecyclerView is going to use the default interpolator. 19547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 19557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void smoothScrollBy(int dx, int dy, Interpolator interpolator) { 19567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout == null) { 19577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.e(TAG, "Cannot smooth scroll without a LayoutManager set. " 19587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "Call setLayoutManager with a non-null argument."); 19597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 19607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 19617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayoutFrozen) { 19627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 19637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 19647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!mLayout.canScrollHorizontally()) { 19657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dx = 0; 19667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 19677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!mLayout.canScrollVertically()) { 19687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dy = 0; 19697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 19707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (dx != 0 || dy != 0) { 19717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mViewFlinger.smoothScrollBy(dx, dy, interpolator); 19727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 19737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 19747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 19757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 19767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Begin a standard fling with an initial velocity along each axis in pixels per second. 19777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If the velocity given is below the system-defined minimum this method will return false 19787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * and no fling will occur. 19797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 19807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param velocityX Initial horizontal velocity in pixels per second 19817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param velocityY Initial vertical velocity in pixels per second 19827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if the fling was started, false if the velocity was too low to fling or 19837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManager does not support scrolling in the axis fling is issued. 19847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 19857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see LayoutManager#canScrollVertically() 19867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see LayoutManager#canScrollHorizontally() 19877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 19887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean fling(int velocityX, int velocityY) { 19897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout == null) { 19907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.e(TAG, "Cannot fling without a LayoutManager set. " 19917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "Call setLayoutManager with a non-null argument."); 19927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 19937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 19947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayoutFrozen) { 19957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 19967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 19977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 19987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean canScrollHorizontal = mLayout.canScrollHorizontally(); 19997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean canScrollVertical = mLayout.canScrollVertically(); 20007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 20017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!canScrollHorizontal || Math.abs(velocityX) < mMinFlingVelocity) { 20027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas velocityX = 0; 20037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 20047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!canScrollVertical || Math.abs(velocityY) < mMinFlingVelocity) { 20057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas velocityY = 0; 20067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 20077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (velocityX == 0 && velocityY == 0) { 20087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // If we don't have any velocity, return false 20097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 20107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 20117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 20127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!dispatchNestedPreFling(velocityX, velocityY)) { 20137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean canScroll = canScrollHorizontal || canScrollVertical; 20147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchNestedFling(velocityX, velocityY, canScroll); 20157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 20167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mOnFlingListener != null && mOnFlingListener.onFling(velocityX, velocityY)) { 20177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return true; 20187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 20197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 20207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (canScroll) { 20217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas velocityX = Math.max(-mMaxFlingVelocity, Math.min(velocityX, mMaxFlingVelocity)); 20227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas velocityY = Math.max(-mMaxFlingVelocity, Math.min(velocityY, mMaxFlingVelocity)); 20237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mViewFlinger.fling(velocityX, velocityY); 20247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return true; 20257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 20267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 20277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 20287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 20297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 20307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 20317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Stop any current scroll in progress, such as one started by 20327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #smoothScrollBy(int, int)}, {@link #fling(int, int)} or a touch-initiated fling. 20337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 20347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void stopScroll() { 20357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setScrollState(SCROLL_STATE_IDLE); 20367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas stopScrollersInternal(); 20377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 20387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 20397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 20407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Similar to {@link #stopScroll()} but does not set the state. 20417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 20427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void stopScrollersInternal() { 20437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mViewFlinger.stop(); 20447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout != null) { 20457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.stopSmoothScroller(); 20467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 20477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 20487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 20497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 20507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the minimum velocity to start a fling. 20517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 20527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The minimum velocity to start a fling 20537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 20547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getMinFlingVelocity() { 20557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mMinFlingVelocity; 20567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 20577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 20587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 20597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 20607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the maximum fling velocity used by this RecyclerView. 20617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 20627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The maximum fling velocity used by this RecyclerView. 20637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 20647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getMaxFlingVelocity() { 20657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mMaxFlingVelocity; 20667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 20677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 20687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 20697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Apply a pull to relevant overscroll glow effects 20707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 20717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void pullGlows(float x, float overscrollX, float y, float overscrollY) { 20727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean invalidate = false; 20737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (overscrollX < 0) { 20747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ensureLeftGlow(); 20757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLeftGlow.onPull(-overscrollX / getWidth(), 1f - y / getHeight()); 20767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas invalidate = true; 20777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (overscrollX > 0) { 20787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ensureRightGlow(); 20797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRightGlow.onPull(overscrollX / getWidth(), y / getHeight()); 20807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas invalidate = true; 20817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 20827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 20837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (overscrollY < 0) { 20847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ensureTopGlow(); 20857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTopGlow.onPull(-overscrollY / getHeight(), x / getWidth()); 20867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas invalidate = true; 20877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (overscrollY > 0) { 20887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ensureBottomGlow(); 20897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mBottomGlow.onPull(overscrollY / getHeight(), 1f - x / getWidth()); 20907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas invalidate = true; 20917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 20927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 20937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (invalidate || overscrollX != 0 || overscrollY != 0) { 20947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas postInvalidateOnAnimation(); 20957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 20967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 20977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 20987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void releaseGlows() { 20997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean needsInvalidate = false; 21007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLeftGlow != null) { 21017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLeftGlow.onRelease(); 21027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas needsInvalidate = true; 21037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mTopGlow != null) { 21057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTopGlow.onRelease(); 21067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas needsInvalidate = true; 21077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRightGlow != null) { 21097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRightGlow.onRelease(); 21107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas needsInvalidate = true; 21117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mBottomGlow != null) { 21137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mBottomGlow.onRelease(); 21147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas needsInvalidate = true; 21157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (needsInvalidate) { 21177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas postInvalidateOnAnimation(); 21187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 21217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void considerReleasingGlowsOnScroll(int dx, int dy) { 21227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean needsInvalidate = false; 21237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLeftGlow != null && !mLeftGlow.isFinished() && dx > 0) { 21247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLeftGlow.onRelease(); 21257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas needsInvalidate = true; 21267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRightGlow != null && !mRightGlow.isFinished() && dx < 0) { 21287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRightGlow.onRelease(); 21297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas needsInvalidate = true; 21307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mTopGlow != null && !mTopGlow.isFinished() && dy > 0) { 21327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTopGlow.onRelease(); 21337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas needsInvalidate = true; 21347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mBottomGlow != null && !mBottomGlow.isFinished() && dy < 0) { 21367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mBottomGlow.onRelease(); 21377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas needsInvalidate = true; 21387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (needsInvalidate) { 21407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas postInvalidateOnAnimation(); 21417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 21447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void absorbGlows(int velocityX, int velocityY) { 21457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (velocityX < 0) { 21467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ensureLeftGlow(); 21477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLeftGlow.onAbsorb(-velocityX); 21487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (velocityX > 0) { 21497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ensureRightGlow(); 21507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRightGlow.onAbsorb(velocityX); 21517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 21537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (velocityY < 0) { 21547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ensureTopGlow(); 21557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTopGlow.onAbsorb(-velocityY); 21567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (velocityY > 0) { 21577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ensureBottomGlow(); 21587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mBottomGlow.onAbsorb(velocityY); 21597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 21617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (velocityX != 0 || velocityY != 0) { 21627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas postInvalidateOnAnimation(); 21637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 21667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void ensureLeftGlow() { 21677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLeftGlow != null) { 21687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 21697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLeftGlow = new EdgeEffect(getContext()); 21717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mClipToPadding) { 21727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLeftGlow.setSize(getMeasuredHeight() - getPaddingTop() - getPaddingBottom(), 21737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas getMeasuredWidth() - getPaddingLeft() - getPaddingRight()); 21747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 21757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLeftGlow.setSize(getMeasuredHeight(), getMeasuredWidth()); 21767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 21797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void ensureRightGlow() { 21807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRightGlow != null) { 21817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 21827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRightGlow = new EdgeEffect(getContext()); 21847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mClipToPadding) { 21857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRightGlow.setSize(getMeasuredHeight() - getPaddingTop() - getPaddingBottom(), 21867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas getMeasuredWidth() - getPaddingLeft() - getPaddingRight()); 21877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 21887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRightGlow.setSize(getMeasuredHeight(), getMeasuredWidth()); 21897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 21927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void ensureTopGlow() { 21937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mTopGlow != null) { 21947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 21957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 21967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTopGlow = new EdgeEffect(getContext()); 21977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mClipToPadding) { 21987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTopGlow.setSize(getMeasuredWidth() - getPaddingLeft() - getPaddingRight(), 21997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas getMeasuredHeight() - getPaddingTop() - getPaddingBottom()); 22007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 22017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTopGlow.setSize(getMeasuredWidth(), getMeasuredHeight()); 22027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 22037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 22047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 22057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 22067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void ensureBottomGlow() { 22077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mBottomGlow != null) { 22087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 22097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 22107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mBottomGlow = new EdgeEffect(getContext()); 22117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mClipToPadding) { 22127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mBottomGlow.setSize(getMeasuredWidth() - getPaddingLeft() - getPaddingRight(), 22137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas getMeasuredHeight() - getPaddingTop() - getPaddingBottom()); 22147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 22157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mBottomGlow.setSize(getMeasuredWidth(), getMeasuredHeight()); 22167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 22177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 22187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 22197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void invalidateGlows() { 22207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLeftGlow = mRightGlow = mTopGlow = mBottomGlow = null; 22217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 22227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 22237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 22247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Since RecyclerView is a collection ViewGroup that includes virtual children (items that are 22257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * in the Adapter but not visible in the UI), it employs a more involved focus search strategy 22267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * that differs from other ViewGroups. 22277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 22287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * It first does a focus search within the RecyclerView. If this search finds a View that is in 22297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the focus direction with respect to the currently focused View, RecyclerView returns that 22307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * child as the next focus target. When it cannot find such child, it calls 22317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link LayoutManager#onFocusSearchFailed(View, int, Recycler, State)} to layout more Views 22327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * in the focus search direction. If LayoutManager adds a View that matches the 22337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * focus search criteria, it will be returned as the focus search result. Otherwise, 22347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView will call parent to handle the focus search like a regular ViewGroup. 22357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 22367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * When the direction is {@link View#FOCUS_FORWARD} or {@link View#FOCUS_BACKWARD}, a View that 22377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * is not in the focus direction is still valid focus target which may not be the desired 22387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * behavior if the Adapter has more children in the focus direction. To handle this case, 22397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView converts the focus direction to an absolute direction and makes a preliminary 22407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * focus search in that direction. If there are no Views to gain focus, it will call 22417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link LayoutManager#onFocusSearchFailed(View, int, Recycler, State)} before running a 22427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * focus search with the original (relative) direction. This allows RecyclerView to provide 22437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * better candidates to the focus search while still allowing the view system to take focus from 22447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the RecyclerView and give it to a more suitable child if such child exists. 22457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 22467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param focused The view that currently has focus 22477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param direction One of {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN}, 22487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link View#FOCUS_LEFT}, {@link View#FOCUS_RIGHT}, {@link View#FOCUS_FORWARD}, 22497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link View#FOCUS_BACKWARD} or 0 for not applicable. 22507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 22517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return A new View that can be the next focus after the focused View 22527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 22537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 22547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public View focusSearch(View focused, int direction) { 22557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas View result = mLayout.onInterceptFocusSearch(focused, direction); 22567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (result != null) { 22577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return result; 22587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 22597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean canRunFocusFailure = mAdapter != null && mLayout != null 22607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && !isComputingLayout() && !mLayoutFrozen; 22617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 22627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final FocusFinder ff = FocusFinder.getInstance(); 22637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (canRunFocusFailure 22647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && (direction == View.FOCUS_FORWARD || direction == View.FOCUS_BACKWARD)) { 22657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // convert direction to absolute direction and see if we have a view there and if not 22667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // tell LayoutManager to add if it can. 22677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean needsFocusFailureLayout = false; 22687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout.canScrollVertically()) { 22697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int absDir = 22707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas direction == View.FOCUS_FORWARD ? View.FOCUS_DOWN : View.FOCUS_UP; 22717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View found = ff.findNextFocus(this, focused, absDir); 22727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas needsFocusFailureLayout = found == null; 22737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (FORCE_ABS_FOCUS_SEARCH_DIRECTION) { 22747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Workaround for broken FOCUS_BACKWARD in API 15 and older devices. 22757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas direction = absDir; 22767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 22777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 22787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!needsFocusFailureLayout && mLayout.canScrollHorizontally()) { 22797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean rtl = mLayout.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; 22807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int absDir = (direction == View.FOCUS_FORWARD) ^ rtl 22817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ? View.FOCUS_RIGHT : View.FOCUS_LEFT; 22827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View found = ff.findNextFocus(this, focused, absDir); 22837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas needsFocusFailureLayout = found == null; 22847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (FORCE_ABS_FOCUS_SEARCH_DIRECTION) { 22857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Workaround for broken FOCUS_BACKWARD in API 15 and older devices. 22867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas direction = absDir; 22877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 22887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 22897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (needsFocusFailureLayout) { 22907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas consumePendingUpdateOperations(); 22917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View focusedItemView = findContainingItemView(focused); 22927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (focusedItemView == null) { 22937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // panic, focused view is not a child anymore, cannot call super. 22947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 22957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 22967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas eatRequestLayout(); 22977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.onFocusSearchFailed(focused, direction, mRecycler, mState); 22987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resumeRequestLayout(false); 22997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 23007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas result = ff.findNextFocus(this, focused, direction); 23017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 23027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas result = ff.findNextFocus(this, focused, direction); 23037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (result == null && canRunFocusFailure) { 23047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas consumePendingUpdateOperations(); 23057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View focusedItemView = findContainingItemView(focused); 23067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (focusedItemView == null) { 23077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // panic, focused view is not a child anymore, cannot call super. 23087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 23097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 23107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas eatRequestLayout(); 23117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas result = mLayout.onFocusSearchFailed(focused, direction, mRecycler, mState); 23127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resumeRequestLayout(false); 23137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 23147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 23157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return isPreferredNextFocus(focused, result, direction) 23167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ? result : super.focusSearch(focused, direction); 23177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 23187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 23197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 23207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Checks if the new focus candidate is a good enough candidate such that RecyclerView will 23217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * assign it as the next focus View instead of letting view hierarchy decide. 23227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * A good candidate means a View that is aligned in the focus direction wrt the focused View 23237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * and is not the RecyclerView itself. 23247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * When this method returns false, RecyclerView will let the parent make the decision so the 23257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * same View may still get the focus as a result of that search. 23267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 23277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private boolean isPreferredNextFocus(View focused, View next, int direction) { 23287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (next == null || next == this) { 23297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 23307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 23317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (focused == null) { 23327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return true; 23337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 23347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 23357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (direction == View.FOCUS_FORWARD || direction == View.FOCUS_BACKWARD) { 23367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean rtl = mLayout.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; 23377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int absHorizontal = (direction == View.FOCUS_FORWARD) ^ rtl 23387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ? View.FOCUS_RIGHT : View.FOCUS_LEFT; 23397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (isPreferredNextFocusAbsolute(focused, next, absHorizontal)) { 23407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return true; 23417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 23427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (direction == View.FOCUS_FORWARD) { 23437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return isPreferredNextFocusAbsolute(focused, next, View.FOCUS_DOWN); 23447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 23457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return isPreferredNextFocusAbsolute(focused, next, View.FOCUS_UP); 23467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 23477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 23487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return isPreferredNextFocusAbsolute(focused, next, direction); 23497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 23507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 23517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 23527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 23537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 23547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Logic taken from FocusSearch#isCandidate 23557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 23567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private boolean isPreferredNextFocusAbsolute(View focused, View next, int direction) { 23577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTempRect.set(0, 0, focused.getWidth(), focused.getHeight()); 23587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTempRect2.set(0, 0, next.getWidth(), next.getHeight()); 23597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas offsetDescendantRectToMyCoords(focused, mTempRect); 23607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas offsetDescendantRectToMyCoords(next, mTempRect2); 23617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas switch (direction) { 23627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case View.FOCUS_LEFT: 23637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return (mTempRect.right > mTempRect2.right 23647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || mTempRect.left >= mTempRect2.right) 23657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && mTempRect.left > mTempRect2.left; 23667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case View.FOCUS_RIGHT: 23677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return (mTempRect.left < mTempRect2.left 23687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || mTempRect.right <= mTempRect2.left) 23697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && mTempRect.right < mTempRect2.right; 23707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case View.FOCUS_UP: 23717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return (mTempRect.bottom > mTempRect2.bottom 23727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || mTempRect.top >= mTempRect2.bottom) 23737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && mTempRect.top > mTempRect2.top; 23747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case View.FOCUS_DOWN: 23757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return (mTempRect.top < mTempRect2.top 23767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || mTempRect.bottom <= mTempRect2.top) 23777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && mTempRect.bottom < mTempRect2.bottom; 23787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 23797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalArgumentException("direction must be absolute. received:" + direction); 23807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 23817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 23827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 23837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void requestChildFocus(View child, View focused) { 23847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!mLayout.onRequestChildFocus(this, mState, child, focused) && focused != null) { 23857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTempRect.set(0, 0, focused.getWidth(), focused.getHeight()); 23867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 23877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // get item decor offsets w/o refreshing. If they are invalid, there will be another 23887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // layout pass to fix them, then it is LayoutManager's responsibility to keep focused 23897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // View in viewport. 23907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewGroup.LayoutParams focusedLayoutParams = focused.getLayoutParams(); 23917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (focusedLayoutParams instanceof LayoutParams) { 23927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // if focused child has item decors, use them. Otherwise, ignore. 23937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final LayoutParams lp = (LayoutParams) focusedLayoutParams; 23947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!lp.mInsetsDirty) { 23957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final Rect insets = lp.mDecorInsets; 23967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTempRect.left -= insets.left; 23977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTempRect.right += insets.right; 23987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTempRect.top -= insets.top; 23997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTempRect.bottom += insets.bottom; 24007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 24017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 24027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 24037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas offsetDescendantRectToMyCoords(focused, mTempRect); 24047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas offsetRectIntoDescendantCoords(child, mTempRect); 24057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas requestChildRectangleOnScreen(child, mTempRect, !mFirstLayoutComplete); 24067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 24077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super.requestChildFocus(child, focused); 24087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 24097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 24107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 24117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean requestChildRectangleOnScreen(View child, Rect rect, boolean immediate) { 24127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mLayout.requestChildRectangleOnScreen(this, child, rect, immediate); 24137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 24147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 24157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 24167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void addFocusables(ArrayList<View> views, int direction, int focusableMode) { 24177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout == null || !mLayout.onAddFocusables(this, views, direction, focusableMode)) { 24187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super.addFocusables(views, direction, focusableMode); 24197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 24207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 24217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 24227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 24237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) { 24247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (isComputingLayout()) { 24257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // if we are in the middle of a layout calculation, don't let any child take focus. 24267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // RV will handle it after layout calculation is finished. 24277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 24287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 24297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return super.onRequestFocusInDescendants(direction, previouslyFocusedRect); 24307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 24317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 24327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 24337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas protected void onAttachedToWindow() { 24347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super.onAttachedToWindow(); 24357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayoutOrScrollCounter = 0; 24367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mIsAttached = true; 24377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mFirstLayoutComplete = mFirstLayoutComplete && !isLayoutRequested(); 24387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout != null) { 24397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.dispatchAttachedToWindow(this); 24407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 24417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPostedAnimatorRunner = false; 24427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 24437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (ALLOW_THREAD_GAP_WORK) { 24447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Register with gap worker 24457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mGapWorker = GapWorker.sGapWorker.get(); 24467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mGapWorker == null) { 24477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mGapWorker = new GapWorker(); 24487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 24497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // break 60 fps assumption if data from display appears valid 24507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // NOTE: we only do this query once, statically, because it's very expensive (> 1ms) 24517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Display display = getDisplay(); 24527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas float refreshRate = 60.0f; 24537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!isInEditMode() && display != null) { 24547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas float displayRefreshRate = display.getRefreshRate(); 24557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (displayRefreshRate >= 30.0f) { 24567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas refreshRate = displayRefreshRate; 24577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 24587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 24597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mGapWorker.mFrameIntervalNs = (long) (1000000000 / refreshRate); 24607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas GapWorker.sGapWorker.set(mGapWorker); 24617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 24627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mGapWorker.add(this); 24637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 24647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 24657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 24667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 24677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas protected void onDetachedFromWindow() { 24687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super.onDetachedFromWindow(); 24697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mItemAnimator != null) { 24707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemAnimator.endAnimations(); 24717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 24727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas stopScroll(); 24737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mIsAttached = false; 24747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout != null) { 24757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.dispatchDetachedFromWindow(this, mRecycler); 24767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 24777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPendingAccessibilityImportanceChange.clear(); 24787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas removeCallbacks(mItemAnimatorRunner); 24797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mViewInfoStore.onDetach(); 24807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 24817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (ALLOW_THREAD_GAP_WORK) { 24827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Unregister with gap worker 24837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mGapWorker.remove(this); 24847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mGapWorker = null; 24857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 24867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 24877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 24887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 24897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns true if RecyclerView is attached to window. 24907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 24917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // @override 24927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean isAttachedToWindow() { 24937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mIsAttached; 24947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 24957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 24967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 24977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Checks if RecyclerView is in the middle of a layout or scroll and throws an 24987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link IllegalStateException} if it <b>is not</b>. 24997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 25007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param message The message for the exception. Can be null. 25017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #assertNotInLayoutOrScroll(String) 25027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 25037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void assertInLayoutOrScroll(String message) { 25047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!isComputingLayout()) { 25057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (message == null) { 25067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException("Cannot call this method unless RecyclerView is " 25077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "computing a layout or scrolling"); 25087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 25097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException(message); 25107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 25117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 25127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 25137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 25147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 25157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Checks if RecyclerView is in the middle of a layout or scroll and throws an 25167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link IllegalStateException} if it <b>is</b>. 25177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 25187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param message The message for the exception. Can be null. 25197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #assertInLayoutOrScroll(String) 25207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 25217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void assertNotInLayoutOrScroll(String message) { 25227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (isComputingLayout()) { 25237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (message == null) { 25247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException("Cannot call this method while RecyclerView is " 25257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "computing a layout or scrolling"); 25267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 25277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException(message); 25287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 25297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mDispatchScrollCounter > 0) { 25307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.w(TAG, "Cannot call this method in a scroll callback. Scroll callbacks might be run" 25317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " during a measure & layout pass where you cannot change the RecyclerView" 25327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " data. Any method call that might change the structure of the RecyclerView" 25337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " or the adapter contents should be postponed to the next frame.", 25347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas new IllegalStateException("")); 25357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 25367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 25377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 25387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 25397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Add an {@link OnItemTouchListener} to intercept touch events before they are dispatched 25407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to child views or this view's standard scrolling behavior. 25417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 25427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Client code may use listeners to implement item manipulation behavior. Once a listener 25437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * returns true from 25447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link OnItemTouchListener#onInterceptTouchEvent(RecyclerView, MotionEvent)} its 25457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link OnItemTouchListener#onTouchEvent(RecyclerView, MotionEvent)} method will be called 25467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * for each incoming MotionEvent until the end of the gesture.</p> 25477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 25487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param listener Listener to add 25497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see SimpleOnItemTouchListener 25507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 25517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void addOnItemTouchListener(OnItemTouchListener listener) { 25527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mOnItemTouchListeners.add(listener); 25537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 25547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 25557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 25567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Remove an {@link OnItemTouchListener}. It will no longer be able to intercept touch events. 25577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 25587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param listener Listener to remove 25597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 25607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void removeOnItemTouchListener(OnItemTouchListener listener) { 25617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mOnItemTouchListeners.remove(listener); 25627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mActiveOnItemTouchListener == listener) { 25637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mActiveOnItemTouchListener = null; 25647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 25657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 25667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 25677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private boolean dispatchOnItemTouchIntercept(MotionEvent e) { 25687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int action = e.getAction(); 25697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_DOWN) { 25707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mActiveOnItemTouchListener = null; 25717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 25727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 25737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int listenerCount = mOnItemTouchListeners.size(); 25747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < listenerCount; i++) { 25757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final OnItemTouchListener listener = mOnItemTouchListeners.get(i); 25767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (listener.onInterceptTouchEvent(this, e) && action != MotionEvent.ACTION_CANCEL) { 25777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mActiveOnItemTouchListener = listener; 25787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return true; 25797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 25807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 25817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 25827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 25837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 25847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private boolean dispatchOnItemTouch(MotionEvent e) { 25857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int action = e.getAction(); 25867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mActiveOnItemTouchListener != null) { 25877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (action == MotionEvent.ACTION_DOWN) { 25887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Stale state from a previous gesture, we're starting a new one. Clear it. 25897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mActiveOnItemTouchListener = null; 25907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 25917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mActiveOnItemTouchListener.onTouchEvent(this, e); 25927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { 25937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Clean up for the next gesture. 25947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mActiveOnItemTouchListener = null; 25957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 25967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return true; 25977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 25987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 25997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 26007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Listeners will have already received the ACTION_DOWN via dispatchOnItemTouchIntercept 26017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // as called from onInterceptTouchEvent; skip it. 26027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (action != MotionEvent.ACTION_DOWN) { 26037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int listenerCount = mOnItemTouchListeners.size(); 26047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < listenerCount; i++) { 26057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final OnItemTouchListener listener = mOnItemTouchListeners.get(i); 26067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (listener.onInterceptTouchEvent(this, e)) { 26077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mActiveOnItemTouchListener = listener; 26087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return true; 26097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 26107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 26117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 26127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 26137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 26147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 26157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 26167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean onInterceptTouchEvent(MotionEvent e) { 26177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayoutFrozen) { 26187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // When layout is frozen, RV does not intercept the motion event. 26197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // A child view e.g. a button may still get the click. 26207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 26217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 26227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (dispatchOnItemTouchIntercept(e)) { 26237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas cancelTouch(); 26247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return true; 26257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 26267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 26277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout == null) { 26287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 26297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 26307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 26317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean canScrollHorizontally = mLayout.canScrollHorizontally(); 26327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean canScrollVertically = mLayout.canScrollVertically(); 26337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 26347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mVelocityTracker == null) { 26357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mVelocityTracker = VelocityTracker.obtain(); 26367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 26377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mVelocityTracker.addMovement(e); 26387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 26397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int action = e.getActionMasked(); 26407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int actionIndex = e.getActionIndex(); 26417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 26427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas switch (action) { 26437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case MotionEvent.ACTION_DOWN: 26447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mIgnoreMotionEventTillDown) { 26457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mIgnoreMotionEventTillDown = false; 26467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 26477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScrollPointerId = e.getPointerId(0); 26487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mInitialTouchX = mLastTouchX = (int) (e.getX() + 0.5f); 26497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mInitialTouchY = mLastTouchY = (int) (e.getY() + 0.5f); 26507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 26517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mScrollState == SCROLL_STATE_SETTLING) { 26527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas getParent().requestDisallowInterceptTouchEvent(true); 26537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setScrollState(SCROLL_STATE_DRAGGING); 26547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 26557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 26567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Clear the nested offsets 26577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mNestedOffsets[0] = mNestedOffsets[1] = 0; 26587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 26597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int nestedScrollAxis = View.SCROLL_AXIS_NONE; 26607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (canScrollHorizontally) { 26617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas nestedScrollAxis |= View.SCROLL_AXIS_HORIZONTAL; 26627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 26637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (canScrollVertically) { 26647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas nestedScrollAxis |= View.SCROLL_AXIS_VERTICAL; 26657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 26667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas startNestedScroll(nestedScrollAxis); 26677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas break; 26687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 26697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case MotionEvent.ACTION_POINTER_DOWN: 26707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScrollPointerId = e.getPointerId(actionIndex); 26717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mInitialTouchX = mLastTouchX = (int) (e.getX(actionIndex) + 0.5f); 26727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mInitialTouchY = mLastTouchY = (int) (e.getY(actionIndex) + 0.5f); 26737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas break; 26747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 26757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case MotionEvent.ACTION_MOVE: { 26767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int index = e.findPointerIndex(mScrollPointerId); 26777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (index < 0) { 26787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.e(TAG, "Error processing scroll; pointer index for id " 26797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + mScrollPointerId + " not found. Did any MotionEvents get skipped?"); 26807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 26817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 26827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 26837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int x = (int) (e.getX(index) + 0.5f); 26847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int y = (int) (e.getY(index) + 0.5f); 26857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mScrollState != SCROLL_STATE_DRAGGING) { 26867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int dx = x - mInitialTouchX; 26877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int dy = y - mInitialTouchY; 26887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean startScroll = false; 26897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (canScrollHorizontally && Math.abs(dx) > mTouchSlop) { 26907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLastTouchX = mInitialTouchX + mTouchSlop * (dx < 0 ? -1 : 1); 26917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas startScroll = true; 26927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 26937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (canScrollVertically && Math.abs(dy) > mTouchSlop) { 26947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLastTouchY = mInitialTouchY + mTouchSlop * (dy < 0 ? -1 : 1); 26957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas startScroll = true; 26967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 26977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (startScroll) { 26987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setScrollState(SCROLL_STATE_DRAGGING); 26997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 27007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 27017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } break; 27027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 27037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case MotionEvent.ACTION_POINTER_UP: { 27047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onPointerUp(e); 27057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } break; 27067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 27077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case MotionEvent.ACTION_UP: { 27087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mVelocityTracker.clear(); 27097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas stopNestedScroll(); 27107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } break; 27117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 27127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case MotionEvent.ACTION_CANCEL: { 27137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas cancelTouch(); 27147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 27157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 27167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mScrollState == SCROLL_STATE_DRAGGING; 27177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 27187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 27197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 27207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { 27217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int listenerCount = mOnItemTouchListeners.size(); 27227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < listenerCount; i++) { 27237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final OnItemTouchListener listener = mOnItemTouchListeners.get(i); 27247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas listener.onRequestDisallowInterceptTouchEvent(disallowIntercept); 27257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 27267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super.requestDisallowInterceptTouchEvent(disallowIntercept); 27277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 27287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 27297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 27307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean onTouchEvent(MotionEvent e) { 27317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayoutFrozen || mIgnoreMotionEventTillDown) { 27327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 27337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 27347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (dispatchOnItemTouch(e)) { 27357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas cancelTouch(); 27367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return true; 27377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 27387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 27397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout == null) { 27407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 27417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 27427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 27437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean canScrollHorizontally = mLayout.canScrollHorizontally(); 27447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean canScrollVertically = mLayout.canScrollVertically(); 27457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 27467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mVelocityTracker == null) { 27477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mVelocityTracker = VelocityTracker.obtain(); 27487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 27497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean eventAddedToVelocityTracker = false; 27507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 27517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final MotionEvent vtev = MotionEvent.obtain(e); 27527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int action = e.getActionMasked(); 27537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int actionIndex = e.getActionIndex(); 27547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 27557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (action == MotionEvent.ACTION_DOWN) { 27567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mNestedOffsets[0] = mNestedOffsets[1] = 0; 27577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 27587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas vtev.offsetLocation(mNestedOffsets[0], mNestedOffsets[1]); 27597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 27607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas switch (action) { 27617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case MotionEvent.ACTION_DOWN: { 27627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScrollPointerId = e.getPointerId(0); 27637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mInitialTouchX = mLastTouchX = (int) (e.getX() + 0.5f); 27647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mInitialTouchY = mLastTouchY = (int) (e.getY() + 0.5f); 27657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 27667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int nestedScrollAxis = View.SCROLL_AXIS_NONE; 27677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (canScrollHorizontally) { 27687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas nestedScrollAxis |= View.SCROLL_AXIS_HORIZONTAL; 27697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 27707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (canScrollVertically) { 27717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas nestedScrollAxis |= View.SCROLL_AXIS_VERTICAL; 27727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 27737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas startNestedScroll(nestedScrollAxis); 27747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } break; 27757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 27767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case MotionEvent.ACTION_POINTER_DOWN: { 27777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScrollPointerId = e.getPointerId(actionIndex); 27787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mInitialTouchX = mLastTouchX = (int) (e.getX(actionIndex) + 0.5f); 27797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mInitialTouchY = mLastTouchY = (int) (e.getY(actionIndex) + 0.5f); 27807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } break; 27817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 27827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case MotionEvent.ACTION_MOVE: { 27837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int index = e.findPointerIndex(mScrollPointerId); 27847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (index < 0) { 27857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.e(TAG, "Error processing scroll; pointer index for id " 27867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + mScrollPointerId + " not found. Did any MotionEvents get skipped?"); 27877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 27887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 27897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 27907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int x = (int) (e.getX(index) + 0.5f); 27917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int y = (int) (e.getY(index) + 0.5f); 27927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int dx = mLastTouchX - x; 27937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int dy = mLastTouchY - y; 27947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 27957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (dispatchNestedPreScroll(dx, dy, mScrollConsumed, mScrollOffset)) { 27967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dx -= mScrollConsumed[0]; 27977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dy -= mScrollConsumed[1]; 27987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas vtev.offsetLocation(mScrollOffset[0], mScrollOffset[1]); 27997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Updated the nested offsets 28007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mNestedOffsets[0] += mScrollOffset[0]; 28017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mNestedOffsets[1] += mScrollOffset[1]; 28027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 28037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 28047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mScrollState != SCROLL_STATE_DRAGGING) { 28057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean startScroll = false; 28067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (canScrollHorizontally && Math.abs(dx) > mTouchSlop) { 28077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (dx > 0) { 28087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dx -= mTouchSlop; 28097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 28107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dx += mTouchSlop; 28117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 28127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas startScroll = true; 28137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 28147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (canScrollVertically && Math.abs(dy) > mTouchSlop) { 28157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (dy > 0) { 28167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dy -= mTouchSlop; 28177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 28187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dy += mTouchSlop; 28197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 28207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas startScroll = true; 28217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 28227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (startScroll) { 28237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setScrollState(SCROLL_STATE_DRAGGING); 28247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 28257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 28267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 28277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mScrollState == SCROLL_STATE_DRAGGING) { 28287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLastTouchX = x - mScrollOffset[0]; 28297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLastTouchY = y - mScrollOffset[1]; 28307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 28317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (scrollByInternal( 28327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas canScrollHorizontally ? dx : 0, 28337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas canScrollVertically ? dy : 0, 28347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas vtev)) { 28357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas getParent().requestDisallowInterceptTouchEvent(true); 28367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 28377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mGapWorker != null && (dx != 0 || dy != 0)) { 28387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mGapWorker.postFromTraversal(this, dx, dy); 28397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 28407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 28417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } break; 28427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 28437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case MotionEvent.ACTION_POINTER_UP: { 28447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onPointerUp(e); 28457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } break; 28467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 28477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case MotionEvent.ACTION_UP: { 28487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mVelocityTracker.addMovement(vtev); 28497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas eventAddedToVelocityTracker = true; 28507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mVelocityTracker.computeCurrentVelocity(1000, mMaxFlingVelocity); 28517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final float xvel = canScrollHorizontally 28527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ? -mVelocityTracker.getXVelocity(mScrollPointerId) : 0; 28537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final float yvel = canScrollVertically 28547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ? -mVelocityTracker.getYVelocity(mScrollPointerId) : 0; 28557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!((xvel != 0 || yvel != 0) && fling((int) xvel, (int) yvel))) { 28567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setScrollState(SCROLL_STATE_IDLE); 28577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 28587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resetTouch(); 28597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } break; 28607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 28617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case MotionEvent.ACTION_CANCEL: { 28627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas cancelTouch(); 28637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } break; 28647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 28657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 28667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!eventAddedToVelocityTracker) { 28677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mVelocityTracker.addMovement(vtev); 28687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 28697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas vtev.recycle(); 28707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 28717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return true; 28727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 28737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 28747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void resetTouch() { 28757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mVelocityTracker != null) { 28767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mVelocityTracker.clear(); 28777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 28787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas stopNestedScroll(); 28797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas releaseGlows(); 28807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 28817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 28827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void cancelTouch() { 28837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resetTouch(); 28847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setScrollState(SCROLL_STATE_IDLE); 28857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 28867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 28877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void onPointerUp(MotionEvent e) { 28887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int actionIndex = e.getActionIndex(); 28897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (e.getPointerId(actionIndex) == mScrollPointerId) { 28907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Pick a new pointer to pick up the slack. 28917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int newIndex = actionIndex == 0 ? 1 : 0; 28927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScrollPointerId = e.getPointerId(newIndex); 28937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mInitialTouchX = mLastTouchX = (int) (e.getX(newIndex) + 0.5f); 28947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mInitialTouchY = mLastTouchY = (int) (e.getY(newIndex) + 0.5f); 28957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 28967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 28977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 28987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // @Override 28997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean onGenericMotionEvent(MotionEvent event) { 29007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout == null) { 29017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 29027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 29037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayoutFrozen) { 29047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 29057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 29067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { 29077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (event.getAction() == MotionEvent.ACTION_SCROLL) { 29087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final float vScroll, hScroll; 29097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout.canScrollVertically()) { 29107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Inverse the sign of the vertical scroll to align the scroll orientation 29117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // with AbsListView. 29127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas vScroll = -event.getAxisValue(MotionEvent.AXIS_VSCROLL); 29137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 29147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas vScroll = 0f; 29157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 29167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout.canScrollHorizontally()) { 29177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas hScroll = event.getAxisValue(MotionEvent.AXIS_HSCROLL); 29187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 29197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas hScroll = 0f; 29207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 29217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 29227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (vScroll != 0 || hScroll != 0) { 29237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final float scrollFactor = getScrollFactor(); 29247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas scrollByInternal((int) (hScroll * scrollFactor), 29257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas (int) (vScroll * scrollFactor), event); 29267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 29277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 29287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 29297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 29307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 29317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 29327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 29337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Ported from View.getVerticalScrollFactor. 29347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 29357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private float getScrollFactor() { 29367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mScrollFactor == Float.MIN_VALUE) { 29377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas TypedValue outValue = new TypedValue(); 29387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (getContext().getTheme().resolveAttribute( 29397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas android.R.attr.listPreferredItemHeight, outValue, true)) { 29407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScrollFactor = outValue.getDimension( 29417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas getContext().getResources().getDisplayMetrics()); 29427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 29437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return 0; //listPreferredItemHeight is not defined, no generic scrolling 29447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 29457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 29467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mScrollFactor; 29477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 29487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 29497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 29507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas protected void onMeasure(int widthSpec, int heightSpec) { 29517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout == null) { 29527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas defaultOnMeasure(widthSpec, heightSpec); 29537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 29547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 29557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout.mAutoMeasure) { 29567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int widthMode = MeasureSpec.getMode(widthSpec); 29577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int heightMode = MeasureSpec.getMode(heightSpec); 29587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean skipMeasure = widthMode == MeasureSpec.EXACTLY 29597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && heightMode == MeasureSpec.EXACTLY; 29607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.onMeasure(mRecycler, mState, widthSpec, heightSpec); 29617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (skipMeasure || mAdapter == null) { 29627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 29637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 29647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mState.mLayoutStep == State.STEP_START) { 29657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchLayoutStep1(); 29667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 29677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // set dimensions in 2nd step. Pre-layout should happen with old dimensions for 29687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // consistency 29697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.setMeasureSpecs(widthSpec, heightSpec); 29707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mIsMeasuring = true; 29717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchLayoutStep2(); 29727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 29737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // now we can get the width and height from the children. 29747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.setMeasuredDimensionFromChildren(widthSpec, heightSpec); 29757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 29767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // if RecyclerView has non-exact width and height and if there is at least one child 29777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // which also has non-exact width & height, we have to re-measure. 29787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout.shouldMeasureTwice()) { 29797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.setMeasureSpecs( 29807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY), 29817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY)); 29827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mIsMeasuring = true; 29837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchLayoutStep2(); 29847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // now we can get the width and height from the children. 29857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.setMeasuredDimensionFromChildren(widthSpec, heightSpec); 29867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 29877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 29887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mHasFixedSize) { 29897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.onMeasure(mRecycler, mState, widthSpec, heightSpec); 29907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 29917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 29927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // custom onMeasure 29937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mAdapterUpdateDuringMeasure) { 29947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas eatRequestLayout(); 29957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onEnterLayoutOrScroll(); 29967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas processAdapterUpdatesAndSetAnimationFlags(); 29977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onExitLayoutOrScroll(); 29987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 29997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mState.mRunPredictiveAnimations) { 30007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mInPreLayout = true; 30017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 30027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // consume remaining updates to provide a consistent state with the layout pass. 30037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAdapterHelper.consumeUpdatesInOnePass(); 30047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mInPreLayout = false; 30057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 30067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAdapterUpdateDuringMeasure = false; 30077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resumeRequestLayout(false); 30087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 30097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 30107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mAdapter != null) { 30117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mItemCount = mAdapter.getItemCount(); 30127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 30137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mItemCount = 0; 30147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 30157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas eatRequestLayout(); 30167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.onMeasure(mRecycler, mState, widthSpec, heightSpec); 30177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resumeRequestLayout(false); 30187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mInPreLayout = false; // clear 30197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 30207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 30217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 30227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 30237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Used when onMeasure is called before layout manager is set 30247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 30257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void defaultOnMeasure(int widthSpec, int heightSpec) { 30267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // calling LayoutManager here is not pretty but that API is already public and it is better 30277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // than creating another method since this is internal. 30287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int width = LayoutManager.chooseSize(widthSpec, 30297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas getPaddingLeft() + getPaddingRight(), 30307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas getMinimumWidth()); 30317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int height = LayoutManager.chooseSize(heightSpec, 30327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas getPaddingTop() + getPaddingBottom(), 30337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas getMinimumHeight()); 30347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 30357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setMeasuredDimension(width, height); 30367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 30377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 30387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 30397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas protected void onSizeChanged(int w, int h, int oldw, int oldh) { 30407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super.onSizeChanged(w, h, oldw, oldh); 30417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (w != oldw || h != oldh) { 30427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas invalidateGlows(); 30437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // layout's w/h are updated during measure/layout steps. 30447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 30457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 30467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 30477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 30487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Sets the {@link ItemAnimator} that will handle animations involving changes 30497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to the items in this RecyclerView. By default, RecyclerView instantiates and 30507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * uses an instance of {@link DefaultItemAnimator}. Whether item animations are 30517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * enabled for the RecyclerView depends on the ItemAnimator and whether 30527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the LayoutManager {@link LayoutManager#supportsPredictiveItemAnimations() 30537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * supports item animations}. 30547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 30557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param animator The ItemAnimator being set. If null, no animations will occur 30567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * when changes occur to the items in this RecyclerView. 30577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 30587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setItemAnimator(ItemAnimator animator) { 30597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mItemAnimator != null) { 30607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemAnimator.endAnimations(); 30617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemAnimator.setListener(null); 30627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 30637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemAnimator = animator; 30647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mItemAnimator != null) { 30657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemAnimator.setListener(mItemAnimatorListener); 30667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 30677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 30687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 30697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void onEnterLayoutOrScroll() { 30707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayoutOrScrollCounter++; 30717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 30727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 30737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void onExitLayoutOrScroll() { 30747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayoutOrScrollCounter--; 30757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayoutOrScrollCounter < 1) { 30767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG && mLayoutOrScrollCounter < 0) { 30777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException("layout or scroll counter cannot go below zero." 30787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "Some calls are not matching"); 30797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 30807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayoutOrScrollCounter = 0; 30817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchContentChangedIfNecessary(); 30827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchPendingImportantForAccessibilityChanges(); 30837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 30847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 30857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 30867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean isAccessibilityEnabled() { 30877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mAccessibilityManager != null && mAccessibilityManager.isEnabled(); 30887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 30897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 30907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void dispatchContentChangedIfNecessary() { 30917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int flags = mEatenAccessibilityChangeFlags; 30927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mEatenAccessibilityChangeFlags = 0; 30937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (flags != 0 && isAccessibilityEnabled()) { 30947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final AccessibilityEvent event = AccessibilityEvent.obtain(); 30957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); 30967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas event.setContentChangeTypes(flags); 30977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas sendAccessibilityEventUnchecked(event); 30987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 30997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 31007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 31017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 31027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns whether RecyclerView is currently computing a layout. 31037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 31047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If this method returns true, it means that RecyclerView is in a lockdown state and any 31057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * attempt to update adapter contents will result in an exception because adapter contents 31067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * cannot be changed while RecyclerView is trying to compute the layout. 31077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 31087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * It is very unlikely that your code will be running during this state as it is 31097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * called by the framework when a layout traversal happens or RecyclerView starts to scroll 31107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * in response to system events (touch, accessibility etc). 31117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 31127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This case may happen if you have some custom logic to change adapter contents in 31137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * response to a View callback (e.g. focus change callback) which might be triggered during a 31147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * layout calculation. In these cases, you should just postpone the change using a Handler or a 31157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * similar mechanism. 31167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 31177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return <code>true</code> if RecyclerView is currently computing a layout, <code>false</code> 31187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * otherwise 31197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 31207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean isComputingLayout() { 31217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mLayoutOrScrollCounter > 0; 31227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 31237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 31247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 31257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns true if an accessibility event should not be dispatched now. This happens when an 31267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * accessibility request arrives while RecyclerView does not have a stable state which is very 31277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * hard to handle for a LayoutManager. Instead, this method records necessary information about 31287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the event and dispatches a window change event after the critical section is finished. 31297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 31307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return True if the accessibility event should be postponed. 31317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 31327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean shouldDeferAccessibilityEvent(AccessibilityEvent event) { 31337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (isComputingLayout()) { 31347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int type = 0; 31357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (event != null) { 31367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas type = event.getContentChangeTypes(); 31377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 31387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (type == 0) { 31397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas type = AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED; 31407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 31417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mEatenAccessibilityChangeFlags |= type; 31427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return true; 31437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 31447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 31457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 31467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 31477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 31487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void sendAccessibilityEventUnchecked(AccessibilityEvent event) { 31497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (shouldDeferAccessibilityEvent(event)) { 31507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 31517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 31527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super.sendAccessibilityEventUnchecked(event); 31537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 31547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 31557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 31567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Gets the current ItemAnimator for this RecyclerView. A null return value 31577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * indicates that there is no animator and that item changes will happen without 31587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * any animations. By default, RecyclerView instantiates and 31597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * uses an instance of {@link DefaultItemAnimator}. 31607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 31617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return ItemAnimator The current ItemAnimator. If null, no animations will occur 31627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * when changes occur to the items in this RecyclerView. 31637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 31647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public ItemAnimator getItemAnimator() { 31657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mItemAnimator; 31667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 31677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 31687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 31697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Post a runnable to the next frame to run pending item animations. Only the first such 31707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * request will be posted, governed by the mPostedAnimatorRunner flag. 31717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 31727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void postAnimationRunner() { 31737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!mPostedAnimatorRunner && mIsAttached) { 31747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas postOnAnimation(mItemAnimatorRunner); 31757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPostedAnimatorRunner = true; 31767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 31777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 31787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 31797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private boolean predictiveItemAnimationsEnabled() { 31807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return (mItemAnimator != null && mLayout.supportsPredictiveItemAnimations()); 31817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 31827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 31837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 31847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Consumes adapter updates and calculates which type of animations we want to run. 31857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called in onMeasure and dispatchLayout. 31867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 31877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method may process only the pre-layout state of updates or all of them. 31887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 31897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void processAdapterUpdatesAndSetAnimationFlags() { 31907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mDataSetHasChangedAfterLayout) { 31917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Processing these items have no value since data set changed unexpectedly. 31927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Instead, we just reset it. 31937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAdapterHelper.reset(); 31947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.onItemsChanged(this); 31957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 31967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // simple animations are a subset of advanced animations (which will cause a 31977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // pre-layout step) 31987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // If layout supports predictive animations, pre-process to decide if we want to run them 31997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (predictiveItemAnimationsEnabled()) { 32007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAdapterHelper.preProcess(); 32017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 32027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAdapterHelper.consumeUpdatesInOnePass(); 32037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 32047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean animationTypeSupported = mItemsAddedOrRemoved || mItemsChanged; 32057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mRunSimpleAnimations = mFirstLayoutComplete 32067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && mItemAnimator != null 32077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && (mDataSetHasChangedAfterLayout 32087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || animationTypeSupported 32097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || mLayout.mRequestedSimpleAnimations) 32107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && (!mDataSetHasChangedAfterLayout 32117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || mAdapter.hasStableIds()); 32127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mRunPredictiveAnimations = mState.mRunSimpleAnimations 32137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && animationTypeSupported 32147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && !mDataSetHasChangedAfterLayout 32157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && predictiveItemAnimationsEnabled(); 32167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 32177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 32187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 32197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Wrapper around layoutChildren() that handles animating changes caused by layout. 32207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Animations work on the assumption that there are five different kinds of items 32217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * in play: 32227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * PERSISTENT: items are visible before and after layout 32237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * REMOVED: items were visible before layout and were removed by the app 32247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ADDED: items did not exist before layout and were added by the app 32257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * DISAPPEARING: items exist in the data set before/after, but changed from 32267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * visible to non-visible in the process of layout (they were moved off 32277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * screen as a side-effect of other changes) 32287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * APPEARING: items exist in the data set before/after, but changed from 32297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * non-visible to visible in the process of layout (they were moved on 32307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * screen as a side-effect of other changes) 32317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The overall approach figures out what items exist before/after layout and 32327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * infers one of the five above states for each of the items. Then the animations 32337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * are set up accordingly: 32347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * PERSISTENT views are animated via 32357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link ItemAnimator#animatePersistence(ViewHolder, ItemHolderInfo, ItemHolderInfo)} 32367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * DISAPPEARING views are animated via 32377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link ItemAnimator#animateDisappearance(ViewHolder, ItemHolderInfo, ItemHolderInfo)} 32387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * APPEARING views are animated via 32397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link ItemAnimator#animateAppearance(ViewHolder, ItemHolderInfo, ItemHolderInfo)} 32407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * and changed views are animated via 32417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link ItemAnimator#animateChange(ViewHolder, ViewHolder, ItemHolderInfo, ItemHolderInfo)}. 32427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 32437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void dispatchLayout() { 32447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mAdapter == null) { 32457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.e(TAG, "No adapter attached; skipping layout"); 32467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // leave the state in START 32477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 32487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 32497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout == null) { 32507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.e(TAG, "No layout manager attached; skipping layout"); 32517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // leave the state in START 32527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 32537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 32547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mIsMeasuring = false; 32557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mState.mLayoutStep == State.STEP_START) { 32567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchLayoutStep1(); 32577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.setExactMeasureSpecsFrom(this); 32587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchLayoutStep2(); 32597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (mAdapterHelper.hasUpdates() || mLayout.getWidth() != getWidth() 32607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || mLayout.getHeight() != getHeight()) { 32617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // First 2 steps are done in onMeasure but looks like we have to run again due to 32627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // changed size. 32637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.setExactMeasureSpecsFrom(this); 32647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchLayoutStep2(); 32657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 32667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // always make sure we sync them (to ensure mode is exact) 32677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.setExactMeasureSpecsFrom(this); 32687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 32697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchLayoutStep3(); 32707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 32717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 32727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void saveFocusInfo() { 32737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas View child = null; 32747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mPreserveFocusAfterLayout && hasFocus() && mAdapter != null) { 32757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas child = getFocusedChild(); 32767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 32777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 32787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder focusedVh = child == null ? null : findContainingViewHolder(child); 32797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (focusedVh == null) { 32807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resetFocusInfo(); 32817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 32827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mFocusedItemId = mAdapter.hasStableIds() ? focusedVh.getItemId() : NO_ID; 32837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // mFocusedItemPosition should hold the current adapter position of the previously 32847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // focused item. If the item is removed, we store the previous adapter position of the 32857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // removed item. 32867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mFocusedItemPosition = mDataSetHasChangedAfterLayout ? NO_POSITION 32877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas : (focusedVh.isRemoved() ? focusedVh.mOldPosition 32887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas : focusedVh.getAdapterPosition()); 32897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mFocusedSubChildId = getDeepestFocusedViewWithId(focusedVh.itemView); 32907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 32917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 32927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 32937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void resetFocusInfo() { 32947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mFocusedItemId = NO_ID; 32957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mFocusedItemPosition = NO_POSITION; 32967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mFocusedSubChildId = View.NO_ID; 32977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 32987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 32997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 33007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Finds the best view candidate to request focus on using mFocusedItemPosition index of the 33017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * previously focused item. It first traverses the adapter forward to find a focusable candidate 33027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * and if no such candidate is found, it reverses the focus search direction for the items 33037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * before the mFocusedItemPosition'th index; 33047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The best candidate to request focus on, or null if no such candidate exists. Null 33057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * indicates all the existing adapter items are unfocusable. 33067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 33077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Nullable 33087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private View findNextViewToFocus() { 33097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int startFocusSearchIndex = mState.mFocusedItemPosition != -1 ? mState.mFocusedItemPosition 33107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas : 0; 33117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder nextFocus; 33127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int itemCount = mState.getItemCount(); 33137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = startFocusSearchIndex; i < itemCount; i++) { 33147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas nextFocus = findViewHolderForAdapterPosition(i); 33157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (nextFocus == null) { 33167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas break; 33177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 33187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (nextFocus.itemView.hasFocusable()) { 33197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return nextFocus.itemView; 33207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 33217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 33227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int limit = Math.min(itemCount, startFocusSearchIndex); 33237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = limit - 1; i >= 0; i--) { 33247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas nextFocus = findViewHolderForAdapterPosition(i); 33257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (nextFocus == null) { 33267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 33277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 33287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (nextFocus.itemView.hasFocusable()) { 33297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return nextFocus.itemView; 33307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 33317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 33327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 33337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 33347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 33357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void recoverFocusFromState() { 33367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!mPreserveFocusAfterLayout || mAdapter == null || !hasFocus() 33377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || getDescendantFocusability() == FOCUS_BLOCK_DESCENDANTS 33387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || (getDescendantFocusability() == FOCUS_BEFORE_DESCENDANTS && isFocused())) { 33397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // No-op if either of these cases happens: 33407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // 1. RV has no focus, or 2. RV blocks focus to its children, or 3. RV takes focus 33417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // before its children and is focused (i.e. it already stole the focus away from its 33427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // descendants). 33437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 33447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 33457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // only recover focus if RV itself has the focus or the focused view is hidden 33467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!isFocused()) { 33477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View focusedChild = getFocusedChild(); 33487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (IGNORE_DETACHED_FOCUSED_CHILD 33497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && (focusedChild.getParent() == null || !focusedChild.hasFocus())) { 33507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Special handling of API 15-. A focused child can be invalid because mFocus is not 33517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // cleared when the child is detached (mParent = null), 33527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // This happens because clearFocus on API 15- does not invalidate mFocus of its 33537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // parent when this child is detached. 33547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // For API 16+, this is not an issue because requestFocus takes care of clearing the 33557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // prior detached focused child. For API 15- the problem happens in 2 cases because 33567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // clearChild does not call clearChildFocus on RV: 1. setFocusable(false) is called 33577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // for the current focused item which calls clearChild or 2. when the prior focused 33587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // child is removed, removeDetachedView called in layout step 3 which calls 33597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // clearChild. We should ignore this invalid focused child in all our calculations 33607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // for the next view to receive focus, and apply the focus recovery logic instead. 33617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mChildHelper.getChildCount() == 0) { 33627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // No children left. Request focus on the RV itself since one of its children 33637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // was holding focus previously. 33647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas requestFocus(); 33657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 33667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 33677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (!mChildHelper.isHidden(focusedChild)) { 33687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // If the currently focused child is hidden, apply the focus recovery logic. 33697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Otherwise return, i.e. the currently (unhidden) focused child is good enough :/. 33707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 33717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 33727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 33737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder focusTarget = null; 33747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // RV first attempts to locate the previously focused item to request focus on using 33757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // mFocusedItemId. If such an item no longer exists, it then makes a best-effort attempt to 33767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // find the next best candidate to request focus on based on mFocusedItemPosition. 33777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mState.mFocusedItemId != NO_ID && mAdapter.hasStableIds()) { 33787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas focusTarget = findViewHolderForItemId(mState.mFocusedItemId); 33797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 33807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas View viewToFocus = null; 33817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (focusTarget == null || mChildHelper.isHidden(focusTarget.itemView) 33827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || !focusTarget.itemView.hasFocusable()) { 33837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mChildHelper.getChildCount() > 0) { 33847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // At this point, RV has focus and either of these conditions are true: 33857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // 1. There's no previously focused item either because RV received focused before 33867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // layout, or the previously focused item was removed, or RV doesn't have stable IDs 33877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // 2. Previous focus child is hidden, or 3. Previous focused child is no longer 33887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // focusable. In either of these cases, we make sure that RV still passes down the 33897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // focus to one of its focusable children using a best-effort algorithm. 33907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas viewToFocus = findNextViewToFocus(); 33917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 33927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 33937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // looks like the focused item has been replaced with another view that represents the 33947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // same item in the adapter. Request focus on that. 33957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas viewToFocus = focusTarget.itemView; 33967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 33977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 33987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (viewToFocus != null) { 33997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mState.mFocusedSubChildId != NO_ID) { 34007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas View child = viewToFocus.findViewById(mState.mFocusedSubChildId); 34017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (child != null && child.isFocusable()) { 34027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas viewToFocus = child; 34037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 34047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 34057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas viewToFocus.requestFocus(); 34067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 34077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 34087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 34097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int getDeepestFocusedViewWithId(View view) { 34107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int lastKnownId = view.getId(); 34117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas while (!view.isFocused() && view instanceof ViewGroup && view.hasFocus()) { 34127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas view = ((ViewGroup) view).getFocusedChild(); 34137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int id = view.getId(); 34147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (id != View.NO_ID) { 34157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas lastKnownId = view.getId(); 34167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 34177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 34187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return lastKnownId; 34197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 34207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 34217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 34227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The first step of a layout where we; 34237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * - process adapter updates 34247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * - decide which animation should run 34257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * - save information about current views 34267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * - If necessary, run predictive layout and save its information 34277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 34287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void dispatchLayoutStep1() { 34297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.assertLayoutStep(State.STEP_START); 34307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mIsMeasuring = false; 34317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas eatRequestLayout(); 34327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mViewInfoStore.clear(); 34337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onEnterLayoutOrScroll(); 34347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas processAdapterUpdatesAndSetAnimationFlags(); 34357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas saveFocusInfo(); 34367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mTrackOldChangeHolders = mState.mRunSimpleAnimations && mItemsChanged; 34377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemsAddedOrRemoved = mItemsChanged = false; 34387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mInPreLayout = mState.mRunPredictiveAnimations; 34397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mItemCount = mAdapter.getItemCount(); 34407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas findMinMaxChildLayoutPositions(mMinMaxLayoutPositions); 34417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 34427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mState.mRunSimpleAnimations) { 34437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Step 0: Find out where all non-removed items are, pre-layout 34447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int count = mChildHelper.getChildCount(); 34457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < count; ++i) { 34467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = getChildViewHolderInt(mChildHelper.getChildAt(i)); 34477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.shouldIgnore() || (holder.isInvalid() && !mAdapter.hasStableIds())) { 34487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas continue; 34497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 34507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ItemHolderInfo animationInfo = mItemAnimator 34517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas .recordPreLayoutInformation(mState, holder, 34527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ItemAnimator.buildAdapterChangeFlagsForAnimations(holder), 34537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.getUnmodifiedPayloads()); 34547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mViewInfoStore.addToPreLayout(holder, animationInfo); 34557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mState.mTrackOldChangeHolders && holder.isUpdated() && !holder.isRemoved() 34567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && !holder.shouldIgnore() && !holder.isInvalid()) { 34577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas long key = getChangedHolderKey(holder); 34587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // This is NOT the only place where a ViewHolder is added to old change holders 34597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // list. There is another case where: 34607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // * A VH is currently hidden but not deleted 34617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // * The hidden item is changed in the adapter 34627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // * Layout manager decides to layout the item in the pre-Layout pass (step1) 34637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // When this case is detected, RV will un-hide that view and add to the old 34647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // change holders list. 34657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mViewInfoStore.addToOldChangeHolders(key, holder); 34667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 34677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 34687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 34697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mState.mRunPredictiveAnimations) { 34707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Step 1: run prelayout: This will use the old positions of items. The layout manager 34717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // is expected to layout everything, even removed items (though not to add removed 34727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // items back to the container). This gives the pre-layout position of APPEARING views 34737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // which come into existence as part of the real layout. 34747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 34757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Save old positions so that LayoutManager can run its mapping logic. 34767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas saveOldPositions(); 34777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean didStructureChange = mState.mStructureChanged; 34787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mStructureChanged = false; 34797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // temporarily disable flag because we are asking for previous layout 34807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.onLayoutChildren(mRecycler, mState); 34817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mStructureChanged = didStructureChange; 34827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 34837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < mChildHelper.getChildCount(); ++i) { 34847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View child = mChildHelper.getChildAt(i); 34857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder viewHolder = getChildViewHolderInt(child); 34867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (viewHolder.shouldIgnore()) { 34877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas continue; 34887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 34897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!mViewInfoStore.isInPreLayout(viewHolder)) { 34907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int flags = ItemAnimator.buildAdapterChangeFlagsForAnimations(viewHolder); 34917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean wasHidden = viewHolder 34927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas .hasAnyOfTheFlags(ViewHolder.FLAG_BOUNCED_FROM_HIDDEN_LIST); 34937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!wasHidden) { 34947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas flags |= ItemAnimator.FLAG_APPEARED_IN_PRE_LAYOUT; 34957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 34967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ItemHolderInfo animationInfo = mItemAnimator.recordPreLayoutInformation( 34977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState, viewHolder, flags, viewHolder.getUnmodifiedPayloads()); 34987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (wasHidden) { 34997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recordAnimationInfoIfBouncedHiddenView(viewHolder, animationInfo); 35007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 35017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mViewInfoStore.addToAppearedInPreLayoutHolders(viewHolder, animationInfo); 35027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 35037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 35047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 35057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // we don't process disappearing list because they may re-appear in post layout pass. 35067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas clearOldPositions(); 35077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 35087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas clearOldPositions(); 35097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 35107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onExitLayoutOrScroll(); 35117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resumeRequestLayout(false); 35127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mLayoutStep = State.STEP_LAYOUT; 35137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 35147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 35157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 35167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The second layout step where we do the actual layout of the views for the final state. 35177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This step might be run multiple times if necessary (e.g. measure). 35187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 35197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void dispatchLayoutStep2() { 35207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas eatRequestLayout(); 35217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onEnterLayoutOrScroll(); 35227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.assertLayoutStep(State.STEP_LAYOUT | State.STEP_ANIMATIONS); 35237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAdapterHelper.consumeUpdatesInOnePass(); 35247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mItemCount = mAdapter.getItemCount(); 35257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mDeletedInvisibleItemCountSincePreviousLayout = 0; 35267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 35277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Step 2: Run layout 35287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mInPreLayout = false; 35297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.onLayoutChildren(mRecycler, mState); 35307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 35317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mStructureChanged = false; 35327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPendingSavedState = null; 35337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 35347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // onLayoutChildren may have caused client code to disable item animations; re-check 35357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mRunSimpleAnimations = mState.mRunSimpleAnimations && mItemAnimator != null; 35367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mLayoutStep = State.STEP_ANIMATIONS; 35377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onExitLayoutOrScroll(); 35387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resumeRequestLayout(false); 35397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 35407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 35417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 35427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The final step of the layout where we save the information about views for animations, 35437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * trigger animations and do any necessary cleanup. 35447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 35457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void dispatchLayoutStep3() { 35467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.assertLayoutStep(State.STEP_ANIMATIONS); 35477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas eatRequestLayout(); 35487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onEnterLayoutOrScroll(); 35497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mLayoutStep = State.STEP_START; 35507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mState.mRunSimpleAnimations) { 35517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Step 3: Find out where things are now, and process change animations. 35527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // traverse list in reverse because we may call animateChange in the loop which may 35537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // remove the target view holder. 35547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = mChildHelper.getChildCount() - 1; i >= 0; i--) { 35557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder holder = getChildViewHolderInt(mChildHelper.getChildAt(i)); 35567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.shouldIgnore()) { 35577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas continue; 35587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 35597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas long key = getChangedHolderKey(holder); 35607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ItemHolderInfo animationInfo = mItemAnimator 35617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas .recordPostLayoutInformation(mState, holder); 35627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder oldChangeViewHolder = mViewInfoStore.getFromOldChangeHolders(key); 35637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (oldChangeViewHolder != null && !oldChangeViewHolder.shouldIgnore()) { 35647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // run a change animation 35657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 35667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // If an Item is CHANGED but the updated version is disappearing, it creates 35677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // a conflicting case. 35687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Since a view that is marked as disappearing is likely to be going out of 35697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // bounds, we run a change animation. Both views will be cleaned automatically 35707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // once their animations finish. 35717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // On the other hand, if it is the same view holder instance, we run a 35727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // disappearing animation instead because we are not going to rebind the updated 35737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // VH unless it is enforced by the layout manager. 35747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean oldDisappearing = mViewInfoStore.isDisappearing( 35757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas oldChangeViewHolder); 35767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean newDisappearing = mViewInfoStore.isDisappearing(holder); 35777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (oldDisappearing && oldChangeViewHolder == holder) { 35787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // run disappear animation instead of change 35797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mViewInfoStore.addToPostLayout(holder, animationInfo); 35807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 35817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ItemHolderInfo preInfo = mViewInfoStore.popFromPreLayout( 35827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas oldChangeViewHolder); 35837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // we add and remove so that any post info is merged. 35847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mViewInfoStore.addToPostLayout(holder, animationInfo); 35857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ItemHolderInfo postInfo = mViewInfoStore.popFromPostLayout(holder); 35867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (preInfo == null) { 35877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas handleMissingPreInfoForChangeError(key, holder, oldChangeViewHolder); 35887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 35897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas animateChange(oldChangeViewHolder, holder, preInfo, postInfo, 35907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas oldDisappearing, newDisappearing); 35917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 35927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 35937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 35947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mViewInfoStore.addToPostLayout(holder, animationInfo); 35957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 35967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 35977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 35987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Step 4: Process view info lists and trigger animations 35997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mViewInfoStore.process(mViewInfoProcessCallback); 36007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 36017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 36027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.removeAndRecycleScrapInt(mRecycler); 36037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mPreviousLayoutItemCount = mState.mItemCount; 36047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mDataSetHasChangedAfterLayout = false; 36057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mRunSimpleAnimations = false; 36067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 36077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mRunPredictiveAnimations = false; 36087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.mRequestedSimpleAnimations = false; 36097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecycler.mChangedScrap != null) { 36107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.mChangedScrap.clear(); 36117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 36127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout.mPrefetchMaxObservedInInitialPrefetch) { 36137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Initial prefetch has expanded cache, so reset until next prefetch. 36147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // This prevents initial prefetches from expanding the cache permanently. 36157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.mPrefetchMaxCountObserved = 0; 36167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.mPrefetchMaxObservedInInitialPrefetch = false; 36177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.updateViewCacheSize(); 36187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 36197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 36207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.onLayoutCompleted(mState); 36217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onExitLayoutOrScroll(); 36227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resumeRequestLayout(false); 36237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mViewInfoStore.clear(); 36247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (didChildRangeChange(mMinMaxLayoutPositions[0], mMinMaxLayoutPositions[1])) { 36257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchOnScrolled(0, 0); 36267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 36277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recoverFocusFromState(); 36287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resetFocusInfo(); 36297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 36307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 36317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 36327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This handles the case where there is an unexpected VH missing in the pre-layout map. 36337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 36347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * We might be able to detect the error in the application which will help the developer to 36357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * resolve the issue. 36367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 36377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If it is not an expected error, we at least print an error to notify the developer and ignore 36387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the animation. 36397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 36407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * https://code.google.com/p/android/issues/detail?id=193958 36417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 36427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param key The change key 36437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param holder Current ViewHolder 36447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param oldChangeViewHolder Changed ViewHolder 36457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 36467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void handleMissingPreInfoForChangeError(long key, 36477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder holder, ViewHolder oldChangeViewHolder) { 36487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // check if two VH have the same key, if so, print that as an error 36497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childCount = mChildHelper.getChildCount(); 36507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < childCount; i++) { 36517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas View view = mChildHelper.getChildAt(i); 36527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder other = getChildViewHolderInt(view); 36537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (other == holder) { 36547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas continue; 36557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 36567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final long otherKey = getChangedHolderKey(other); 36577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (otherKey == key) { 36587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mAdapter != null && mAdapter.hasStableIds()) { 36597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException("Two different ViewHolders have the same stable" 36607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " ID. Stable IDs in your adapter MUST BE unique and SHOULD NOT" 36617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " change.\n ViewHolder 1:" + other + " \n View Holder 2:" + holder); 36627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 36637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException("Two different ViewHolders have the same change" 36647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " ID. This might happen due to inconsistent Adapter update events or" 36657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " if the LayoutManager lays out the same View multiple times." 36667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "\n ViewHolder 1:" + other + " \n View Holder 2:" + holder); 36677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 36687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 36697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 36707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Very unlikely to happen but if it does, notify the developer. 36717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.e(TAG, "Problem while matching changed view holders with the new" 36727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "ones. The pre-layout information for the change holder " + oldChangeViewHolder 36737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " cannot be found but it is necessary for " + holder); 36747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 36757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 36767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 36777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Records the animation information for a view holder that was bounced from hidden list. It 36787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * also clears the bounce back flag. 36797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 36807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void recordAnimationInfoIfBouncedHiddenView(ViewHolder viewHolder, 36817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ItemHolderInfo animationInfo) { 36827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // looks like this view bounced back from hidden list! 36837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas viewHolder.setFlags(0, ViewHolder.FLAG_BOUNCED_FROM_HIDDEN_LIST); 36847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mState.mTrackOldChangeHolders && viewHolder.isUpdated() 36857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && !viewHolder.isRemoved() && !viewHolder.shouldIgnore()) { 36867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas long key = getChangedHolderKey(viewHolder); 36877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mViewInfoStore.addToOldChangeHolders(key, viewHolder); 36887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 36897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mViewInfoStore.addToPreLayout(viewHolder, animationInfo); 36907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 36917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 36927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void findMinMaxChildLayoutPositions(int[] into) { 36937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int count = mChildHelper.getChildCount(); 36947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (count == 0) { 36957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas into[0] = NO_POSITION; 36967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas into[1] = NO_POSITION; 36977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 36987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 36997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int minPositionPreLayout = Integer.MAX_VALUE; 37007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int maxPositionPreLayout = Integer.MIN_VALUE; 37017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < count; ++i) { 37027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = getChildViewHolderInt(mChildHelper.getChildAt(i)); 37037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.shouldIgnore()) { 37047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas continue; 37057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 37067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int pos = holder.getLayoutPosition(); 37077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (pos < minPositionPreLayout) { 37087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas minPositionPreLayout = pos; 37097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 37107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (pos > maxPositionPreLayout) { 37117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas maxPositionPreLayout = pos; 37127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 37137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 37147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas into[0] = minPositionPreLayout; 37157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas into[1] = maxPositionPreLayout; 37167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 37177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 37187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private boolean didChildRangeChange(int minPositionPreLayout, int maxPositionPreLayout) { 37197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas findMinMaxChildLayoutPositions(mMinMaxLayoutPositions); 37207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mMinMaxLayoutPositions[0] != minPositionPreLayout 37217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || mMinMaxLayoutPositions[1] != maxPositionPreLayout; 37227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 37237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 37247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 37257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas protected void removeDetachedView(View child, boolean animate) { 37267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder vh = getChildViewHolderInt(child); 37277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (vh != null) { 37287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (vh.isTmpDetached()) { 37297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas vh.clearTmpDetachFlag(); 37307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (!vh.shouldIgnore()) { 37317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalArgumentException("Called removeDetachedView with a view which" 37327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " is not flagged as tmp detached." + vh); 37337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 37347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 37357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchChildDetached(child); 37367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super.removeDetachedView(child, animate); 37377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 37387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 37397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 37407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns a unique key to be used while handling change animations. 37417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * It might be child's position or stable id depending on the adapter type. 37427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 37437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas long getChangedHolderKey(ViewHolder holder) { 37447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mAdapter.hasStableIds() ? holder.getItemId() : holder.mPosition; 37457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 37467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 37477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void animateAppearance(@NonNull ViewHolder itemHolder, 37487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Nullable ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) { 37497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas itemHolder.setIsRecyclable(false); 37507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mItemAnimator.animateAppearance(itemHolder, preLayoutInfo, postLayoutInfo)) { 37517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas postAnimationRunner(); 37527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 37537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 37547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 37557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void animateDisappearance(@NonNull ViewHolder holder, 37567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @NonNull ItemHolderInfo preLayoutInfo, @Nullable ItemHolderInfo postLayoutInfo) { 37577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas addAnimatingView(holder); 37587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.setIsRecyclable(false); 37597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mItemAnimator.animateDisappearance(holder, preLayoutInfo, postLayoutInfo)) { 37607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas postAnimationRunner(); 37617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 37627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 37637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 37647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void animateChange(@NonNull ViewHolder oldHolder, @NonNull ViewHolder newHolder, 37657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @NonNull ItemHolderInfo preInfo, @NonNull ItemHolderInfo postInfo, 37667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean oldHolderDisappearing, boolean newHolderDisappearing) { 37677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas oldHolder.setIsRecyclable(false); 37687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (oldHolderDisappearing) { 37697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas addAnimatingView(oldHolder); 37707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 37717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (oldHolder != newHolder) { 37727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (newHolderDisappearing) { 37737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas addAnimatingView(newHolder); 37747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 37757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas oldHolder.mShadowedHolder = newHolder; 37767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // old holder should disappear after animation ends 37777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas addAnimatingView(oldHolder); 37787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.unscrapView(oldHolder); 37797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas newHolder.setIsRecyclable(false); 37807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas newHolder.mShadowingHolder = oldHolder; 37817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 37827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mItemAnimator.animateChange(oldHolder, newHolder, preInfo, postInfo)) { 37837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas postAnimationRunner(); 37847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 37857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 37867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 37877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 37887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas protected void onLayout(boolean changed, int l, int t, int r, int b) { 37897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Trace.beginSection(TRACE_ON_LAYOUT_TAG); 37907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchLayout(); 37917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Trace.endSection(); 37927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mFirstLayoutComplete = true; 37937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 37947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 37957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 37967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void requestLayout() { 37977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mEatRequestLayout == 0 && !mLayoutFrozen) { 37987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super.requestLayout(); 37997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 38007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayoutRequestEaten = true; 38017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 38027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 38037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 38047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void markItemDecorInsetsDirty() { 38057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childCount = mChildHelper.getUnfilteredChildCount(); 38067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < childCount; i++) { 38077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View child = mChildHelper.getUnfilteredChildAt(i); 38087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ((LayoutParams) child.getLayoutParams()).mInsetsDirty = true; 38097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 38107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.markItemDecorInsetsDirty(); 38117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 38127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 38137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 38147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void draw(Canvas c) { 38157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super.draw(c); 38167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 38177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int count = mItemDecorations.size(); 38187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < count; i++) { 38197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemDecorations.get(i).onDrawOver(c, this, mState); 38207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 38217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // TODO If padding is not 0 and clipChildrenToPadding is false, to draw glows properly, we 38227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // need find children closest to edges. Not sure if it is worth the effort. 38237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean needsInvalidate = false; 38247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLeftGlow != null && !mLeftGlow.isFinished()) { 38257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int restore = c.save(); 38267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int padding = mClipToPadding ? getPaddingBottom() : 0; 38277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas c.rotate(270); 38287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas c.translate(-getHeight() + padding, 0); 38297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas needsInvalidate = mLeftGlow != null && mLeftGlow.draw(c); 38307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas c.restoreToCount(restore); 38317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 38327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mTopGlow != null && !mTopGlow.isFinished()) { 38337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int restore = c.save(); 38347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mClipToPadding) { 38357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas c.translate(getPaddingLeft(), getPaddingTop()); 38367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 38377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas needsInvalidate |= mTopGlow != null && mTopGlow.draw(c); 38387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas c.restoreToCount(restore); 38397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 38407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRightGlow != null && !mRightGlow.isFinished()) { 38417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int restore = c.save(); 38427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int width = getWidth(); 38437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int padding = mClipToPadding ? getPaddingTop() : 0; 38447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas c.rotate(90); 38457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas c.translate(-padding, -width); 38467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas needsInvalidate |= mRightGlow != null && mRightGlow.draw(c); 38477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas c.restoreToCount(restore); 38487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 38497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mBottomGlow != null && !mBottomGlow.isFinished()) { 38507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int restore = c.save(); 38517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas c.rotate(180); 38527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mClipToPadding) { 38537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas c.translate(-getWidth() + getPaddingRight(), -getHeight() + getPaddingBottom()); 38547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 38557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas c.translate(-getWidth(), -getHeight()); 38567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 38577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas needsInvalidate |= mBottomGlow != null && mBottomGlow.draw(c); 38587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas c.restoreToCount(restore); 38597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 38607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 38617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // If some views are animating, ItemDecorators are likely to move/change with them. 38627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Invalidate RecyclerView to re-draw decorators. This is still efficient because children's 38637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // display lists are not invalidated. 38647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!needsInvalidate && mItemAnimator != null && mItemDecorations.size() > 0 38657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && mItemAnimator.isRunning()) { 38667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas needsInvalidate = true; 38677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 38687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 38697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (needsInvalidate) { 38707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas postInvalidateOnAnimation(); 38717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 38727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 38737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 38747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 38757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onDraw(Canvas c) { 38767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super.onDraw(c); 38777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 38787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int count = mItemDecorations.size(); 38797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < count; i++) { 38807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemDecorations.get(i).onDraw(c, this, mState); 38817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 38827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 38837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 38847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 38857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 38867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return p instanceof LayoutParams && mLayout.checkLayoutParams((LayoutParams) p); 38877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 38887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 38897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 38907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas protected ViewGroup.LayoutParams generateDefaultLayoutParams() { 38917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout == null) { 38927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException("RecyclerView has no LayoutManager"); 38937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 38947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mLayout.generateDefaultLayoutParams(); 38957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 38967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 38977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 38987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { 38997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout == null) { 39007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException("RecyclerView has no LayoutManager"); 39017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 39027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mLayout.generateLayoutParams(getContext(), attrs); 39037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 39047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 39057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 39067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 39077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout == null) { 39087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException("RecyclerView has no LayoutManager"); 39097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 39107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mLayout.generateLayoutParams(p); 39117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 39127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 39137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 39147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns true if RecyclerView is currently running some animations. 39157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 39167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If you want to be notified when animations are finished, use 39177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link ItemAnimator#isRunning(ItemAnimator.ItemAnimatorFinishedListener)}. 39187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 39197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return True if there are some item animations currently running or waiting to be started. 39207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 39217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean isAnimating() { 39227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mItemAnimator != null && mItemAnimator.isRunning(); 39237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 39247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 39257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void saveOldPositions() { 39267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childCount = mChildHelper.getUnfilteredChildCount(); 39277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < childCount; i++) { 39287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = getChildViewHolderInt(mChildHelper.getUnfilteredChildAt(i)); 39297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG && holder.mPosition == -1 && !holder.isRemoved()) { 39307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException("view holder cannot have position -1 unless it" 39317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " is removed"); 39327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 39337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!holder.shouldIgnore()) { 39347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.saveOldPosition(); 39357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 39367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 39377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 39387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 39397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void clearOldPositions() { 39407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childCount = mChildHelper.getUnfilteredChildCount(); 39417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < childCount; i++) { 39427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = getChildViewHolderInt(mChildHelper.getUnfilteredChildAt(i)); 39437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!holder.shouldIgnore()) { 39447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.clearOldPosition(); 39457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 39467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 39477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.clearOldPositions(); 39487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 39497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 39507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void offsetPositionRecordsForMove(int from, int to) { 39517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childCount = mChildHelper.getUnfilteredChildCount(); 39527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int start, end, inBetweenOffset; 39537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (from < to) { 39547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas start = from; 39557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas end = to; 39567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas inBetweenOffset = -1; 39577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 39587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas start = to; 39597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas end = from; 39607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas inBetweenOffset = 1; 39617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 39627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 39637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < childCount; i++) { 39647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = getChildViewHolderInt(mChildHelper.getUnfilteredChildAt(i)); 39657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder == null || holder.mPosition < start || holder.mPosition > end) { 39667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas continue; 39677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 39687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 39697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.d(TAG, "offsetPositionRecordsForMove attached child " + i + " holder " 39707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + holder); 39717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 39727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.mPosition == from) { 39737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.offsetPosition(to - from, false); 39747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 39757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.offsetPosition(inBetweenOffset, false); 39767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 39777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 39787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mStructureChanged = true; 39797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 39807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.offsetPositionRecordsForMove(from, to); 39817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas requestLayout(); 39827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 39837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 39847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void offsetPositionRecordsForInsert(int positionStart, int itemCount) { 39857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childCount = mChildHelper.getUnfilteredChildCount(); 39867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < childCount; i++) { 39877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = getChildViewHolderInt(mChildHelper.getUnfilteredChildAt(i)); 39887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder != null && !holder.shouldIgnore() && holder.mPosition >= positionStart) { 39897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 39907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.d(TAG, "offsetPositionRecordsForInsert attached child " + i + " holder " 39917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + holder + " now at position " + (holder.mPosition + itemCount)); 39927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 39937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.offsetPosition(itemCount, false); 39947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mStructureChanged = true; 39957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 39967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 39977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.offsetPositionRecordsForInsert(positionStart, itemCount); 39987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas requestLayout(); 39997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 40007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 40017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void offsetPositionRecordsForRemove(int positionStart, int itemCount, 40027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean applyToPreLayout) { 40037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int positionEnd = positionStart + itemCount; 40047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childCount = mChildHelper.getUnfilteredChildCount(); 40057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < childCount; i++) { 40067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = getChildViewHolderInt(mChildHelper.getUnfilteredChildAt(i)); 40077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder != null && !holder.shouldIgnore()) { 40087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.mPosition >= positionEnd) { 40097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 40107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.d(TAG, "offsetPositionRecordsForRemove attached child " + i 40117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " holder " + holder + " now at position " 40127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + (holder.mPosition - itemCount)); 40137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 40147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.offsetPosition(-itemCount, applyToPreLayout); 40157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mStructureChanged = true; 40167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (holder.mPosition >= positionStart) { 40177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 40187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.d(TAG, "offsetPositionRecordsForRemove attached child " + i 40197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " holder " + holder + " now REMOVED"); 40207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 40217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.flagRemovedAndOffsetPosition(positionStart - 1, -itemCount, 40227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas applyToPreLayout); 40237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mStructureChanged = true; 40247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 40257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 40267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 40277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.offsetPositionRecordsForRemove(positionStart, itemCount, applyToPreLayout); 40287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas requestLayout(); 40297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 40307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 40317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 40327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Rebind existing views for the given range, or create as needed. 40337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 40347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param positionStart Adapter position to start at 40357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param itemCount Number of views that must explicitly be rebound 40367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 40377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void viewRangeUpdate(int positionStart, int itemCount, Object payload) { 40387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childCount = mChildHelper.getUnfilteredChildCount(); 40397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int positionEnd = positionStart + itemCount; 40407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 40417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < childCount; i++) { 40427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View child = mChildHelper.getUnfilteredChildAt(i); 40437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = getChildViewHolderInt(child); 40447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder == null || holder.shouldIgnore()) { 40457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas continue; 40467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 40477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.mPosition >= positionStart && holder.mPosition < positionEnd) { 40487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // We re-bind these view holders after pre-processing is complete so that 40497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // ViewHolders have their final positions assigned. 40507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.addFlags(ViewHolder.FLAG_UPDATE); 40517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.addChangePayload(payload); 40527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // lp cannot be null since we get ViewHolder from it. 40537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ((LayoutParams) child.getLayoutParams()).mInsetsDirty = true; 40547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 40557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 40567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.viewRangeUpdate(positionStart, itemCount); 40577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 40587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 40597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean canReuseUpdatedViewHolder(ViewHolder viewHolder) { 40607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mItemAnimator == null || mItemAnimator.canReuseUpdatedViewHolder(viewHolder, 40617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas viewHolder.getUnmodifiedPayloads()); 40627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 40637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 40647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 40657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 40667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Call this method to signal that *all* adapter content has changed (generally, because of 40677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * swapAdapter, or notifyDataSetChanged), and that once layout occurs, all attached items should 40687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * be discarded or animated. Note that this work is deferred because RecyclerView requires a 40697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * layout to resolve non-incremental changes to the data set. 40707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 40717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Attached items are labeled as position unknown, and may no longer be cached. 40727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 40737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * It is still possible for items to be prefetched while mDataSetHasChangedAfterLayout == true, 40747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * so calling this method *must* be associated with marking the cache invalid, so that the 40757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * only valid items that remain in the cache, once layout occurs, are prefetched items. 40767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 40777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void setDataSetChangedAfterLayout() { 40787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mDataSetHasChangedAfterLayout) { 40797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 40807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 40817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mDataSetHasChangedAfterLayout = true; 40827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childCount = mChildHelper.getUnfilteredChildCount(); 40837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < childCount; i++) { 40847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = getChildViewHolderInt(mChildHelper.getUnfilteredChildAt(i)); 40857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder != null && !holder.shouldIgnore()) { 40867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.addFlags(ViewHolder.FLAG_ADAPTER_POSITION_UNKNOWN); 40877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 40887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 40897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.setAdapterPositionsAsUnknown(); 40907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 40917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // immediately mark all views as invalid, so prefetched views can be 40927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // differentiated from views bound to previous data set - both in children, and cache 40937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas markKnownViewsInvalid(); 40947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 40957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 40967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 40977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Mark all known views as invalid. Used in response to a, "the whole world might have changed" 40987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * data change event. 40997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 41007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void markKnownViewsInvalid() { 41017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childCount = mChildHelper.getUnfilteredChildCount(); 41027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < childCount; i++) { 41037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = getChildViewHolderInt(mChildHelper.getUnfilteredChildAt(i)); 41047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder != null && !holder.shouldIgnore()) { 41057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.addFlags(ViewHolder.FLAG_UPDATE | ViewHolder.FLAG_INVALID); 41067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 41077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 41087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas markItemDecorInsetsDirty(); 41097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecycler.markKnownViewsInvalid(); 41107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 41117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 41127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 41137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Invalidates all ItemDecorations. If RecyclerView has item decorations, calling this method 41147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * will trigger a {@link #requestLayout()} call. 41157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 41167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void invalidateItemDecorations() { 41177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mItemDecorations.size() == 0) { 41187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 41197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 41207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout != null) { 41217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.assertNotInLayoutOrScroll("Cannot invalidate item decorations during a scroll" 41227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " or layout"); 41237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 41247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas markItemDecorInsetsDirty(); 41257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas requestLayout(); 41267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 41277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 41287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 41297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns true if the RecyclerView should attempt to preserve currently focused Adapter Item's 41307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * focus even if the View representing the Item is replaced during a layout calculation. 41317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 41327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * By default, this value is {@code true}. 41337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 41347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return True if the RecyclerView will try to preserve focused Item after a layout if it loses 41357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * focus. 41367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 41377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #setPreserveFocusAfterLayout(boolean) 41387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 41397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean getPreserveFocusAfterLayout() { 41407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mPreserveFocusAfterLayout; 41417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 41427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 41437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 41447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Set whether the RecyclerView should try to keep the same Item focused after a layout 41457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * calculation or not. 41467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 41477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Usually, LayoutManagers keep focused views visible before and after layout but sometimes, 41487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * views may lose focus during a layout calculation as their state changes or they are replaced 41497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * with another view due to type change or animation. In these cases, RecyclerView can request 41507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * focus on the new view automatically. 41517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 41527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param preserveFocusAfterLayout Whether RecyclerView should preserve focused Item during a 41537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * layout calculations. Defaults to true. 41547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 41557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #getPreserveFocusAfterLayout() 41567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 41577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setPreserveFocusAfterLayout(boolean preserveFocusAfterLayout) { 41587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPreserveFocusAfterLayout = preserveFocusAfterLayout; 41597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 41607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 41617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 41627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Retrieve the {@link ViewHolder} for the given child view. 41637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 41647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child of this RecyclerView to query for its ViewHolder 41657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The child view's ViewHolder 41667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 41677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public ViewHolder getChildViewHolder(View child) { 41687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewParent parent = child.getParent(); 41697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (parent != null && parent != this) { 41707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalArgumentException("View " + child + " is not a direct child of " 41717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + this); 41727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 41737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return getChildViewHolderInt(child); 41747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 41757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 41767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 41777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Traverses the ancestors of the given view and returns the item view that contains it and 41787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * also a direct child of the RecyclerView. This returned view can be used to get the 41797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ViewHolder by calling {@link #getChildViewHolder(View)}. 41807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 41817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param view The view that is a descendant of the RecyclerView. 41827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 41837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The direct child of the RecyclerView which contains the given view or null if the 41847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * provided view is not a descendant of this RecyclerView. 41857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 41867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #getChildViewHolder(View) 41877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #findContainingViewHolder(View) 41887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 41897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Nullable 41907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public View findContainingItemView(View view) { 41917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewParent parent = view.getParent(); 41927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas while (parent != null && parent != this && parent instanceof View) { 41937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas view = (View) parent; 41947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas parent = view.getParent(); 41957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 41967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return parent == this ? view : null; 41977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 41987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 41997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 42007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the ViewHolder that contains the given view. 42017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 42027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param view The view that is a descendant of the RecyclerView. 42037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 42047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The ViewHolder that contains the given view or null if the provided view is not a 42057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * descendant of this RecyclerView. 42067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 42077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Nullable 42087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public ViewHolder findContainingViewHolder(View view) { 42097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas View itemView = findContainingItemView(view); 42107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return itemView == null ? null : getChildViewHolder(itemView); 42117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 42127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 42137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 42147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static ViewHolder getChildViewHolderInt(View child) { 42157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (child == null) { 42167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 42177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 42187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return ((LayoutParams) child.getLayoutParams()).mViewHolder; 42197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 42207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 42217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 42227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @deprecated use {@link #getChildAdapterPosition(View)} or 42237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #getChildLayoutPosition(View)}. 42247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 42257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Deprecated 42267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getChildPosition(View child) { 42277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return getChildAdapterPosition(child); 42287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 42297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 42307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 42317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Return the adapter position that the given child view corresponds to. 42327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 42337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child View to query 42347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Adapter position corresponding to the given view or {@link #NO_POSITION} 42357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 42367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getChildAdapterPosition(View child) { 42377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = getChildViewHolderInt(child); 42387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return holder != null ? holder.getAdapterPosition() : NO_POSITION; 42397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 42407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 42417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 42427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Return the adapter position of the given child view as of the latest completed layout pass. 42437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 42447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This position may not be equal to Item's adapter position if there are pending changes 42457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * in the adapter which have not been reflected to the layout yet. 42467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 42477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child View to query 42487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Adapter position of the given View as of last layout pass or {@link #NO_POSITION} if 42497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the View is representing a removed item. 42507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 42517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getChildLayoutPosition(View child) { 42527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = getChildViewHolderInt(child); 42537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return holder != null ? holder.getLayoutPosition() : NO_POSITION; 42547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 42557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 42567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 42577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Return the stable item id that the given child view corresponds to. 42587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 42597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child View to query 42607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Item id corresponding to the given view or {@link #NO_ID} 42617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 42627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public long getChildItemId(View child) { 42637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mAdapter == null || !mAdapter.hasStableIds()) { 42647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return NO_ID; 42657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 42667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = getChildViewHolderInt(child); 42677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return holder != null ? holder.getItemId() : NO_ID; 42687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 42697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 42707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 42717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @deprecated use {@link #findViewHolderForLayoutPosition(int)} or 42727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #findViewHolderForAdapterPosition(int)} 42737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 42747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Deprecated 42757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public ViewHolder findViewHolderForPosition(int position) { 42767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return findViewHolderForPosition(position, false); 42777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 42787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 42797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 42807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Return the ViewHolder for the item in the given position of the data set as of the latest 42817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * layout pass. 42827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 42837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method checks only the children of RecyclerView. If the item at the given 42847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <code>position</code> is not laid out, it <em>will not</em> create a new one. 42857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 42867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that when Adapter contents change, ViewHolder positions are not updated until the 42877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * next layout calculation. If there are pending adapter updates, the return value of this 42887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * method may not match your adapter contents. You can use 42897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * #{@link ViewHolder#getAdapterPosition()} to get the current adapter position of a ViewHolder. 42907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 42917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * When the ItemAnimator is running a change animation, there might be 2 ViewHolders 42927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * with the same layout position representing the same Item. In this case, the updated 42937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ViewHolder will be returned. 42947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 42957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param position The position of the item in the data set of the adapter 42967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The ViewHolder at <code>position</code> or null if there is no such item 42977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 42987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public ViewHolder findViewHolderForLayoutPosition(int position) { 42997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return findViewHolderForPosition(position, false); 43007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 43017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 43027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 43037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Return the ViewHolder for the item in the given position of the data set. Unlike 43047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #findViewHolderForLayoutPosition(int)} this method takes into account any pending 43057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * adapter changes that may not be reflected to the layout yet. On the other hand, if 43067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link Adapter#notifyDataSetChanged()} has been called but the new layout has not been 43077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * calculated yet, this method will return <code>null</code> since the new positions of views 43087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * are unknown until the layout is calculated. 43097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 43107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method checks only the children of RecyclerView. If the item at the given 43117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <code>position</code> is not laid out, it <em>will not</em> create a new one. 43127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 43137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * When the ItemAnimator is running a change animation, there might be 2 ViewHolders 43147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * representing the same Item. In this case, the updated ViewHolder will be returned. 43157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 43167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param position The position of the item in the data set of the adapter 43177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The ViewHolder at <code>position</code> or null if there is no such item 43187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 43197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public ViewHolder findViewHolderForAdapterPosition(int position) { 43207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mDataSetHasChangedAfterLayout) { 43217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 43227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 43237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childCount = mChildHelper.getUnfilteredChildCount(); 43247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // hidden VHs are not preferred but if that is the only one we find, we rather return it 43257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder hidden = null; 43267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < childCount; i++) { 43277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = getChildViewHolderInt(mChildHelper.getUnfilteredChildAt(i)); 43287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder != null && !holder.isRemoved() 43297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && getAdapterPositionFor(holder) == position) { 43307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mChildHelper.isHidden(holder.itemView)) { 43317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas hidden = holder; 43327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 43337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return holder; 43347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 43357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 43367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 43377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return hidden; 43387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 43397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 43407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder findViewHolderForPosition(int position, boolean checkNewPosition) { 43417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childCount = mChildHelper.getUnfilteredChildCount(); 43427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder hidden = null; 43437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < childCount; i++) { 43447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = getChildViewHolderInt(mChildHelper.getUnfilteredChildAt(i)); 43457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder != null && !holder.isRemoved()) { 43467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (checkNewPosition) { 43477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.mPosition != position) { 43487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas continue; 43497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 43507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (holder.getLayoutPosition() != position) { 43517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas continue; 43527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 43537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mChildHelper.isHidden(holder.itemView)) { 43547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas hidden = holder; 43557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 43567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return holder; 43577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 43587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 43597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 43607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // This method should not query cached views. It creates a problem during adapter updates 43617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // when we are dealing with already laid out views. Also, for the public method, it is more 43627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // reasonable to return null if position is not laid out. 43637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return hidden; 43647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 43657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 43667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 43677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Return the ViewHolder for the item with the given id. The RecyclerView must 43687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * use an Adapter with {@link Adapter#setHasStableIds(boolean) stableIds} to 43697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * return a non-null value. 43707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 43717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method checks only the children of RecyclerView. If the item with the given 43727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <code>id</code> is not laid out, it <em>will not</em> create a new one. 43737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 43747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * When the ItemAnimator is running a change animation, there might be 2 ViewHolders with the 43757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * same id. In this case, the updated ViewHolder will be returned. 43767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 43777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param id The id for the requested item 43787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The ViewHolder with the given <code>id</code> or null if there is no such item 43797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 43807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public ViewHolder findViewHolderForItemId(long id) { 43817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mAdapter == null || !mAdapter.hasStableIds()) { 43827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 43837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 43847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childCount = mChildHelper.getUnfilteredChildCount(); 43857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder hidden = null; 43867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < childCount; i++) { 43877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = getChildViewHolderInt(mChildHelper.getUnfilteredChildAt(i)); 43887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder != null && !holder.isRemoved() && holder.getItemId() == id) { 43897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mChildHelper.isHidden(holder.itemView)) { 43907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas hidden = holder; 43917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 43927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return holder; 43937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 43947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 43957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 43967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return hidden; 43977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 43987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 43997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 44007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Find the topmost view under the given point. 44017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 44027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param x Horizontal position in pixels to search 44037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param y Vertical position in pixels to search 44047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The child view under (x, y) or null if no matching child is found 44057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 44067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public View findChildViewUnder(float x, float y) { 44077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int count = mChildHelper.getChildCount(); 44087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = count - 1; i >= 0; i--) { 44097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View child = mChildHelper.getChildAt(i); 44107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final float translationX = child.getTranslationX(); 44117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final float translationY = child.getTranslationY(); 44127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (x >= child.getLeft() + translationX 44137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && x <= child.getRight() + translationX 44147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && y >= child.getTop() + translationY 44157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && y <= child.getBottom() + translationY) { 44167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return child; 44177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 44187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 44197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 44207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 44217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 44227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 44237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean drawChild(Canvas canvas, View child, long drawingTime) { 44247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return super.drawChild(canvas, child, drawingTime); 44257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 44267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 44277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 44287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Offset the bounds of all child views by <code>dy</code> pixels. 44297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Useful for implementing simple scrolling in {@link LayoutManager LayoutManagers}. 44307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 44317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dy Vertical pixel offset to apply to the bounds of all child views 44327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 44337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void offsetChildrenVertical(int dy) { 44347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childCount = mChildHelper.getChildCount(); 44357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < childCount; i++) { 44367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChildHelper.getChildAt(i).offsetTopAndBottom(dy); 44377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 44387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 44397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 44407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 44417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when an item view is attached to this RecyclerView. 44427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 44437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Subclasses of RecyclerView may want to perform extra bookkeeping or modifications 44447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * of child views as they become attached. This will be called before a 44457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link LayoutManager} measures or lays out the view and is a good time to perform these 44467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * changes.</p> 44477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 44487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child view that is now attached to this RecyclerView and its associated window 44497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 44507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onChildAttachedToWindow(View child) { 44517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 44527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 44537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 44547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when an item view is detached from this RecyclerView. 44557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 44567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Subclasses of RecyclerView may want to perform extra bookkeeping or modifications 44577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * of child views as they become detached. This will be called as a 44587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link LayoutManager} fully detaches the child view from the parent and its window.</p> 44597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 44607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child view that is now detached from this RecyclerView and its associated window 44617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 44627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onChildDetachedFromWindow(View child) { 44637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 44647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 44657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 44667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Offset the bounds of all child views by <code>dx</code> pixels. 44677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Useful for implementing simple scrolling in {@link LayoutManager LayoutManagers}. 44687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 44697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dx Horizontal pixel offset to apply to the bounds of all child views 44707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 44717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void offsetChildrenHorizontal(int dx) { 44727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childCount = mChildHelper.getChildCount(); 44737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < childCount; i++) { 44747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChildHelper.getChildAt(i).offsetLeftAndRight(dx); 44757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 44767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 44777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 44787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 44797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the bounds of the view including its decoration and margins. 44807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 44817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param view The view element to check 44827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param outBounds A rect that will receive the bounds of the element including its 44837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * decoration and margins. 44847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 44857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void getDecoratedBoundsWithMargins(View view, Rect outBounds) { 44867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas getDecoratedBoundsWithMarginsInt(view, outBounds); 44877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 44887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 44897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static void getDecoratedBoundsWithMarginsInt(View view, Rect outBounds) { 44907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 44917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final Rect insets = lp.mDecorInsets; 44927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas outBounds.set(view.getLeft() - insets.left - lp.leftMargin, 44937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas view.getTop() - insets.top - lp.topMargin, 44947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas view.getRight() + insets.right + lp.rightMargin, 44957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas view.getBottom() + insets.bottom + lp.bottomMargin); 44967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 44977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 44987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Rect getItemDecorInsetsForChild(View child) { 44997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 45007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!lp.mInsetsDirty) { 45017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return lp.mDecorInsets; 45027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 45037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 45047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mState.isPreLayout() && (lp.isItemChanged() || lp.isViewInvalid())) { 45057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // changed/invalid items should not be updated until they are rebound. 45067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return lp.mDecorInsets; 45077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 45087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final Rect insets = lp.mDecorInsets; 45097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas insets.set(0, 0, 0, 0); 45107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int decorCount = mItemDecorations.size(); 45117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < decorCount; i++) { 45127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTempRect.set(0, 0, 0, 0); 45137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemDecorations.get(i).getItemOffsets(mTempRect, child, this, mState); 45147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas insets.left += mTempRect.left; 45157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas insets.top += mTempRect.top; 45167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas insets.right += mTempRect.right; 45177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas insets.bottom += mTempRect.bottom; 45187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 45197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas lp.mInsetsDirty = false; 45207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return insets; 45217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 45227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 45237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 45247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when the scroll position of this RecyclerView changes. Subclasses should use 45257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * this method to respond to scrolling within the adapter's data set instead of an explicit 45267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * listener. 45277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 45287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>This method will always be invoked before listeners. If a subclass needs to perform 45297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * any additional upkeep or bookkeeping after scrolling but before listeners run, 45307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * this is a good place to do so.</p> 45317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 45327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>This differs from {@link View#onScrollChanged(int, int, int, int)} in that it receives 45337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the distance scrolled in either direction within the adapter's data set instead of absolute 45347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * scroll coordinates. Since RecyclerView cannot compute the absolute scroll position from 45357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * any arbitrary point in the data set, <code>onScrollChanged</code> will always receive 45367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the current {@link View#getScrollX()} and {@link View#getScrollY()} values which 45377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * do not correspond to the data set scroll position. However, some subclasses may choose 45387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to use these fields as special offsets.</p> 45397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 45407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dx horizontal distance scrolled in pixels 45417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dy vertical distance scrolled in pixels 45427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 45437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onScrolled(int dx, int dy) { 45447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Do nothing 45457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 45467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 45477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void dispatchOnScrolled(int hresult, int vresult) { 45487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mDispatchScrollCounter++; 45497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Pass the current scrollX/scrollY values; no actual change in these properties occurred 45507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // but some general-purpose code may choose to respond to changes this way. 45517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int scrollX = getScrollX(); 45527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int scrollY = getScrollY(); 45537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onScrollChanged(scrollX, scrollY, scrollX, scrollY); 45547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 45557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Pass the real deltas to onScrolled, the RecyclerView-specific method. 45567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onScrolled(hresult, vresult); 45577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 45587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Invoke listeners last. Subclassed view methods always handle the event first. 45597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // All internal state is consistent by the time listeners are invoked. 45607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mScrollListener != null) { 45617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScrollListener.onScrolled(this, hresult, vresult); 45627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 45637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mScrollListeners != null) { 45647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = mScrollListeners.size() - 1; i >= 0; i--) { 45657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScrollListeners.get(i).onScrolled(this, hresult, vresult); 45667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 45677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 45687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mDispatchScrollCounter--; 45697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 45707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 45717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 45727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when the scroll state of this RecyclerView changes. Subclasses should use this 45737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * method to respond to state changes instead of an explicit listener. 45747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 45757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>This method will always be invoked before listeners, but after the LayoutManager 45767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * responds to the scroll state change.</p> 45777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 45787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state the new scroll state, one of {@link #SCROLL_STATE_IDLE}, 45797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #SCROLL_STATE_DRAGGING} or {@link #SCROLL_STATE_SETTLING} 45807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 45817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onScrollStateChanged(int state) { 45827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Do nothing 45837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 45847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 45857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void dispatchOnScrollStateChanged(int state) { 45867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Let the LayoutManager go first; this allows it to bring any properties into 45877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // a consistent state before the RecyclerView subclass responds. 45887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout != null) { 45897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayout.onScrollStateChanged(state); 45907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 45917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 45927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Let the RecyclerView subclass handle this event next; any LayoutManager property 45937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // changes will be reflected by this time. 45947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onScrollStateChanged(state); 45957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 45967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Listeners go last. All other internal state is consistent by this point. 45977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mScrollListener != null) { 45987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScrollListener.onScrollStateChanged(this, state); 45997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 46007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mScrollListeners != null) { 46017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = mScrollListeners.size() - 1; i >= 0; i--) { 46027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScrollListeners.get(i).onScrollStateChanged(this, state); 46037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 46047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 46057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 46067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 46077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 46087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns whether there are pending adapter updates which are not yet applied to the layout. 46097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 46107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If this method returns <code>true</code>, it means that what user is currently seeing may not 46117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * reflect them adapter contents (depending on what has changed). 46127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * You may use this information to defer or cancel some operations. 46137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 46147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method returns true if RecyclerView has not yet calculated the first layout after it is 46157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * attached to the Window or the Adapter has been replaced. 46167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 46177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return True if there are some adapter updates which are not yet reflected to layout or false 46187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * if layout is up to date. 46197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 46207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean hasPendingAdapterUpdates() { 46217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return !mFirstLayoutComplete || mDataSetHasChangedAfterLayout 46227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || mAdapterHelper.hasPendingUpdates(); 46237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 46247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 46257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas class ViewFlinger implements Runnable { 46267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mLastFlingX; 46277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mLastFlingY; 46287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private OverScroller mScroller; 46297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Interpolator mInterpolator = sQuinticInterpolator; 46307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 46317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 46327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // When set to true, postOnAnimation callbacks are delayed until the run method completes 46337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private boolean mEatRunOnAnimationRequest = false; 46347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 46357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Tracks if postAnimationCallback should be re-attached when it is done 46367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private boolean mReSchedulePostAnimationCallback = false; 46377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 46387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewFlinger() { 46397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScroller = new OverScroller(getContext(), sQuinticInterpolator); 46407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 46417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 46427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 46437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void run() { 46447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mLayout == null) { 46457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas stop(); 46467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; // no layout, cannot scroll. 46477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 46487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas disableRunOnAnimationRequests(); 46497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas consumePendingUpdateOperations(); 46507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // keep a local reference so that if it is changed during onAnimation method, it won't 46517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // cause unexpected behaviors 46527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final OverScroller scroller = mScroller; 46537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final SmoothScroller smoothScroller = mLayout.mSmoothScroller; 46547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (scroller.computeScrollOffset()) { 46557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int x = scroller.getCurrX(); 46567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int y = scroller.getCurrY(); 46577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int dx = x - mLastFlingX; 46587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int dy = y - mLastFlingY; 46597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int hresult = 0; 46607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int vresult = 0; 46617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLastFlingX = x; 46627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLastFlingY = y; 46637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int overscrollX = 0, overscrollY = 0; 46647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mAdapter != null) { 46657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas eatRequestLayout(); 46667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onEnterLayoutOrScroll(); 46677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Trace.beginSection(TRACE_SCROLL_TAG); 46687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (dx != 0) { 46697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas hresult = mLayout.scrollHorizontallyBy(dx, mRecycler, mState); 46707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas overscrollX = dx - hresult; 46717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 46727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (dy != 0) { 46737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas vresult = mLayout.scrollVerticallyBy(dy, mRecycler, mState); 46747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas overscrollY = dy - vresult; 46757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 46767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Trace.endSection(); 46777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas repositionShadowingViews(); 46787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 46797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onExitLayoutOrScroll(); 46807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resumeRequestLayout(false); 46817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 46827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (smoothScroller != null && !smoothScroller.isPendingInitialRun() 46837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && smoothScroller.isRunning()) { 46847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int adapterSize = mState.getItemCount(); 46857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (adapterSize == 0) { 46867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas smoothScroller.stop(); 46877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (smoothScroller.getTargetPosition() >= adapterSize) { 46887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas smoothScroller.setTargetPosition(adapterSize - 1); 46897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas smoothScroller.onAnimation(dx - overscrollX, dy - overscrollY); 46907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 46917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas smoothScroller.onAnimation(dx - overscrollX, dy - overscrollY); 46927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 46937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 46947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 46957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!mItemDecorations.isEmpty()) { 46967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas invalidate(); 46977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 46987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (getOverScrollMode() != View.OVER_SCROLL_NEVER) { 46997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas considerReleasingGlowsOnScroll(dx, dy); 47007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (overscrollX != 0 || overscrollY != 0) { 47027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int vel = (int) scroller.getCurrVelocity(); 47037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 47047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int velX = 0; 47057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (overscrollX != x) { 47067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas velX = overscrollX < 0 ? -vel : overscrollX > 0 ? vel : 0; 47077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 47097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int velY = 0; 47107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (overscrollY != y) { 47117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas velY = overscrollY < 0 ? -vel : overscrollY > 0 ? vel : 0; 47127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 47147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (getOverScrollMode() != View.OVER_SCROLL_NEVER) { 47157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas absorbGlows(velX, velY); 47167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if ((velX != 0 || overscrollX == x || scroller.getFinalX() == 0) 47187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && (velY != 0 || overscrollY == y || scroller.getFinalY() == 0)) { 47197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas scroller.abortAnimation(); 47207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (hresult != 0 || vresult != 0) { 47237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchOnScrolled(hresult, vresult); 47247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 47267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!awakenScrollBars()) { 47277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas invalidate(); 47287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 47307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean fullyConsumedVertical = dy != 0 && mLayout.canScrollVertically() 47317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && vresult == dy; 47327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean fullyConsumedHorizontal = dx != 0 && mLayout.canScrollHorizontally() 47337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && hresult == dx; 47347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean fullyConsumedAny = (dx == 0 && dy == 0) || fullyConsumedHorizontal 47357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || fullyConsumedVertical; 47367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 47377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (scroller.isFinished() || !fullyConsumedAny) { 47387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setScrollState(SCROLL_STATE_IDLE); // setting state to idle will stop this. 47397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (ALLOW_THREAD_GAP_WORK) { 47407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPrefetchRegistry.clearPrefetchPositions(); 47417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 47437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas postOnAnimation(); 47447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mGapWorker != null) { 47457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mGapWorker.postFromTraversal(RecyclerView.this, dx, dy); 47467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // call this after the onAnimation is complete not to have inconsistent callbacks etc. 47507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (smoothScroller != null) { 47517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (smoothScroller.isPendingInitialRun()) { 47527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas smoothScroller.onAnimation(0, 0); 47537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!mReSchedulePostAnimationCallback) { 47557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas smoothScroller.stop(); //stop if it does not trigger any scroll 47567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas enableRunOnAnimationRequests(); 47597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 47617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void disableRunOnAnimationRequests() { 47627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mReSchedulePostAnimationCallback = false; 47637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mEatRunOnAnimationRequest = true; 47647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 47667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void enableRunOnAnimationRequests() { 47677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mEatRunOnAnimationRequest = false; 47687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mReSchedulePostAnimationCallback) { 47697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas postOnAnimation(); 47707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 47737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void postOnAnimation() { 47747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mEatRunOnAnimationRequest) { 47757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mReSchedulePostAnimationCallback = true; 47767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 47777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas removeCallbacks(this); 47787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas RecyclerView.this.postOnAnimation(this); 47797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 47827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void fling(int velocityX, int velocityY) { 47837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setScrollState(SCROLL_STATE_SETTLING); 47847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLastFlingX = mLastFlingY = 0; 47857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScroller.fling(0, 0, velocityX, velocityY, 47867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE); 47877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas postOnAnimation(); 47887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 47907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void smoothScrollBy(int dx, int dy) { 47917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas smoothScrollBy(dx, dy, 0, 0); 47927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 47947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void smoothScrollBy(int dx, int dy, int vx, int vy) { 47957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas smoothScrollBy(dx, dy, computeScrollDuration(dx, dy, vx, vy)); 47967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 47977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 47987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private float distanceInfluenceForSnapDuration(float f) { 47997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas f -= 0.5f; // center the values about 0. 48007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas f *= 0.3f * Math.PI / 2.0f; 48017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return (float) Math.sin(f); 48027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 48037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 48047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int computeScrollDuration(int dx, int dy, int vx, int vy) { 48057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int absDx = Math.abs(dx); 48067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int absDy = Math.abs(dy); 48077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean horizontal = absDx > absDy; 48087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int velocity = (int) Math.sqrt(vx * vx + vy * vy); 48097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int delta = (int) Math.sqrt(dx * dx + dy * dy); 48107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int containerSize = horizontal ? getWidth() : getHeight(); 48117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int halfContainerSize = containerSize / 2; 48127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final float distanceRatio = Math.min(1.f, 1.f * delta / containerSize); 48137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final float distance = halfContainerSize + halfContainerSize 48147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * distanceInfluenceForSnapDuration(distanceRatio); 48157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 48167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int duration; 48177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (velocity > 0) { 48187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas duration = 4 * Math.round(1000 * Math.abs(distance / velocity)); 48197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 48207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas float absDelta = (float) (horizontal ? absDx : absDy); 48217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas duration = (int) (((absDelta / containerSize) + 1) * 300); 48227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 48237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return Math.min(duration, MAX_SCROLL_DURATION); 48247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 48257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 48267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void smoothScrollBy(int dx, int dy, int duration) { 48277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas smoothScrollBy(dx, dy, duration, sQuinticInterpolator); 48287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 48297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 48307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void smoothScrollBy(int dx, int dy, Interpolator interpolator) { 48317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas smoothScrollBy(dx, dy, computeScrollDuration(dx, dy, 0, 0), 48327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas interpolator == null ? sQuinticInterpolator : interpolator); 48337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 48347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 48357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void smoothScrollBy(int dx, int dy, int duration, Interpolator interpolator) { 48367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mInterpolator != interpolator) { 48377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mInterpolator = interpolator; 48387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScroller = new OverScroller(getContext(), interpolator); 48397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 48407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setScrollState(SCROLL_STATE_SETTLING); 48417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLastFlingX = mLastFlingY = 0; 48427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScroller.startScroll(0, 0, dx, dy, duration); 48437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas postOnAnimation(); 48447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 48457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 48467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void stop() { 48477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas removeCallbacks(this); 48487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScroller.abortAnimation(); 48497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 48507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 48517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 48527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 48537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void repositionShadowingViews() { 48547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Fix up shadow views used by change animations 48557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int count = mChildHelper.getChildCount(); 48567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < count; i++) { 48577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas View view = mChildHelper.getChildAt(i); 48587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder holder = getChildViewHolder(view); 48597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder != null && holder.mShadowingHolder != null) { 48607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas View shadowingView = holder.mShadowingHolder.itemView; 48617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int left = view.getLeft(); 48627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int top = view.getTop(); 48637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (left != shadowingView.getLeft() || top != shadowingView.getTop()) { 48647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas shadowingView.layout(left, top, 48657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas left + shadowingView.getWidth(), 48667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas top + shadowingView.getHeight()); 48677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 48687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 48697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 48707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 48717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 48727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private class RecyclerViewDataObserver extends AdapterDataObserver { 48737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas RecyclerViewDataObserver() { 48747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 48757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 48767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 48777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onChanged() { 48787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas assertNotInLayoutOrScroll(null); 48797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mState.mStructureChanged = true; 48807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 48817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setDataSetChangedAfterLayout(); 48827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!mAdapterHelper.hasPendingUpdates()) { 48837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas requestLayout(); 48847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 48857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 48867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 48877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 48887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onItemRangeChanged(int positionStart, int itemCount, Object payload) { 48897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas assertNotInLayoutOrScroll(null); 48907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mAdapterHelper.onItemRangeChanged(positionStart, itemCount, payload)) { 48917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas triggerUpdateProcessor(); 48927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 48937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 48947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 48957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 48967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onItemRangeInserted(int positionStart, int itemCount) { 48977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas assertNotInLayoutOrScroll(null); 48987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mAdapterHelper.onItemRangeInserted(positionStart, itemCount)) { 48997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas triggerUpdateProcessor(); 49007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 49017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 49027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 49037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 49047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onItemRangeRemoved(int positionStart, int itemCount) { 49057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas assertNotInLayoutOrScroll(null); 49067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mAdapterHelper.onItemRangeRemoved(positionStart, itemCount)) { 49077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas triggerUpdateProcessor(); 49087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 49097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 49107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 49117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 49127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { 49137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas assertNotInLayoutOrScroll(null); 49147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mAdapterHelper.onItemRangeMoved(fromPosition, toPosition, itemCount)) { 49157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas triggerUpdateProcessor(); 49167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 49177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 49187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 49197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void triggerUpdateProcessor() { 49207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (POST_UPDATES_ON_ANIMATION && mHasFixedSize && mIsAttached) { 49217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas RecyclerView.this.postOnAnimation(mUpdateChildViewsRunnable); 49227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 49237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAdapterUpdateDuringMeasure = true; 49247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas requestLayout(); 49257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 49267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 49277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 49287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 49297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 49307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecycledViewPool lets you share Views between multiple RecyclerViews. 49317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 49327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If you want to recycle views across RecyclerViews, create an instance of RecycledViewPool 49337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * and use {@link RecyclerView#setRecycledViewPool(RecycledViewPool)}. 49347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 49357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView automatically creates a pool for itself if you don't provide one. 49367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 49377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 49387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static class RecycledViewPool { 49397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private static final int DEFAULT_MAX_SCRAP = 5; 49407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 49417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 49427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Tracks both pooled holders, as well as create/bind timing metadata for the given type. 49437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 49447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that this tracks running averages of create/bind time across all RecyclerViews 49457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * (and, indirectly, Adapters) that use this pool. 49467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 49477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 1) This enables us to track average create and bind times across multiple adapters. Even 49487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * though create (and especially bind) may behave differently for different Adapter 49497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * subclasses, sharing the pool is a strong signal that they'll perform similarly, per type. 49507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 49517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 2) If {@link #willBindInTime(int, long, long)} returns false for one view, it will return 49527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * false for all other views of its type for the same deadline. This prevents items 49537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * constructed by {@link GapWorker} prefetch from being bound to a lower priority prefetch. 49547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 49557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static class ScrapData { 49567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ArrayList<ViewHolder> mScrapHeap = new ArrayList<>(); 49577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int mMaxScrap = DEFAULT_MAX_SCRAP; 49587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas long mCreateRunningAverageNs = 0; 49597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas long mBindRunningAverageNs = 0; 49607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 49617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas SparseArray<ScrapData> mScrap = new SparseArray<>(); 49627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 49637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mAttachCount = 0; 49647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 49657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void clear() { 49667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < mScrap.size(); i++) { 49677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ScrapData data = mScrap.valueAt(i); 49687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas data.mScrapHeap.clear(); 49697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 49707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 49717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 49727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setMaxRecycledViews(int viewType, int max) { 49737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ScrapData scrapData = getScrapDataForType(viewType); 49747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas scrapData.mMaxScrap = max; 49757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ArrayList<ViewHolder> scrapHeap = scrapData.mScrapHeap; 49767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (scrapHeap != null) { 49777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas while (scrapHeap.size() > max) { 49787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas scrapHeap.remove(scrapHeap.size() - 1); 49797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 49807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 49817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 49827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 49837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 49847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the current number of Views held by the RecycledViewPool of the given view type. 49857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 49867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getRecycledViewCount(int viewType) { 49877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return getScrapDataForType(viewType).mScrapHeap.size(); 49887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 49897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 49907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public ViewHolder getRecycledView(int viewType) { 49917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ScrapData scrapData = mScrap.get(viewType); 49927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (scrapData != null && !scrapData.mScrapHeap.isEmpty()) { 49937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ArrayList<ViewHolder> scrapHeap = scrapData.mScrapHeap; 49947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return scrapHeap.remove(scrapHeap.size() - 1); 49957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 49967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 49977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 49987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 49997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int size() { 50007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int count = 0; 50017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < mScrap.size(); i++) { 50027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ArrayList<ViewHolder> viewHolders = mScrap.valueAt(i).mScrapHeap; 50037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (viewHolders != null) { 50047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas count += viewHolders.size(); 50057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 50067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 50077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return count; 50087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 50097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 50107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void putRecycledView(ViewHolder scrap) { 50117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int viewType = scrap.getItemViewType(); 50127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ArrayList scrapHeap = getScrapDataForType(viewType).mScrapHeap; 50137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mScrap.get(viewType).mMaxScrap <= scrapHeap.size()) { 50147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 50157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 50167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG && scrapHeap.contains(scrap)) { 50177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalArgumentException("this scrap item already exists"); 50187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 50197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas scrap.resetInternal(); 50207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas scrapHeap.add(scrap); 50217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 50227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 50237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas long runningAverage(long oldAverage, long newValue) { 50247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (oldAverage == 0) { 50257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return newValue; 50267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 50277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return (oldAverage / 4 * 3) + (newValue / 4); 50287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 50297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 50307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void factorInCreateTime(int viewType, long createTimeNs) { 50317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ScrapData scrapData = getScrapDataForType(viewType); 50327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas scrapData.mCreateRunningAverageNs = runningAverage( 50337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas scrapData.mCreateRunningAverageNs, createTimeNs); 50347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 50357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 50367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void factorInBindTime(int viewType, long bindTimeNs) { 50377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ScrapData scrapData = getScrapDataForType(viewType); 50387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas scrapData.mBindRunningAverageNs = runningAverage( 50397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas scrapData.mBindRunningAverageNs, bindTimeNs); 50407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 50417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 50427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean willCreateInTime(int viewType, long approxCurrentNs, long deadlineNs) { 50437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas long expectedDurationNs = getScrapDataForType(viewType).mCreateRunningAverageNs; 50447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return expectedDurationNs == 0 || (approxCurrentNs + expectedDurationNs < deadlineNs); 50457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 50467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 50477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean willBindInTime(int viewType, long approxCurrentNs, long deadlineNs) { 50487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas long expectedDurationNs = getScrapDataForType(viewType).mBindRunningAverageNs; 50497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return expectedDurationNs == 0 || (approxCurrentNs + expectedDurationNs < deadlineNs); 50507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 50517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 50527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void attach(Adapter adapter) { 50537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAttachCount++; 50547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 50557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 50567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void detach() { 50577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAttachCount--; 50587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 50597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 50607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 50617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 50627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Detaches the old adapter and attaches the new one. 50637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 50647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecycledViewPool will clear its cache if it has only one adapter attached and the new 50657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * adapter uses a different ViewHolder than the oldAdapter. 50667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 50677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param oldAdapter The previous adapter instance. Will be detached. 50687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param newAdapter The new adapter instance. Will be attached. 50697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param compatibleWithPrevious True if both oldAdapter and newAdapter are using the same 50707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ViewHolder and view types. 50717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 50727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void onAdapterChanged(Adapter oldAdapter, Adapter newAdapter, 50737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean compatibleWithPrevious) { 50747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (oldAdapter != null) { 50757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas detach(); 50767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 50777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!compatibleWithPrevious && mAttachCount == 0) { 50787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas clear(); 50797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 50807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (newAdapter != null) { 50817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas attach(newAdapter); 50827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 50837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 50847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 50857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private ScrapData getScrapDataForType(int viewType) { 50867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ScrapData scrapData = mScrap.get(viewType); 50877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (scrapData == null) { 50887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas scrapData = new ScrapData(); 50897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScrap.put(viewType, scrapData); 50907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 50917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return scrapData; 50927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 50937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 50947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 50957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 50967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Utility method for finding an internal RecyclerView, if present 50977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 50987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Nullable 50997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static RecyclerView findNestedRecyclerView(@NonNull View view) { 51007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!(view instanceof ViewGroup)) { 51017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 51027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 51037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (view instanceof RecyclerView) { 51047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return (RecyclerView) view; 51057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 51067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewGroup parent = (ViewGroup) view; 51077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int count = parent.getChildCount(); 51087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < count; i++) { 51097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View child = parent.getChildAt(i); 51107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final RecyclerView descendant = findNestedRecyclerView(child); 51117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (descendant != null) { 51127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return descendant; 51137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 51147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 51157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 51167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 51177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 51187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 51197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Utility method for clearing holder's internal RecyclerView, if present 51207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 51217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static void clearNestedRecyclerViewIfNotNested(@NonNull ViewHolder holder) { 51227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.mNestedRecyclerView != null) { 51237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas View item = holder.mNestedRecyclerView.get(); 51247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas while (item != null) { 51257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (item == holder.itemView) { 51267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; // match found, don't need to clear 51277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 51287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 51297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewParent parent = item.getParent(); 51307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (parent instanceof View) { 51317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas item = (View) parent; 51327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 51337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas item = null; 51347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 51357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 51367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.mNestedRecyclerView = null; // not nested 51377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 51387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 51397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 51407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 51417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Time base for deadline-aware work scheduling. Overridable for testing. 51427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 51437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Will return 0 to avoid cost of System.nanoTime where deadline-aware work scheduling 51447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * isn't relevant. 51457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 51467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas long getNanoTime() { 51477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (ALLOW_THREAD_GAP_WORK) { 51487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return System.nanoTime(); 51497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 51507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return 0; 51517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 51527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 51537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 51547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 51557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * A Recycler is responsible for managing scrapped or detached item views for reuse. 51567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 51577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>A "scrapped" view is a view that is still attached to its parent RecyclerView but 51587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * that has been marked for removal or reuse.</p> 51597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 51607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Typical use of a Recycler by a {@link LayoutManager} will be to obtain views for 51617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * an adapter's data set representing the data at a given position or item ID. 51627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If the view to be reused is considered "dirty" the adapter will be asked to rebind it. 51637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If not, the view can be quickly reused by the LayoutManager with no further work. 51647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Clean views that have not {@link android.view.View#isLayoutRequested() requested layout} 51657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * may be repositioned by a LayoutManager without remeasurement.</p> 51667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 51677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final class Recycler { 51687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ArrayList<ViewHolder> mAttachedScrap = new ArrayList<>(); 51697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ArrayList<ViewHolder> mChangedScrap = null; 51707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 51717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ArrayList<ViewHolder> mCachedViews = new ArrayList<ViewHolder>(); 51727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 51737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private final List<ViewHolder> 51747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mUnmodifiableAttachedScrap = Collections.unmodifiableList(mAttachedScrap); 51757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 51767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mRequestedCacheMax = DEFAULT_CACHE_SIZE; 51777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int mViewCacheMax = DEFAULT_CACHE_SIZE; 51787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 51797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas RecycledViewPool mRecyclerPool; 51807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 51817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private ViewCacheExtension mViewCacheExtension; 51827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 51837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final int DEFAULT_CACHE_SIZE = 2; 51847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 51857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 51867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Clear scrap views out of this recycler. Detached views contained within a 51877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * recycled view pool will remain. 51887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 51897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void clear() { 51907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAttachedScrap.clear(); 51917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recycleAndClearCachedViews(); 51927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 51937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 51947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 51957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Set the maximum number of detached, valid views we should retain for later use. 51967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 51977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param viewCount Number of views to keep before sending views to the shared pool 51987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 51997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setViewCacheSize(int viewCount) { 52007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRequestedCacheMax = viewCount; 52017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas updateViewCacheSize(); 52027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 52037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 52047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void updateViewCacheSize() { 52057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int extraCache = mLayout != null ? mLayout.mPrefetchMaxCountObserved : 0; 52067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mViewCacheMax = mRequestedCacheMax + extraCache; 52077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 52087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // first, try the views that can be recycled 52097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = mCachedViews.size() - 1; 52107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas i >= 0 && mCachedViews.size() > mViewCacheMax; i--) { 52117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recycleCachedViewAt(i); 52127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 52137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 52147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 52157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 52167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns an unmodifiable list of ViewHolders that are currently in the scrap list. 52177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 52187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return List of ViewHolders in the scrap list. 52197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 52207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public List<ViewHolder> getScrapList() { 52217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mUnmodifiableAttachedScrap; 52227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 52237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 52247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 52257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Helper method for getViewForPosition. 52267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 52277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Checks whether a given view holder can be used for the provided position. 52287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 52297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param holder ViewHolder 52307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if ViewHolder matches the provided position, false otherwise 52317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 52327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean validateViewHolderForOffsetPosition(ViewHolder holder) { 52337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // if it is a removed holder, nothing to verify since we cannot ask adapter anymore 52347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // if it is not removed, verify the type and id. 52357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.isRemoved()) { 52367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG && !mState.isPreLayout()) { 52377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException("should not receive a removed view unless it" 52387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " is pre layout"); 52397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 52407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mState.isPreLayout(); 52417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 52427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.mPosition < 0 || holder.mPosition >= mAdapter.getItemCount()) { 52437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IndexOutOfBoundsException("Inconsistency detected. Invalid view holder " 52447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "adapter position" + holder); 52457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 52467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!mState.isPreLayout()) { 52477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // don't check type if it is pre-layout. 52487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int type = mAdapter.getItemViewType(holder.mPosition); 52497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (type != holder.getItemViewType()) { 52507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 52517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 52527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 52537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mAdapter.hasStableIds()) { 52547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return holder.getItemId() == mAdapter.getItemId(holder.mPosition); 52557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 52567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return true; 52577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 52587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 52597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 52607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Attempts to bind view, and account for relevant timing information. If 52617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * deadlineNs != FOREVER_NS, this method may fail to bind, and return false. 52627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 52637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param holder Holder to be bound. 52647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param offsetPosition Position of item to be bound. 52657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param position Pre-layout position of item to be bound. 52667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param deadlineNs Time, relative to getNanoTime(), by which bind/create work should 52677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * complete. If FOREVER_NS is passed, this method will not fail to 52687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * bind the holder. 52697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return 52707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 52717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private boolean tryBindViewHolderByDeadline(ViewHolder holder, int offsetPosition, 52727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int position, long deadlineNs) { 52737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.mOwnerRecyclerView = RecyclerView.this; 52747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int viewType = holder.getItemViewType(); 52757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas long startBindNs = getNanoTime(); 52767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (deadlineNs != FOREVER_NS 52777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && !mRecyclerPool.willBindInTime(viewType, startBindNs, deadlineNs)) { 52787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // abort - we have a deadline we can't meet 52797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 52807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 52817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAdapter.bindViewHolder(holder, offsetPosition); 52827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas long endBindNs = getNanoTime(); 52837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerPool.factorInBindTime(holder.getItemViewType(), endBindNs - startBindNs); 52847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas attachAccessibilityDelegate(holder.itemView); 52857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mState.isPreLayout()) { 52867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.mPreLayoutPosition = position; 52877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 52887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return true; 52897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 52907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 52917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 52927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Binds the given View to the position. The View can be a View previously retrieved via 52937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #getViewForPosition(int)} or created by 52947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link Adapter#onCreateViewHolder(ViewGroup, int)}. 52957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 52967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Generally, a LayoutManager should acquire its views via {@link #getViewForPosition(int)} 52977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * and let the RecyclerView handle caching. This is a helper method for LayoutManager who 52987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * wants to handle its own recycling logic. 52997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 53007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that, {@link #getViewForPosition(int)} already binds the View to the position so 53017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * you don't need to call this method unless you want to bind this View to another position. 53027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 53037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param view The view to update. 53047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param position The position of the item to bind to this View. 53057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 53067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void bindViewToPosition(View view, int position) { 53077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder holder = getChildViewHolderInt(view); 53087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder == null) { 53097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalArgumentException("The view does not have a ViewHolder. You cannot" 53107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " pass arbitrary views to this method, they should be created by the " 53117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "Adapter"); 53127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 53137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int offsetPosition = mAdapterHelper.findPositionOffset(position); 53147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (offsetPosition < 0 || offsetPosition >= mAdapter.getItemCount()) { 53157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IndexOutOfBoundsException("Inconsistency detected. Invalid item " 53167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "position " + position + "(offset:" + offsetPosition + ")." 53177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "state:" + mState.getItemCount()); 53187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 53197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas tryBindViewHolderByDeadline(holder, offsetPosition, position, FOREVER_NS); 53207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 53217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams(); 53227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final LayoutParams rvLayoutParams; 53237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (lp == null) { 53247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas rvLayoutParams = (LayoutParams) generateDefaultLayoutParams(); 53257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.itemView.setLayoutParams(rvLayoutParams); 53267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (!checkLayoutParams(lp)) { 53277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas rvLayoutParams = (LayoutParams) generateLayoutParams(lp); 53287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.itemView.setLayoutParams(rvLayoutParams); 53297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 53307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas rvLayoutParams = (LayoutParams) lp; 53317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 53327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 53337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas rvLayoutParams.mInsetsDirty = true; 53347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas rvLayoutParams.mViewHolder = holder; 53357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas rvLayoutParams.mPendingInvalidate = holder.itemView.getParent() == null; 53367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 53377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 53387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 53397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView provides artificial position range (item count) in pre-layout state and 53407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * automatically maps these positions to {@link Adapter} positions when 53417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #getViewForPosition(int)} or {@link #bindViewToPosition(View, int)} is called. 53427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 53437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Usually, LayoutManager does not need to worry about this. However, in some cases, your 53447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManager may need to call some custom component with item positions in which 53457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * case you need the actual adapter position instead of the pre layout position. You 53467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * can use this method to convert a pre-layout position to adapter (post layout) position. 53477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 53487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that if the provided position belongs to a deleted ViewHolder, this method will 53497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * return -1. 53507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 53517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Calling this method in post-layout state returns the same value back. 53527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 53537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param position The pre-layout position to convert. Must be greater or equal to 0 and 53547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * less than {@link State#getItemCount()}. 53557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 53567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int convertPreLayoutPositionToPostLayout(int position) { 53577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (position < 0 || position >= mState.getItemCount()) { 53587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IndexOutOfBoundsException("invalid position " + position + ". State " 53597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "item count is " + mState.getItemCount()); 53607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 53617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!mState.isPreLayout()) { 53627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return position; 53637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 53647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mAdapterHelper.findPositionOffset(position); 53657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 53667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 53677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 53687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Obtain a view initialized for the given position. 53697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 53707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method should be used by {@link LayoutManager} implementations to obtain 53717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * views to represent data from an {@link Adapter}. 53727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 53737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The Recycler may reuse a scrap or detached view from a shared pool if one is 53747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * available for the correct view type. If the adapter has not indicated that the 53757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * data at the given position has changed, the Recycler will attempt to hand back 53767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * a scrap view that was previously initialized for that data without rebinding. 53777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 53787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param position Position to obtain a view for 53797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return A view representing the data at <code>position</code> from <code>adapter</code> 53807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 53817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public View getViewForPosition(int position) { 53827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return getViewForPosition(position, false); 53837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 53847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 53857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas View getViewForPosition(int position, boolean dryRun) { 53867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return tryGetViewHolderForPositionByDeadline(position, dryRun, FOREVER_NS).itemView; 53877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 53887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 53897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 53907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Attempts to get the ViewHolder for the given position, either from the Recycler scrap, 53917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * cache, the RecycledViewPool, or creating it directly. 53927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 53937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If a deadlineNs other than {@link #FOREVER_NS} is passed, this method early return 53947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * rather than constructing or binding a ViewHolder if it doesn't think it has time. 53957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If a ViewHolder must be constructed and not enough time remains, null is returned. If a 53967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ViewHolder is aquired and must be bound but not enough time remains, an unbound holder is 53977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * returned. Use {@link ViewHolder#isBound()} on the returned object to check for this. 53987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 53997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param position Position of ViewHolder to be returned. 54007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dryRun True if the ViewHolder should not be removed from scrap/cache/ 54017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param deadlineNs Time, relative to getNanoTime(), by which bind/create work should 54027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * complete. If FOREVER_NS is passed, this method will not fail to 54037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * create/bind the holder if needed. 54047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 54057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return ViewHolder for requested position 54067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 54077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Nullable 54087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder tryGetViewHolderForPositionByDeadline(int position, 54097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean dryRun, long deadlineNs) { 54107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (position < 0 || position >= mState.getItemCount()) { 54117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IndexOutOfBoundsException("Invalid item position " + position 54127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "(" + position + "). Item count:" + mState.getItemCount()); 54137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 54147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean fromScrapOrHiddenOrCache = false; 54157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder holder = null; 54167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // 0) If there is a changed scrap, try to find from there 54177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mState.isPreLayout()) { 54187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder = getChangedScrapViewForPosition(position); 54197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas fromScrapOrHiddenOrCache = holder != null; 54207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 54217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // 1) Find by position from scrap/hidden list/cache 54227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder == null) { 54237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder = getScrapOrHiddenOrCachedHolderForPosition(position, dryRun); 54247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder != null) { 54257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!validateViewHolderForOffsetPosition(holder)) { 54267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // recycle holder (and unscrap if relevant) since it can't be used 54277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!dryRun) { 54287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // we would like to recycle this but need to make sure it is not used by 54297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // animation logic etc. 54307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.addFlags(ViewHolder.FLAG_INVALID); 54317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.isScrap()) { 54327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas removeDetachedView(holder.itemView, false); 54337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.unScrap(); 54347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (holder.wasReturnedFromScrap()) { 54357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.clearReturnedFromScrapFlag(); 54367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 54377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recycleViewHolderInternal(holder); 54387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 54397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder = null; 54407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 54417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas fromScrapOrHiddenOrCache = true; 54427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 54437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 54447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 54457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder == null) { 54467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int offsetPosition = mAdapterHelper.findPositionOffset(position); 54477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (offsetPosition < 0 || offsetPosition >= mAdapter.getItemCount()) { 54487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IndexOutOfBoundsException("Inconsistency detected. Invalid item " 54497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "position " + position + "(offset:" + offsetPosition + ")." 54507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "state:" + mState.getItemCount()); 54517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 54527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 54537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int type = mAdapter.getItemViewType(offsetPosition); 54547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // 2) Find from scrap/cache via stable ids, if exists 54557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mAdapter.hasStableIds()) { 54567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder = getScrapOrCachedViewForId(mAdapter.getItemId(offsetPosition), 54577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas type, dryRun); 54587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder != null) { 54597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // update position 54607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.mPosition = offsetPosition; 54617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas fromScrapOrHiddenOrCache = true; 54627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 54637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 54647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder == null && mViewCacheExtension != null) { 54657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // We are NOT sending the offsetPosition because LayoutManager does not 54667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // know it. 54677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View view = mViewCacheExtension 54687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas .getViewForPositionAndType(this, position, type); 54697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (view != null) { 54707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder = getChildViewHolder(view); 54717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder == null) { 54727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalArgumentException("getViewForPositionAndType returned" 54737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " a view which does not have a ViewHolder"); 54747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (holder.shouldIgnore()) { 54757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalArgumentException("getViewForPositionAndType returned" 54767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " a view that is ignored. You must call stopIgnoring before" 54777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " returning this view."); 54787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 54797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 54807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 54817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder == null) { // fallback to pool 54827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 54837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.d(TAG, "tryGetViewHolderForPositionByDeadline(" 54847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + position + ") fetching from shared pool"); 54857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 54867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder = getRecycledViewPool().getRecycledView(type); 54877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder != null) { 54887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.resetInternal(); 54897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (FORCE_INVALIDATE_DISPLAY_LIST) { 54907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas invalidateDisplayListInt(holder); 54917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 54927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 54937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 54947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder == null) { 54957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas long start = getNanoTime(); 54967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (deadlineNs != FOREVER_NS 54977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && !mRecyclerPool.willCreateInTime(type, start, deadlineNs)) { 54987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // abort - we have a deadline we can't meet 54997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 55007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 55017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder = mAdapter.createViewHolder(RecyclerView.this, type); 55027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (ALLOW_THREAD_GAP_WORK) { 55037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // only bother finding nested RV if prefetching 55047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas RecyclerView innerView = findNestedRecyclerView(holder.itemView); 55057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (innerView != null) { 55067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.mNestedRecyclerView = new WeakReference<>(innerView); 55077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 55087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 55097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 55107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas long end = getNanoTime(); 55117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerPool.factorInCreateTime(type, end - start); 55127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 55137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.d(TAG, "tryGetViewHolderForPositionByDeadline created new ViewHolder"); 55147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 55157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 55167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 55177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 55187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // This is very ugly but the only place we can grab this information 55197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // before the View is rebound and returned to the LayoutManager for post layout ops. 55207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // We don't need this in pre-layout since the VH is not updated by the LM. 55217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (fromScrapOrHiddenOrCache && !mState.isPreLayout() && holder 55227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas .hasAnyOfTheFlags(ViewHolder.FLAG_BOUNCED_FROM_HIDDEN_LIST)) { 55237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.setFlags(0, ViewHolder.FLAG_BOUNCED_FROM_HIDDEN_LIST); 55247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mState.mRunSimpleAnimations) { 55257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int changeFlags = ItemAnimator 55267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas .buildAdapterChangeFlagsForAnimations(holder); 55277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas changeFlags |= ItemAnimator.FLAG_APPEARED_IN_PRE_LAYOUT; 55287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ItemHolderInfo info = mItemAnimator.recordPreLayoutInformation(mState, 55297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder, changeFlags, holder.getUnmodifiedPayloads()); 55307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recordAnimationInfoIfBouncedHiddenView(holder, info); 55317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 55327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 55337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 55347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean bound = false; 55357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mState.isPreLayout() && holder.isBound()) { 55367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // do not update unless we absolutely have to. 55377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.mPreLayoutPosition = position; 55387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (!holder.isBound() || holder.needsUpdate() || holder.isInvalid()) { 55397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG && holder.isRemoved()) { 55407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException("Removed holder should be bound and it should" 55417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " come here only in pre-layout. Holder: " + holder); 55427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 55437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int offsetPosition = mAdapterHelper.findPositionOffset(position); 55447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas bound = tryBindViewHolderByDeadline(holder, offsetPosition, position, deadlineNs); 55457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 55467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 55477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams(); 55487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final LayoutParams rvLayoutParams; 55497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (lp == null) { 55507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas rvLayoutParams = (LayoutParams) generateDefaultLayoutParams(); 55517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.itemView.setLayoutParams(rvLayoutParams); 55527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (!checkLayoutParams(lp)) { 55537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas rvLayoutParams = (LayoutParams) generateLayoutParams(lp); 55547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.itemView.setLayoutParams(rvLayoutParams); 55557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 55567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas rvLayoutParams = (LayoutParams) lp; 55577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 55587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas rvLayoutParams.mViewHolder = holder; 55597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas rvLayoutParams.mPendingInvalidate = fromScrapOrHiddenOrCache && bound; 55607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return holder; 55617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 55627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 55637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void attachAccessibilityDelegate(View itemView) { 55647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (isAccessibilityEnabled()) { 55657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (itemView.getImportantForAccessibility() 55667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) { 55677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas itemView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); 55687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 55697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 55707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (itemView.getAccessibilityDelegate() == null) { 55717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas itemView.setAccessibilityDelegate(mAccessibilityDelegate.getItemDelegate()); 55727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 55737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 55747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 55757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 55767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void invalidateDisplayListInt(ViewHolder holder) { 55777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.itemView instanceof ViewGroup) { 55787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas invalidateDisplayListInt((ViewGroup) holder.itemView, false); 55797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 55807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 55817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 55827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void invalidateDisplayListInt(ViewGroup viewGroup, boolean invalidateThis) { 55837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = viewGroup.getChildCount() - 1; i >= 0; i--) { 55847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View view = viewGroup.getChildAt(i); 55857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (view instanceof ViewGroup) { 55867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas invalidateDisplayListInt((ViewGroup) view, true); 55877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 55887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 55897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!invalidateThis) { 55907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 55917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 55927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // we need to force it to become invisible 55937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (viewGroup.getVisibility() == View.INVISIBLE) { 55947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas viewGroup.setVisibility(View.VISIBLE); 55957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas viewGroup.setVisibility(View.INVISIBLE); 55967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 55977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int visibility = viewGroup.getVisibility(); 55987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas viewGroup.setVisibility(View.INVISIBLE); 55997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas viewGroup.setVisibility(visibility); 56007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 56017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 56027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 56037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 56047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Recycle a detached view. The specified view will be added to a pool of views 56057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * for later rebinding and reuse. 56067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 56077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>A view must be fully detached (removed from parent) before it may be recycled. If the 56087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * View is scrapped, it will be removed from scrap list.</p> 56097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 56107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param view Removed view for recycling 56117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see LayoutManager#removeAndRecycleView(View, Recycler) 56127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 56137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void recycleView(View view) { 56147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // This public recycle method tries to make view recycle-able since layout manager 56157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // intended to recycle this view (e.g. even if it is in scrap or change cache) 56167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder holder = getChildViewHolderInt(view); 56177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.isTmpDetached()) { 56187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas removeDetachedView(view, false); 56197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 56207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.isScrap()) { 56217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.unScrap(); 56227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (holder.wasReturnedFromScrap()) { 56237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.clearReturnedFromScrapFlag(); 56247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 56257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recycleViewHolderInternal(holder); 56267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 56277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 56287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 56297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Internally, use this method instead of {@link #recycleView(android.view.View)} to 56307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * catch potential bugs. 56317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param view 56327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 56337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void recycleViewInternal(View view) { 56347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recycleViewHolderInternal(getChildViewHolderInt(view)); 56357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 56367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 56377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void recycleAndClearCachedViews() { 56387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int count = mCachedViews.size(); 56397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = count - 1; i >= 0; i--) { 56407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recycleCachedViewAt(i); 56417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 56427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mCachedViews.clear(); 56437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (ALLOW_THREAD_GAP_WORK) { 56447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPrefetchRegistry.clearPrefetchPositions(); 56457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 56467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 56477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 56487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 56497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Recycles a cached view and removes the view from the list. Views are added to cache 56507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * if and only if they are recyclable, so this method does not check it again. 56517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 56527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * A small exception to this rule is when the view does not have an animator reference 56537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * but transient state is true (due to animations created outside ItemAnimator). In that 56547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * case, adapter may choose to recycle it. From RecyclerView's perspective, the view is 56557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * still recyclable since Adapter wants to do so. 56567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 56577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param cachedViewIndex The index of the view in cached views list 56587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 56597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void recycleCachedViewAt(int cachedViewIndex) { 56607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 56617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.d(TAG, "Recycling cached view at index " + cachedViewIndex); 56627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 56637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder viewHolder = mCachedViews.get(cachedViewIndex); 56647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 56657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.d(TAG, "CachedViewHolder to be recycled: " + viewHolder); 56667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 56677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas addViewHolderToRecycledViewPool(viewHolder, true); 56687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mCachedViews.remove(cachedViewIndex); 56697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 56707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 56717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 56727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * internal implementation checks if view is scrapped or attached and throws an exception 56737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * if so. 56747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Public version un-scraps before calling recycle. 56757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 56767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void recycleViewHolderInternal(ViewHolder holder) { 56777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.isScrap() || holder.itemView.getParent() != null) { 56787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalArgumentException( 56797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas "Scrapped or attached views may not be recycled. isScrap:" 56807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + holder.isScrap() + " isAttached:" 56817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + (holder.itemView.getParent() != null)); 56827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 56837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 56847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.isTmpDetached()) { 56857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalArgumentException("Tmp detached view should be removed " 56867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "from RecyclerView before it can be recycled: " + holder); 56877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 56887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 56897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.shouldIgnore()) { 56907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalArgumentException("Trying to recycle an ignored view holder. You" 56917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " should first call stopIgnoringView(view) before calling recycle."); 56927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 56937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas //noinspection unchecked 56947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean transientStatePreventsRecycling = holder 56957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas .doesTransientStatePreventRecycling(); 56967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final boolean forceRecycle = mAdapter != null 56977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && transientStatePreventsRecycling 56987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && mAdapter.onFailedToRecycleView(holder); 56997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean cached = false; 57007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean recycled = false; 57017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG && mCachedViews.contains(holder)) { 57027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalArgumentException("cached view received recycle internal? " 57037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + holder); 57047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 57057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (forceRecycle || holder.isRecyclable()) { 57067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mViewCacheMax > 0 57077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && !holder.hasAnyOfTheFlags(ViewHolder.FLAG_INVALID 57087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas | ViewHolder.FLAG_REMOVED 57097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas | ViewHolder.FLAG_UPDATE 57107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas | ViewHolder.FLAG_ADAPTER_POSITION_UNKNOWN)) { 57117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Retire oldest cached view 57127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int cachedViewSize = mCachedViews.size(); 57137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (cachedViewSize >= mViewCacheMax && cachedViewSize > 0) { 57147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recycleCachedViewAt(0); 57157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas cachedViewSize--; 57167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 57177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 57187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int targetCacheIndex = cachedViewSize; 57197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (ALLOW_THREAD_GAP_WORK 57207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && cachedViewSize > 0 57217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && !mPrefetchRegistry.lastPrefetchIncludedPosition(holder.mPosition)) { 57227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // when adding the view, skip past most recently prefetched views 57237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int cacheIndex = cachedViewSize - 1; 57247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas while (cacheIndex >= 0) { 57257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int cachedPos = mCachedViews.get(cacheIndex).mPosition; 57267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!mPrefetchRegistry.lastPrefetchIncludedPosition(cachedPos)) { 57277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas break; 57287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 57297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas cacheIndex--; 57307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 57317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas targetCacheIndex = cacheIndex + 1; 57327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 57337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mCachedViews.add(targetCacheIndex, holder); 57347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas cached = true; 57357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 57367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!cached) { 57377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas addViewHolderToRecycledViewPool(holder, true); 57387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recycled = true; 57397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 57407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 57417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // NOTE: A view can fail to be recycled when it is scrolled off while an animation 57427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // runs. In this case, the item is eventually recycled by 57437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // ItemAnimatorRestoreListener#onAnimationFinished. 57447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 57457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // TODO: consider cancelling an animation when an item is removed scrollBy, 57467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // to return it to the pool faster 57477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 57487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.d(TAG, "trying to recycle a non-recycleable holder. Hopefully, it will " 57497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "re-visit here. We are still removing it from animation lists"); 57507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 57517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 57527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // even if the holder is not removed, we still call this method so that it is removed 57537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // from view holder lists. 57547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mViewInfoStore.removeViewHolder(holder); 57557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!cached && !recycled && transientStatePreventsRecycling) { 57567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.mOwnerRecyclerView = null; 57577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 57587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 57597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 57607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 57617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Prepares the ViewHolder to be removed/recycled, and inserts it into the RecycledViewPool. 57627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 57637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Pass false to dispatchRecycled for views that have not been bound. 57647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 57657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param holder Holder to be added to the pool. 57667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dispatchRecycled True to dispatch View recycled callbacks. 57677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 57687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void addViewHolderToRecycledViewPool(ViewHolder holder, boolean dispatchRecycled) { 57697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas clearNestedRecyclerViewIfNotNested(holder); 57707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.itemView.setAccessibilityDelegate(null); 57717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (dispatchRecycled) { 57727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dispatchViewRecycled(holder); 57737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 57747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.mOwnerRecyclerView = null; 57757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas getRecycledViewPool().putRecycledView(holder); 57767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 57777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 57787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 57797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Used as a fast path for unscrapping and recycling a view during a bulk operation. 57807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The caller must call {@link #clearScrap()} when it's done to update the recycler's 57817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * internal bookkeeping. 57827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 57837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void quickRecycleScrapView(View view) { 57847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = getChildViewHolderInt(view); 57857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.mScrapContainer = null; 57867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.mInChangeScrap = false; 57877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.clearReturnedFromScrapFlag(); 57887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recycleViewHolderInternal(holder); 57897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 57907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 57917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 57927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Mark an attached view as scrap. 57937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 57947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>"Scrap" views are still attached to their parent RecyclerView but are eligible 57957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * for rebinding and reuse. Requests for a view for a given position may return a 57967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * reused or rebound scrap view instance.</p> 57977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 57987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param view View to scrap 57997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 58007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void scrapView(View view) { 58017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = getChildViewHolderInt(view); 58027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.hasAnyOfTheFlags(ViewHolder.FLAG_REMOVED | ViewHolder.FLAG_INVALID) 58037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || !holder.isUpdated() || canReuseUpdatedViewHolder(holder)) { 58047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.isInvalid() && !holder.isRemoved() && !mAdapter.hasStableIds()) { 58057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalArgumentException("Called scrap view with an invalid view." 58067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " Invalid views cannot be reused from scrap, they should rebound from" 58077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " recycler pool."); 58087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 58097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.setScrapContainer(this, false); 58107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAttachedScrap.add(holder); 58117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 58127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mChangedScrap == null) { 58137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChangedScrap = new ArrayList<ViewHolder>(); 58147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 58157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.setScrapContainer(this, true); 58167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChangedScrap.add(holder); 58177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 58187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 58197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 58207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 58217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Remove a previously scrapped view from the pool of eligible scrap. 58227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 58237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>This view will no longer be eligible for reuse until re-scrapped or 58247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * until it is explicitly removed and recycled.</p> 58257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 58267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void unscrapView(ViewHolder holder) { 58277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.mInChangeScrap) { 58287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChangedScrap.remove(holder); 58297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 58307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAttachedScrap.remove(holder); 58317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 58327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.mScrapContainer = null; 58337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.mInChangeScrap = false; 58347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.clearReturnedFromScrapFlag(); 58357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 58367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 58377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int getScrapCount() { 58387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mAttachedScrap.size(); 58397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 58407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 58417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas View getScrapViewAt(int index) { 58427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mAttachedScrap.get(index).itemView; 58437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 58447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 58457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void clearScrap() { 58467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAttachedScrap.clear(); 58477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mChangedScrap != null) { 58487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChangedScrap.clear(); 58497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 58507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 58517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 58527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder getChangedScrapViewForPosition(int position) { 58537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // If pre-layout, check the changed scrap for an exact match. 58547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int changedScrapSize; 58557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mChangedScrap == null || (changedScrapSize = mChangedScrap.size()) == 0) { 58567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 58577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 58587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // find by position 58597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < changedScrapSize; i++) { 58607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = mChangedScrap.get(i); 58617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!holder.wasReturnedFromScrap() && holder.getLayoutPosition() == position) { 58627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.addFlags(ViewHolder.FLAG_RETURNED_FROM_SCRAP); 58637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return holder; 58647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 58657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 58667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // find by id 58677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mAdapter.hasStableIds()) { 58687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int offsetPosition = mAdapterHelper.findPositionOffset(position); 58697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (offsetPosition > 0 && offsetPosition < mAdapter.getItemCount()) { 58707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final long id = mAdapter.getItemId(offsetPosition); 58717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < changedScrapSize; i++) { 58727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = mChangedScrap.get(i); 58737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!holder.wasReturnedFromScrap() && holder.getItemId() == id) { 58747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.addFlags(ViewHolder.FLAG_RETURNED_FROM_SCRAP); 58757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return holder; 58767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 58777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 58787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 58797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 58807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 58817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 58827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 58837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 58847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns a view for the position either from attach scrap, hidden children, or cache. 58857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 58867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param position Item position 58877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dryRun Does a dry run, finds the ViewHolder but does not remove 58887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return a ViewHolder that can be re-used for this position. 58897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 58907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder getScrapOrHiddenOrCachedHolderForPosition(int position, boolean dryRun) { 58917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int scrapCount = mAttachedScrap.size(); 58927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 58937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Try first for an exact, non-invalid match from scrap. 58947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < scrapCount; i++) { 58957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = mAttachedScrap.get(i); 58967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!holder.wasReturnedFromScrap() && holder.getLayoutPosition() == position 58977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && !holder.isInvalid() && (mState.mInPreLayout || !holder.isRemoved())) { 58987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.addFlags(ViewHolder.FLAG_RETURNED_FROM_SCRAP); 58997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return holder; 59007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 59017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 59027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 59037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!dryRun) { 59047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas View view = mChildHelper.findHiddenNonRemovedView(position); 59057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (view != null) { 59067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // This View is good to be used. We just need to unhide, detach and move to the 59077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // scrap list. 59087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder vh = getChildViewHolderInt(view); 59097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChildHelper.unhide(view); 59107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int layoutIndex = mChildHelper.indexOfChild(view); 59117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (layoutIndex == RecyclerView.NO_POSITION) { 59127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException("layout index should not be -1 after " 59137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "unhiding a view:" + vh); 59147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 59157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChildHelper.detachViewFromParent(layoutIndex); 59167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas scrapView(view); 59177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas vh.addFlags(ViewHolder.FLAG_RETURNED_FROM_SCRAP 59187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas | ViewHolder.FLAG_BOUNCED_FROM_HIDDEN_LIST); 59197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return vh; 59207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 59217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 59227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 59237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Search in our first-level recycled view cache. 59247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int cacheSize = mCachedViews.size(); 59257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < cacheSize; i++) { 59267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = mCachedViews.get(i); 59277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // invalid view holders may be in cache if adapter has stable ids as they can be 59287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // retrieved via getScrapOrCachedViewForId 59297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!holder.isInvalid() && holder.getLayoutPosition() == position) { 59307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!dryRun) { 59317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mCachedViews.remove(i); 59327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 59337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 59347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.d(TAG, "getScrapOrHiddenOrCachedHolderForPosition(" + position 59357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + ") found match in cache: " + holder); 59367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 59377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return holder; 59387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 59397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 59407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 59417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 59427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 59437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder getScrapOrCachedViewForId(long id, int type, boolean dryRun) { 59447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Look in our attached views first 59457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int count = mAttachedScrap.size(); 59467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = count - 1; i >= 0; i--) { 59477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = mAttachedScrap.get(i); 59487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.getItemId() == id && !holder.wasReturnedFromScrap()) { 59497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (type == holder.getItemViewType()) { 59507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.addFlags(ViewHolder.FLAG_RETURNED_FROM_SCRAP); 59517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.isRemoved()) { 59527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // this might be valid in two cases: 59537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // > item is removed but we are in pre-layout pass 59547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // >> do nothing. return as is. make sure we don't rebind 59557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // > item is removed then added to another position and we are in 59567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // post layout. 59577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // >> remove removed and invalid flags, add update flag to rebind 59587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // because item was invisible to us and we don't know what happened in 59597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // between. 59607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!mState.isPreLayout()) { 59617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.setFlags(ViewHolder.FLAG_UPDATE, ViewHolder.FLAG_UPDATE 59627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas | ViewHolder.FLAG_INVALID | ViewHolder.FLAG_REMOVED); 59637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 59647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 59657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return holder; 59667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (!dryRun) { 59677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // if we are running animations, it is actually better to keep it in scrap 59687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // but this would force layout manager to lay it out which would be bad. 59697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Recycle this scrap. Type mismatch. 59707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAttachedScrap.remove(i); 59717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas removeDetachedView(holder.itemView, false); 59727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas quickRecycleScrapView(holder.itemView); 59737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 59747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 59757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 59767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 59777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Search the first-level cache 59787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int cacheSize = mCachedViews.size(); 59797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = cacheSize - 1; i >= 0; i--) { 59807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = mCachedViews.get(i); 59817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.getItemId() == id) { 59827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (type == holder.getItemViewType()) { 59837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!dryRun) { 59847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mCachedViews.remove(i); 59857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 59867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return holder; 59877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (!dryRun) { 59887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recycleCachedViewAt(i); 59897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 59907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 59917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 59927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 59937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 59947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 59957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 59967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void dispatchViewRecycled(ViewHolder holder) { 59977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerListener != null) { 59987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerListener.onViewRecycled(holder); 59997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mAdapter != null) { 60017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAdapter.onViewRecycled(holder); 60027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mState != null) { 60047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mViewInfoStore.removeViewHolder(holder); 60057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) Log.d(TAG, "dispatchViewRecycled: " + holder); 60077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 60097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void onAdapterChanged(Adapter oldAdapter, Adapter newAdapter, 60107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean compatibleWithPrevious) { 60117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas clear(); 60127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas getRecycledViewPool().onAdapterChanged(oldAdapter, newAdapter, compatibleWithPrevious); 60137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 60157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void offsetPositionRecordsForMove(int from, int to) { 60167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int start, end, inBetweenOffset; 60177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (from < to) { 60187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas start = from; 60197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas end = to; 60207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas inBetweenOffset = -1; 60217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 60227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas start = to; 60237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas end = from; 60247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas inBetweenOffset = 1; 60257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int cachedCount = mCachedViews.size(); 60277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < cachedCount; i++) { 60287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = mCachedViews.get(i); 60297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder == null || holder.mPosition < start || holder.mPosition > end) { 60307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas continue; 60317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.mPosition == from) { 60337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.offsetPosition(to - from, false); 60347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 60357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.offsetPosition(inBetweenOffset, false); 60367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 60387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.d(TAG, "offsetPositionRecordsForMove cached child " + i + " holder " 60397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + holder); 60407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 60447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void offsetPositionRecordsForInsert(int insertedAt, int count) { 60457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int cachedCount = mCachedViews.size(); 60467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < cachedCount; i++) { 60477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = mCachedViews.get(i); 60487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder != null && holder.mPosition >= insertedAt) { 60497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 60507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.d(TAG, "offsetPositionRecordsForInsert cached " + i + " holder " 60517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + holder + " now at position " + (holder.mPosition + count)); 60527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.offsetPosition(count, true); 60547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 60587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 60597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param removedFrom Remove start index 60607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param count Remove count 60617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param applyToPreLayout If true, changes will affect ViewHolder's pre-layout position, if 60627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * false, they'll be applied before the second layout pass 60637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 60647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void offsetPositionRecordsForRemove(int removedFrom, int count, boolean applyToPreLayout) { 60657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int removedEnd = removedFrom + count; 60667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int cachedCount = mCachedViews.size(); 60677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = cachedCount - 1; i >= 0; i--) { 60687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = mCachedViews.get(i); 60697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder != null) { 60707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.mPosition >= removedEnd) { 60717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 60727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.d(TAG, "offsetPositionRecordsForRemove cached " + i 60737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " holder " + holder + " now at position " 60747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + (holder.mPosition - count)); 60757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.offsetPosition(-count, applyToPreLayout); 60777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (holder.mPosition >= removedFrom) { 60787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Item for this view was removed. Dump it from the cache. 60797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.addFlags(ViewHolder.FLAG_REMOVED); 60807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recycleCachedViewAt(i); 60817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 60867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void setViewCacheExtension(ViewCacheExtension extension) { 60877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mViewCacheExtension = extension; 60887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 60907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void setRecycledViewPool(RecycledViewPool pool) { 60917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerPool != null) { 60927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerPool.detach(); 60937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerPool = pool; 60957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (pool != null) { 60967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerPool.attach(getAdapter()); 60977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 60997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 61007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas RecycledViewPool getRecycledViewPool() { 61017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerPool == null) { 61027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerPool = new RecycledViewPool(); 61037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 61047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mRecyclerPool; 61057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 61067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 61077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void viewRangeUpdate(int positionStart, int itemCount) { 61087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int positionEnd = positionStart + itemCount; 61097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int cachedCount = mCachedViews.size(); 61107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = cachedCount - 1; i >= 0; i--) { 61117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = mCachedViews.get(i); 61127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder == null) { 61137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas continue; 61147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 61157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 61167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int pos = holder.getLayoutPosition(); 61177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (pos >= positionStart && pos < positionEnd) { 61187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.addFlags(ViewHolder.FLAG_UPDATE); 61197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recycleCachedViewAt(i); 61207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // cached views should not be flagged as changed because this will cause them 61217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // to animate when they are returned from cache. 61227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 61237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 61247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 61257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 61267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void setAdapterPositionsAsUnknown() { 61277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int cachedCount = mCachedViews.size(); 61287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < cachedCount; i++) { 61297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = mCachedViews.get(i); 61307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder != null) { 61317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.addFlags(ViewHolder.FLAG_ADAPTER_POSITION_UNKNOWN); 61327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 61337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 61347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 61357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 61367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void markKnownViewsInvalid() { 61377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mAdapter != null && mAdapter.hasStableIds()) { 61387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int cachedCount = mCachedViews.size(); 61397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < cachedCount; i++) { 61407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = mCachedViews.get(i); 61417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder != null) { 61427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.addFlags(ViewHolder.FLAG_UPDATE | ViewHolder.FLAG_INVALID); 61437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.addChangePayload(null); 61447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 61457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 61467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 61477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // we cannot re-use cached views in this case. Recycle them all 61487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recycleAndClearCachedViews(); 61497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 61507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 61517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 61527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void clearOldPositions() { 61537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int cachedCount = mCachedViews.size(); 61547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < cachedCount; i++) { 61557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = mCachedViews.get(i); 61567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.clearOldPosition(); 61577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 61587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int scrapCount = mAttachedScrap.size(); 61597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < scrapCount; i++) { 61607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAttachedScrap.get(i).clearOldPosition(); 61617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 61627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mChangedScrap != null) { 61637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int changedScrapCount = mChangedScrap.size(); 61647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < changedScrapCount; i++) { 61657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChangedScrap.get(i).clearOldPosition(); 61667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 61677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 61687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 61697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 61707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void markItemDecorInsetsDirty() { 61717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int cachedCount = mCachedViews.size(); 61727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < cachedCount; i++) { 61737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = mCachedViews.get(i); 61747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas LayoutParams layoutParams = (LayoutParams) holder.itemView.getLayoutParams(); 61757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (layoutParams != null) { 61767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas layoutParams.mInsetsDirty = true; 61777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 61787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 61797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 61807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 61817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 61827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 61837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ViewCacheExtension is a helper class to provide an additional layer of view caching that can 61847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * be controlled by the developer. 61857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 61867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * When {@link Recycler#getViewForPosition(int)} is called, Recycler checks attached scrap and 61877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * first level cache to find a matching View. If it cannot find a suitable View, Recycler will 61887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * call the {@link #getViewForPositionAndType(Recycler, int, int)} before checking 61897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecycledViewPool}. 61907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 61917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that, Recycler never sends Views to this method to be cached. It is developers 61927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * responsibility to decide whether they want to keep their Views in this custom cache or let 61937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the default recycling policy handle it. 61947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 61957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract static class ViewCacheExtension { 61967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 61977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 61987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns a View that can be binded to the given Adapter position. 61997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 62007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method should <b>not</b> create a new View. Instead, it is expected to return 62017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * an already created View that can be re-used for the given type and position. 62027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If the View is marked as ignored, it should first call 62037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link LayoutManager#stopIgnoringView(View)} before returning the View. 62047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 62057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView will re-bind the returned View to the position if necessary. 62067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 62077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler The Recycler that can be used to bind the View 62087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param position The adapter position 62097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param type The type of the View, defined by adapter 62107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return A View that is bound to the given position or NULL if there is no View to re-use 62117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see LayoutManager#ignoreView(View) 62127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 62137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract View getViewForPositionAndType(Recycler recycler, int position, int type); 62147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 62157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 62167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 62177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Base class for an Adapter 62187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 62197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Adapters provide a binding from an app-specific data set to views that are displayed 62207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * within a {@link RecyclerView}.</p> 62217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 62227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @paramA class that extends ViewHolder that will be used by the adapter. 62237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 62247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract static class Adapter<VH extends ViewHolder> { 62257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private final AdapterDataObservable mObservable = new AdapterDataObservable(); 62267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private boolean mHasStableIds = false; 62277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 62287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 62297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when RecyclerView needs a new {@link ViewHolder} of the given type to represent 62307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * an item. 62317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 62327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This new ViewHolder should be constructed with a new View that can represent the items 62337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * of the given type. You can either create a new View manually or inflate it from an XML 62347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * layout file. 62357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 62367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The new ViewHolder will be used to display items of the adapter using 62377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #onBindViewHolder(ViewHolder, int, List)}. Since it will be re-used to display 62387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * different items in the data set, it is a good idea to cache references to sub views of 62397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the View to avoid unnecessary {@link View#findViewById(int)} calls. 62407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 62417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param parent The ViewGroup into which the new View will be added after it is bound to 62427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * an adapter position. 62437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param viewType The view type of the new View. 62447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 62457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return A new ViewHolder that holds a View of the given view type. 62467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #getItemViewType(int) 62477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #onBindViewHolder(ViewHolder, int) 62487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 62497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract VH onCreateViewHolder(ViewGroup parent, int viewType); 62507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 62517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 62527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called by RecyclerView to display the data at the specified position. This method should 62537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * update the contents of the {@link ViewHolder#itemView} to reflect the item at the given 62547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * position. 62557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 62567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that unlike {@link android.widget.ListView}, RecyclerView will not call this method 62577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * again if the position of the item changes in the data set unless the item itself is 62587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * invalidated or the new position cannot be determined. For this reason, you should only 62597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * use the <code>position</code> parameter while acquiring the related data item inside 62607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * this method and should not keep a copy of it. If you need the position of an item later 62617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * on (e.g. in a click listener), use {@link ViewHolder#getAdapterPosition()} which will 62627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * have the updated adapter position. 62637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 62647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Override {@link #onBindViewHolder(ViewHolder, int, List)} instead if Adapter can 62657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * handle efficient partial bind. 62667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 62677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param holder The ViewHolder which should be updated to represent the contents of the 62687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * item at the given position in the data set. 62697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param position The position of the item within the adapter's data set. 62707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 62717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract void onBindViewHolder(VH holder, int position); 62727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 62737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 62747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called by RecyclerView to display the data at the specified position. This method 62757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * should update the contents of the {@link ViewHolder#itemView} to reflect the item at 62767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the given position. 62777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 62787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that unlike {@link android.widget.ListView}, RecyclerView will not call this method 62797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * again if the position of the item changes in the data set unless the item itself is 62807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * invalidated or the new position cannot be determined. For this reason, you should only 62817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * use the <code>position</code> parameter while acquiring the related data item inside 62827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * this method and should not keep a copy of it. If you need the position of an item later 62837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * on (e.g. in a click listener), use {@link ViewHolder#getAdapterPosition()} which will 62847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * have the updated adapter position. 62857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 62867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Partial bind vs full bind: 62877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 62887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The payloads parameter is a merge list from {@link #notifyItemChanged(int, Object)} or 62897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #notifyItemRangeChanged(int, int, Object)}. If the payloads list is not empty, 62907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the ViewHolder is currently bound to old data and Adapter may run an efficient partial 62917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * update using the payload info. If the payload is empty, Adapter must run a full bind. 62927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Adapter should not assume that the payload passed in notify methods will be received by 62937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * onBindViewHolder(). For example when the view is not attached to the screen, the 62947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * payload in notifyItemChange() will be simply dropped. 62957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 62967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param holder The ViewHolder which should be updated to represent the contents of the 62977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * item at the given position in the data set. 62987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param position The position of the item within the adapter's data set. 62997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param payloads A non-null list of merged payloads. Can be empty list if requires full 63007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * update. 63017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 63027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onBindViewHolder(VH holder, int position, List<Object> payloads) { 63037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onBindViewHolder(holder, position); 63047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 63057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 63067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 63077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method calls {@link #onCreateViewHolder(ViewGroup, int)} to create a new 63087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link ViewHolder} and initializes some private fields to be used by RecyclerView. 63097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 63107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #onCreateViewHolder(ViewGroup, int) 63117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 63127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final VH createViewHolder(ViewGroup parent, int viewType) { 63137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Trace.beginSection(TRACE_CREATE_VIEW_TAG); 63147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final VH holder = onCreateViewHolder(parent, viewType); 63157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.mItemViewType = viewType; 63167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Trace.endSection(); 63177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return holder; 63187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 63197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 63207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 63217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method internally calls {@link #onBindViewHolder(ViewHolder, int)} to update the 63227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link ViewHolder} contents with the item at the given position and also sets up some 63237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * private fields to be used by RecyclerView. 63247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 63257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #onBindViewHolder(ViewHolder, int) 63267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 63277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final void bindViewHolder(VH holder, int position) { 63287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.mPosition = position; 63297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (hasStableIds()) { 63307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.mItemId = getItemId(position); 63317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 63327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.setFlags(ViewHolder.FLAG_BOUND, 63337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder.FLAG_BOUND | ViewHolder.FLAG_UPDATE | ViewHolder.FLAG_INVALID 63347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas | ViewHolder.FLAG_ADAPTER_POSITION_UNKNOWN); 63357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Trace.beginSection(TRACE_BIND_VIEW_TAG); 63367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onBindViewHolder(holder, position, holder.getUnmodifiedPayloads()); 63377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.clearPayload(); 63387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams(); 63397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (layoutParams instanceof RecyclerView.LayoutParams) { 63407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ((LayoutParams) layoutParams).mInsetsDirty = true; 63417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 63427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Trace.endSection(); 63437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 63447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 63457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 63467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Return the view type of the item at <code>position</code> for the purposes 63477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * of view recycling. 63487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 63497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>The default implementation of this method returns 0, making the assumption of 63507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * a single view type for the adapter. Unlike ListView adapters, types need not 63517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * be contiguous. Consider using id resources to uniquely identify item view types. 63527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 63537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param position position to query 63547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return integer value identifying the type of the view needed to represent the item at 63557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <code>position</code>. Type codes need not be contiguous. 63567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 63577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getItemViewType(int position) { 63587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return 0; 63597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 63607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 63617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 63627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Indicates whether each item in the data set can be represented with a unique identifier 63637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * of type {@link java.lang.Long}. 63647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 63657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param hasStableIds Whether items in data set have unique identifiers or not. 63667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #hasStableIds() 63677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #getItemId(int) 63687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 63697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setHasStableIds(boolean hasStableIds) { 63707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (hasObservers()) { 63717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException("Cannot change whether this adapter has " 63727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "stable IDs while the adapter has registered observers."); 63737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 63747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mHasStableIds = hasStableIds; 63757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 63767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 63777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 63787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Return the stable ID for the item at <code>position</code>. If {@link #hasStableIds()} 63797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * would return false this method should return {@link #NO_ID}. The default implementation 63807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * of this method returns {@link #NO_ID}. 63817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 63827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param position Adapter position to query 63837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return the stable ID of the item at position 63847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 63857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public long getItemId(int position) { 63867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return NO_ID; 63877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 63887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 63897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 63907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the total number of items in the data set held by the adapter. 63917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 63927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The total number of items in this adapter. 63937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 63947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract int getItemCount(); 63957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 63967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 63977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns true if this adapter publishes a unique <code>long</code> value that can 63987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * act as a key for the item at a given position in the data set. If that item is relocated 63997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * in the data set, the ID returned for that item should be the same. 64007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 64017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if this adapter's items have stable IDs 64027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 64037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final boolean hasStableIds() { 64047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mHasStableIds; 64057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 64067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 64077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 64087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when a view created by this adapter has been recycled. 64097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 64107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>A view is recycled when a {@link LayoutManager} decides that it no longer 64117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * needs to be attached to its parent {@link RecyclerView}. This can be because it has 64127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * fallen out of visibility or a set of cached views represented by views still 64137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * attached to the parent RecyclerView. If an item view has large or expensive data 64147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * bound to it such as large bitmaps, this may be a good place to release those 64157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * resources.</p> 64167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 64177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView calls this method right before clearing ViewHolder's internal data and 64187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * sending it to RecycledViewPool. This way, if ViewHolder was holding valid information 64197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * before being recycled, you can call {@link ViewHolder#getAdapterPosition()} to get 64207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * its adapter position. 64217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 64227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param holder The ViewHolder for the view being recycled 64237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 64247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onViewRecycled(VH holder) { 64257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 64267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 64277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 64287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called by the RecyclerView if a ViewHolder created by this Adapter cannot be recycled 64297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * due to its transient state. Upon receiving this callback, Adapter can clear the 64307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animation(s) that effect the View's transient state and return <code>true</code> so that 64317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the View can be recycled. Keep in mind that the View in question is already removed from 64327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the RecyclerView. 64337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 64347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * In some cases, it is acceptable to recycle a View although it has transient state. Most 64357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * of the time, this is a case where the transient state will be cleared in 64367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #onBindViewHolder(ViewHolder, int)} call when View is rebound to a new position. 64377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * For this reason, RecyclerView leaves the decision to the Adapter and uses the return 64387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * value of this method to decide whether the View should be recycled or not. 64397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 64407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that when all animations are created by {@link RecyclerView.ItemAnimator}, you 64417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * should never receive this callback because RecyclerView keeps those Views as children 64427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * until their animations are complete. This callback is useful when children of the item 64437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * views create animations which may not be easy to implement using an {@link ItemAnimator}. 64447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 64457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * You should <em>never</em> fix this issue by calling 64467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <code>holder.itemView.setHasTransientState(false);</code> unless you've previously called 64477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <code>holder.itemView.setHasTransientState(true);</code>. Each 64487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <code>View.setHasTransientState(true)</code> call must be matched by a 64497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <code>View.setHasTransientState(false)</code> call, otherwise, the state of the View 64507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * may become inconsistent. You should always prefer to end or cancel animations that are 64517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * triggering the transient state instead of handling it manually. 64527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 64537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param holder The ViewHolder containing the View that could not be recycled due to its 64547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * transient state. 64557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return True if the View should be recycled, false otherwise. Note that if this method 64567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * returns <code>true</code>, RecyclerView <em>will ignore</em> the transient state of 64577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the View and recycle it regardless. If this method returns <code>false</code>, 64587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView will check the View's transient state again before giving a final decision. 64597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Default implementation returns false. 64607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 64617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean onFailedToRecycleView(VH holder) { 64627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 64637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 64647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 64657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 64667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when a view created by this adapter has been attached to a window. 64677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 64687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>This can be used as a reasonable signal that the view is about to be seen 64697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * by the user. If the adapter previously freed any resources in 64707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #onViewDetachedFromWindow(RecyclerView.ViewHolder) onViewDetachedFromWindow} 64717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * those resources should be restored here.</p> 64727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 64737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param holder Holder of the view being attached 64747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 64757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onViewAttachedToWindow(VH holder) { 64767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 64777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 64787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 64797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when a view created by this adapter has been detached from its window. 64807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 64817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Becoming detached from the window is not necessarily a permanent condition; 64827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the consumer of an Adapter's views may choose to cache views offscreen while they 64837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * are not visible, attaching and detaching them as appropriate.</p> 64847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 64857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param holder Holder of the view being detached 64867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 64877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onViewDetachedFromWindow(VH holder) { 64887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 64897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 64907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 64917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns true if one or more observers are attached to this adapter. 64927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 64937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if this adapter has observers 64947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 64957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final boolean hasObservers() { 64967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mObservable.hasObservers(); 64977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 64987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 64997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 65007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Register a new observer to listen for data changes. 65017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 65027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>The adapter may publish a variety of events describing specific changes. 65037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Not all adapters may support all change types and some may fall back to a generic 65047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link com.android.internal.widget.RecyclerView.AdapterDataObserver#onChanged() 65057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * "something changed"} event if more specific data is not available.</p> 65067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 65077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Components registering observers with an adapter are responsible for 65087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #unregisterAdapterDataObserver(RecyclerView.AdapterDataObserver) 65097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * unregistering} those observers when finished.</p> 65107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 65117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param observer Observer to register 65127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 65137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #unregisterAdapterDataObserver(RecyclerView.AdapterDataObserver) 65147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 65157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void registerAdapterDataObserver(AdapterDataObserver observer) { 65167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mObservable.registerObserver(observer); 65177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 65187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 65197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 65207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Unregister an observer currently listening for data changes. 65217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 65227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>The unregistered observer will no longer receive events about changes 65237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to the adapter.</p> 65247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 65257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param observer Observer to unregister 65267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 65277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #registerAdapterDataObserver(RecyclerView.AdapterDataObserver) 65287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 65297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void unregisterAdapterDataObserver(AdapterDataObserver observer) { 65307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mObservable.unregisterObserver(observer); 65317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 65327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 65337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 65347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called by RecyclerView when it starts observing this Adapter. 65357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 65367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Keep in mind that same adapter may be observed by multiple RecyclerViews. 65377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 65387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recyclerView The RecyclerView instance which started observing this adapter. 65397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #onDetachedFromRecyclerView(RecyclerView) 65407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 65417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onAttachedToRecyclerView(RecyclerView recyclerView) { 65427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 65437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 65447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 65457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called by RecyclerView when it stops observing this Adapter. 65467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 65477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recyclerView The RecyclerView instance which stopped observing this adapter. 65487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #onAttachedToRecyclerView(RecyclerView) 65497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 65507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onDetachedFromRecyclerView(RecyclerView recyclerView) { 65517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 65527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 65537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 65547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Notify any registered observers that the data set has changed. 65557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 65567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>There are two different classes of data change events, item changes and structural 65577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * changes. Item changes are when a single item has its data updated but no positional 65587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * changes have occurred. Structural changes are when items are inserted, removed or moved 65597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * within the data set.</p> 65607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 65617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>This event does not specify what about the data set has changed, forcing 65627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * any observers to assume that all existing items and structure may no longer be valid. 65637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManagers will be forced to fully rebind and relayout all visible views.</p> 65647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 65657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p><code>RecyclerView</code> will attempt to synthesize visible structural change events 65667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * for adapters that report that they have {@link #hasStableIds() stable IDs} when 65677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * this method is used. This can help for the purposes of animation and visual 65687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * object persistence but individual item views will still need to be rebound 65697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * and relaid out.</p> 65707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 65717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>If you are writing an adapter it will always be more efficient to use the more 65727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * specific change events if you can. Rely on <code>notifyDataSetChanged()</code> 65737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * as a last resort.</p> 65747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 65757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #notifyItemChanged(int) 65767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #notifyItemInserted(int) 65777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #notifyItemRemoved(int) 65787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #notifyItemRangeChanged(int, int) 65797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #notifyItemRangeInserted(int, int) 65807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #notifyItemRangeRemoved(int, int) 65817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 65827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final void notifyDataSetChanged() { 65837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mObservable.notifyChanged(); 65847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 65857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 65867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 65877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Notify any registered observers that the item at <code>position</code> has changed. 65887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Equivalent to calling <code>notifyItemChanged(position, null);</code>. 65897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 65907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>This is an item change event, not a structural change event. It indicates that any 65917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * reflection of the data at <code>position</code> is out of date and should be updated. 65927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The item at <code>position</code> retains the same identity.</p> 65937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 65947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param position Position of the item that has changed 65957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 65967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #notifyItemRangeChanged(int, int) 65977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 65987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final void notifyItemChanged(int position) { 65997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mObservable.notifyItemRangeChanged(position, 1); 66007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 66017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 66027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 66037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Notify any registered observers that the item at <code>position</code> has changed with 66047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * an optional payload object. 66057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 66067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>This is an item change event, not a structural change event. It indicates that any 66077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * reflection of the data at <code>position</code> is out of date and should be updated. 66087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The item at <code>position</code> retains the same identity. 66097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * </p> 66107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 66117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 66127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Client can optionally pass a payload for partial change. These payloads will be merged 66137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * and may be passed to adapter's {@link #onBindViewHolder(ViewHolder, int, List)} if the 66147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * item is already represented by a ViewHolder and it will be rebound to the same 66157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ViewHolder. A notifyItemRangeChanged() with null payload will clear all existing 66167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * payloads on that item and prevent future payload until 66177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #onBindViewHolder(ViewHolder, int, List)} is called. Adapter should not assume 66187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * that the payload will always be passed to onBindViewHolder(), e.g. when the view is not 66197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * attached, the payload will be simply dropped. 66207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 66217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param position Position of the item that has changed 66227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param payload Optional parameter, use null to identify a "full" update 66237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 66247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #notifyItemRangeChanged(int, int) 66257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 66267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final void notifyItemChanged(int position, Object payload) { 66277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mObservable.notifyItemRangeChanged(position, 1, payload); 66287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 66297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 66307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 66317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Notify any registered observers that the <code>itemCount</code> items starting at 66327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * position <code>positionStart</code> have changed. 66337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Equivalent to calling <code>notifyItemRangeChanged(position, itemCount, null);</code>. 66347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 66357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>This is an item change event, not a structural change event. It indicates that 66367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * any reflection of the data in the given position range is out of date and should 66377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * be updated. The items in the given range retain the same identity.</p> 66387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 66397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param positionStart Position of the first item that has changed 66407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param itemCount Number of items that have changed 66417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 66427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #notifyItemChanged(int) 66437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 66447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final void notifyItemRangeChanged(int positionStart, int itemCount) { 66457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mObservable.notifyItemRangeChanged(positionStart, itemCount); 66467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 66477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 66487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 66497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Notify any registered observers that the <code>itemCount</code> items starting at 66507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * position <code>positionStart</code> have changed. An optional payload can be 66517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * passed to each changed item. 66527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 66537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>This is an item change event, not a structural change event. It indicates that any 66547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * reflection of the data in the given position range is out of date and should be updated. 66557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The items in the given range retain the same identity. 66567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * </p> 66577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 66587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 66597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Client can optionally pass a payload for partial change. These payloads will be merged 66607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * and may be passed to adapter's {@link #onBindViewHolder(ViewHolder, int, List)} if the 66617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * item is already represented by a ViewHolder and it will be rebound to the same 66627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ViewHolder. A notifyItemRangeChanged() with null payload will clear all existing 66637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * payloads on that item and prevent future payload until 66647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #onBindViewHolder(ViewHolder, int, List)} is called. Adapter should not assume 66657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * that the payload will always be passed to onBindViewHolder(), e.g. when the view is not 66667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * attached, the payload will be simply dropped. 66677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 66687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param positionStart Position of the first item that has changed 66697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param itemCount Number of items that have changed 66707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param payload Optional parameter, use null to identify a "full" update 66717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 66727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #notifyItemChanged(int) 66737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 66747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final void notifyItemRangeChanged(int positionStart, int itemCount, Object payload) { 66757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mObservable.notifyItemRangeChanged(positionStart, itemCount, payload); 66767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 66777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 66787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 66797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Notify any registered observers that the item reflected at <code>position</code> 66807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * has been newly inserted. The item previously at <code>position</code> is now at 66817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * position <code>position + 1</code>. 66827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 66837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>This is a structural change event. Representations of other existing items in the 66847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * data set are still considered up to date and will not be rebound, though their 66857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * positions may be altered.</p> 66867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 66877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param position Position of the newly inserted item in the data set 66887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 66897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #notifyItemRangeInserted(int, int) 66907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 66917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final void notifyItemInserted(int position) { 66927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mObservable.notifyItemRangeInserted(position, 1); 66937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 66947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 66957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 66967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Notify any registered observers that the item reflected at <code>fromPosition</code> 66977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * has been moved to <code>toPosition</code>. 66987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 66997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>This is a structural change event. Representations of other existing items in the 67007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * data set are still considered up to date and will not be rebound, though their 67017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * positions may be altered.</p> 67027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 67037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param fromPosition Previous position of the item. 67047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param toPosition New position of the item. 67057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 67067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final void notifyItemMoved(int fromPosition, int toPosition) { 67077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mObservable.notifyItemMoved(fromPosition, toPosition); 67087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 67097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 67107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 67117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Notify any registered observers that the currently reflected <code>itemCount</code> 67127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * items starting at <code>positionStart</code> have been newly inserted. The items 67137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * previously located at <code>positionStart</code> and beyond can now be found starting 67147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * at position <code>positionStart + itemCount</code>. 67157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 67167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>This is a structural change event. Representations of other existing items in the 67177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * data set are still considered up to date and will not be rebound, though their positions 67187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * may be altered.</p> 67197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 67207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param positionStart Position of the first item that was inserted 67217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param itemCount Number of items inserted 67227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 67237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #notifyItemInserted(int) 67247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 67257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final void notifyItemRangeInserted(int positionStart, int itemCount) { 67267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mObservable.notifyItemRangeInserted(positionStart, itemCount); 67277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 67287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 67297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 67307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Notify any registered observers that the item previously located at <code>position</code> 67317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * has been removed from the data set. The items previously located at and after 67327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <code>position</code> may now be found at <code>oldPosition - 1</code>. 67337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 67347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>This is a structural change event. Representations of other existing items in the 67357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * data set are still considered up to date and will not be rebound, though their positions 67367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * may be altered.</p> 67377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 67387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param position Position of the item that has now been removed 67397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 67407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #notifyItemRangeRemoved(int, int) 67417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 67427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final void notifyItemRemoved(int position) { 67437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mObservable.notifyItemRangeRemoved(position, 1); 67447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 67457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 67467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 67477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Notify any registered observers that the <code>itemCount</code> items previously 67487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * located at <code>positionStart</code> have been removed from the data set. The items 67497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * previously located at and after <code>positionStart + itemCount</code> may now be found 67507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * at <code>oldPosition - itemCount</code>. 67517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 67527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>This is a structural change event. Representations of other existing items in the data 67537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * set are still considered up to date and will not be rebound, though their positions 67547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * may be altered.</p> 67557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 67567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param positionStart Previous position of the first item that was removed 67577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param itemCount Number of items removed from the data set 67587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 67597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final void notifyItemRangeRemoved(int positionStart, int itemCount) { 67607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mObservable.notifyItemRangeRemoved(positionStart, itemCount); 67617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 67627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 67637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 67647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void dispatchChildDetached(View child) { 67657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder viewHolder = getChildViewHolderInt(child); 67667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onChildDetachedFromWindow(child); 67677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mAdapter != null && viewHolder != null) { 67687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAdapter.onViewDetachedFromWindow(viewHolder); 67697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 67707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mOnChildAttachStateListeners != null) { 67717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int cnt = mOnChildAttachStateListeners.size(); 67727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = cnt - 1; i >= 0; i--) { 67737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mOnChildAttachStateListeners.get(i).onChildViewDetachedFromWindow(child); 67747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 67757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 67767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 67777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 67787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void dispatchChildAttached(View child) { 67797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder viewHolder = getChildViewHolderInt(child); 67807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onChildAttachedToWindow(child); 67817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mAdapter != null && viewHolder != null) { 67827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAdapter.onViewAttachedToWindow(viewHolder); 67837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 67847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mOnChildAttachStateListeners != null) { 67857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int cnt = mOnChildAttachStateListeners.size(); 67867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = cnt - 1; i >= 0; i--) { 67877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mOnChildAttachStateListeners.get(i).onChildViewAttachedToWindow(child); 67887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 67897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 67907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 67917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 67927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 67937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * A <code>LayoutManager</code> is responsible for measuring and positioning item views 67947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * within a <code>RecyclerView</code> as well as determining the policy for when to recycle 67957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * item views that are no longer visible to the user. By changing the <code>LayoutManager</code> 67967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * a <code>RecyclerView</code> can be used to implement a standard vertically scrolling list, 67977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * a uniform grid, staggered grids, horizontally scrolling collections and more. Several stock 67987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * layout managers are provided for general use. 67997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p/> 68007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If the LayoutManager specifies a default constructor or one with the signature 68017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ({@link Context}, {@link AttributeSet}, {@code int}, {@code int}), RecyclerView will 68027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * instantiate and set the LayoutManager when being inflated. Most used properties can 68037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * be then obtained from {@link #getProperties(Context, AttributeSet, int, int)}. In case 68047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * a LayoutManager specifies both constructors, the non-default constructor will take 68057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * precedence. 68067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 68077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 68087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract static class LayoutManager { 68097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ChildHelper mChildHelper; 68107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas RecyclerView mRecyclerView; 68117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 68127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Nullable 68137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas SmoothScroller mSmoothScroller; 68147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 68157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean mRequestedSimpleAnimations = false; 68167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 68177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean mIsAttachedToWindow = false; 68187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 68197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean mAutoMeasure = false; 68207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 68217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 68227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManager has its own more strict measurement cache to avoid re-measuring a child 68237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * if the space that will be given to it is already larger than what it has measured before. 68247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 68257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private boolean mMeasurementCacheEnabled = true; 68267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 68277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private boolean mItemPrefetchEnabled = true; 68287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 68297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 68307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Written by {@link GapWorker} when prefetches occur to track largest number of view ever 68317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * requested by a {@link #collectInitialPrefetchPositions(int, LayoutPrefetchRegistry)} or 68327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #collectAdjacentPrefetchPositions(int, int, State, LayoutPrefetchRegistry)} call. 68337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 68347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If expanded by a {@link #collectInitialPrefetchPositions(int, LayoutPrefetchRegistry)}, 68357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * will be reset upon layout to prevent initial prefetches (often large, since they're 68367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * proportional to expected child count) from expanding cache permanently. 68377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 68387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int mPrefetchMaxCountObserved; 68397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 68407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 68417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If true, mPrefetchMaxCountObserved is only valid until next layout, and should be reset. 68427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 68437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean mPrefetchMaxObservedInInitialPrefetch; 68447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 68457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 68467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * These measure specs might be the measure specs that were passed into RecyclerView's 68477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * onMeasure method OR fake measure specs created by the RecyclerView. 68487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * For example, when a layout is run, RecyclerView always sets these specs to be 68497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * EXACTLY because a LayoutManager cannot resize RecyclerView during a layout pass. 68507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 68517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Also, to be able to use the hint in unspecified measure specs, RecyclerView checks the 68527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * API level and sets the size to 0 pre-M to avoid any issue that might be caused by 68537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * corrupt values. Older platforms have no responsibility to provide a size if they set 68547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * mode to unspecified. 68557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 68567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mWidthMode, mHeightMode; 68577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mWidth, mHeight; 68587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 68597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 68607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 68617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Interface for LayoutManagers to request items to be prefetched, based on position, with 68627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * specified distance from viewport, which indicates priority. 68637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 68647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see LayoutManager#collectAdjacentPrefetchPositions(int, int, State, LayoutPrefetchRegistry) 68657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see LayoutManager#collectInitialPrefetchPositions(int, LayoutPrefetchRegistry) 68667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 68677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public interface LayoutPrefetchRegistry { 68687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 68697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Requests an an item to be prefetched, based on position, with a specified distance, 68707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * indicating priority. 68717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 68727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param layoutPosition Position of the item to prefetch. 68737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param pixelDistance Distance from the current viewport to the bounds of the item, 68747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * must be non-negative. 68757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 68767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void addPosition(int layoutPosition, int pixelDistance); 68777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 68787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 68797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void setRecyclerView(RecyclerView recyclerView) { 68807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (recyclerView == null) { 68817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView = null; 68827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChildHelper = null; 68837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mWidth = 0; 68847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mHeight = 0; 68857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 68867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView = recyclerView; 68877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChildHelper = recyclerView.mChildHelper; 68887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mWidth = recyclerView.getWidth(); 68897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mHeight = recyclerView.getHeight(); 68907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 68917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mWidthMode = MeasureSpec.EXACTLY; 68927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mHeightMode = MeasureSpec.EXACTLY; 68937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 68947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 68957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void setMeasureSpecs(int wSpec, int hSpec) { 68967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mWidth = MeasureSpec.getSize(wSpec); 68977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mWidthMode = MeasureSpec.getMode(wSpec); 68987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mWidthMode == MeasureSpec.UNSPECIFIED && !ALLOW_SIZE_IN_UNSPECIFIED_SPEC) { 68997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mWidth = 0; 69007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 69017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 69027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mHeight = MeasureSpec.getSize(hSpec); 69037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mHeightMode = MeasureSpec.getMode(hSpec); 69047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mHeightMode == MeasureSpec.UNSPECIFIED && !ALLOW_SIZE_IN_UNSPECIFIED_SPEC) { 69057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mHeight = 0; 69067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 69077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 69087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 69097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 69107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called after a layout is calculated during a measure pass when using auto-measure. 69117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 69127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * It simply traverses all children to calculate a bounding box then calls 69137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #setMeasuredDimension(Rect, int, int)}. LayoutManagers can override that method 69147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * if they need to handle the bounding box differently. 69157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 69167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * For example, GridLayoutManager override that method to ensure that even if a column is 69177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * empty, the GridLayoutManager still measures wide enough to include it. 69187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 69197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param widthSpec The widthSpec that was passing into RecyclerView's onMeasure 69207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param heightSpec The heightSpec that was passing into RecyclerView's onMeasure 69217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 69227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void setMeasuredDimensionFromChildren(int widthSpec, int heightSpec) { 69237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int count = getChildCount(); 69247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (count == 0) { 69257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.defaultOnMeasure(widthSpec, heightSpec); 69267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 69277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 69287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int minX = Integer.MAX_VALUE; 69297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int minY = Integer.MAX_VALUE; 69307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int maxX = Integer.MIN_VALUE; 69317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int maxY = Integer.MIN_VALUE; 69327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 69337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < count; i++) { 69347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas View child = getChildAt(i); 69357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final Rect bounds = mRecyclerView.mTempRect; 69367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas getDecoratedBoundsWithMargins(child, bounds); 69377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (bounds.left < minX) { 69387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas minX = bounds.left; 69397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 69407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (bounds.right > maxX) { 69417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas maxX = bounds.right; 69427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 69437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (bounds.top < minY) { 69447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas minY = bounds.top; 69457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 69467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (bounds.bottom > maxY) { 69477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas maxY = bounds.bottom; 69487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 69497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 69507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.mTempRect.set(minX, minY, maxX, maxY); 69517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setMeasuredDimension(mRecyclerView.mTempRect, widthSpec, heightSpec); 69527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 69537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 69547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 69557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Sets the measured dimensions from the given bounding box of the children and the 69567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * measurement specs that were passed into {@link RecyclerView#onMeasure(int, int)}. It is 69577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * called after the RecyclerView calls 69587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link LayoutManager#onLayoutChildren(Recycler, State)} during a measurement pass. 69597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 69607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method should call {@link #setMeasuredDimension(int, int)}. 69617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 69627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The default implementation adds the RecyclerView's padding to the given bounding box 69637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * then caps the value to be within the given measurement specs. 69647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 69657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method is only called if the LayoutManager opted into the auto measurement API. 69667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 69677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param childrenBounds The bounding box of all children 69687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param wSpec The widthMeasureSpec that was passed into the RecyclerView. 69697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param hSpec The heightMeasureSpec that was passed into the RecyclerView. 69707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 69717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #setAutoMeasureEnabled(boolean) 69727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 69737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setMeasuredDimension(Rect childrenBounds, int wSpec, int hSpec) { 69747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int usedWidth = childrenBounds.width() + getPaddingLeft() + getPaddingRight(); 69757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int usedHeight = childrenBounds.height() + getPaddingTop() + getPaddingBottom(); 69767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int width = chooseSize(wSpec, usedWidth, getMinimumWidth()); 69777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int height = chooseSize(hSpec, usedHeight, getMinimumHeight()); 69787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setMeasuredDimension(width, height); 69797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 69807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 69817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 69827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Calls {@code RecyclerView#requestLayout} on the underlying RecyclerView 69837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 69847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void requestLayout() { 69857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView != null) { 69867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.requestLayout(); 69877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 69887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 69897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 69907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 69917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Checks if RecyclerView is in the middle of a layout or scroll and throws an 69927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link IllegalStateException} if it <b>is not</b>. 69937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 69947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param message The message for the exception. Can be null. 69957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #assertNotInLayoutOrScroll(String) 69967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 69977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void assertInLayoutOrScroll(String message) { 69987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView != null) { 69997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.assertInLayoutOrScroll(message); 70007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 70017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 70027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 70037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 70047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Chooses a size from the given specs and parameters that is closest to the desired size 70057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * and also complies with the spec. 70067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 70077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param spec The measureSpec 70087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param desired The preferred measurement 70097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param min The minimum value 70107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 70117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return A size that fits to the given specs 70127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 70137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static int chooseSize(int spec, int desired, int min) { 70147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int mode = View.MeasureSpec.getMode(spec); 70157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int size = View.MeasureSpec.getSize(spec); 70167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas switch (mode) { 70177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case View.MeasureSpec.EXACTLY: 70187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return size; 70197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case View.MeasureSpec.AT_MOST: 70207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return Math.min(size, Math.max(desired, min)); 70217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case View.MeasureSpec.UNSPECIFIED: 70227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas default: 70237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return Math.max(desired, min); 70247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 70257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 70267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 70277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 70287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Checks if RecyclerView is in the middle of a layout or scroll and throws an 70297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link IllegalStateException} if it <b>is</b>. 70307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 70317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param message The message for the exception. Can be null. 70327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #assertInLayoutOrScroll(String) 70337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 70347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void assertNotInLayoutOrScroll(String message) { 70357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView != null) { 70367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.assertNotInLayoutOrScroll(message); 70377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 70387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 70397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 70407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 70417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Defines whether the layout should be measured by the RecyclerView or the LayoutManager 70427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * wants to handle the layout measurements itself. 70437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 70447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method is usually called by the LayoutManager with value {@code true} if it wants 70457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to support WRAP_CONTENT. If you are using a public LayoutManager but want to customize 70467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the measurement logic, you can call this method with {@code false} and override 70477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link LayoutManager#onMeasure(int, int)} to implement your custom measurement logic. 70487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 70497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * AutoMeasure is a convenience mechanism for LayoutManagers to easily wrap their content or 70507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * handle various specs provided by the RecyclerView's parent. 70517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * It works by calling {@link LayoutManager#onLayoutChildren(Recycler, State)} during an 70527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecyclerView#onMeasure(int, int)} call, then calculating desired dimensions based 70537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * on children's positions. It does this while supporting all existing animation 70547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * capabilities of the RecyclerView. 70557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 70567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * AutoMeasure works as follows: 70577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <ol> 70587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>LayoutManager should call {@code setAutoMeasureEnabled(true)} to enable it. All of 70597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the framework LayoutManagers use {@code auto-measure}.</li> 70607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>When {@link RecyclerView#onMeasure(int, int)} is called, if the provided specs are 70617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * exact, RecyclerView will only call LayoutManager's {@code onMeasure} and return without 70627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * doing any layout calculation.</li> 70637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>If one of the layout specs is not {@code EXACT}, the RecyclerView will start the 70647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * layout process in {@code onMeasure} call. It will process all pending Adapter updates and 70657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * decide whether to run a predictive layout or not. If it decides to do so, it will first 70667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * call {@link #onLayoutChildren(Recycler, State)} with {@link State#isPreLayout()} set to 70677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@code true}. At this stage, {@link #getWidth()} and {@link #getHeight()} will still 70687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * return the width and height of the RecyclerView as of the last layout calculation. 70697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 70707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * After handling the predictive case, RecyclerView will call 70717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #onLayoutChildren(Recycler, State)} with {@link State#isMeasuring()} set to 70727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@code true} and {@link State#isPreLayout()} set to {@code false}. The LayoutManager can 70737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * access the measurement specs via {@link #getHeight()}, {@link #getHeightMode()}, 70747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #getWidth()} and {@link #getWidthMode()}.</li> 70757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>After the layout calculation, RecyclerView sets the measured width & height by 70767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * calculating the bounding box for the children (+ RecyclerView's padding). The 70777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManagers can override {@link #setMeasuredDimension(Rect, int, int)} to choose 70787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * different values. For instance, GridLayoutManager overrides this value to handle the case 70797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * where if it is vertical and has 3 columns but only 2 items, it should still measure its 70807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * width to fit 3 items, not 2.</li> 70817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>Any following on measure call to the RecyclerView will run 70827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #onLayoutChildren(Recycler, State)} with {@link State#isMeasuring()} set to 70837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@code true} and {@link State#isPreLayout()} set to {@code false}. RecyclerView will 70847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * take care of which views are actually added / removed / moved / changed for animations so 70857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * that the LayoutManager should not worry about them and handle each 70867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #onLayoutChildren(Recycler, State)} call as if it is the last one. 70877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * </li> 70887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>When measure is complete and RecyclerView's 70897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #onLayout(boolean, int, int, int, int)} method is called, RecyclerView checks 70907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * whether it already did layout calculations during the measure pass and if so, it re-uses 70917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * that information. It may still decide to call {@link #onLayoutChildren(Recycler, State)} 70927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * if the last measure spec was different from the final dimensions or adapter contents 70937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * have changed between the measure call and the layout call.</li> 70947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>Finally, animations are calculated and run as usual.</li> 70957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * </ol> 70967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 70977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param enabled <code>True</code> if the Layout should be measured by the 70987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView, <code>false</code> if the LayoutManager wants 70997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to measure itself. 71007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 71017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #setMeasuredDimension(Rect, int, int) 71027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #isAutoMeasureEnabled() 71037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 71047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setAutoMeasureEnabled(boolean enabled) { 71057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAutoMeasure = enabled; 71067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 71077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 71087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 71097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns whether the LayoutManager uses the automatic measurement API or not. 71107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 71117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return <code>True</code> if the LayoutManager is measured by the RecyclerView or 71127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <code>false</code> if it measures itself. 71137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 71147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #setAutoMeasureEnabled(boolean) 71157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 71167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean isAutoMeasureEnabled() { 71177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mAutoMeasure; 71187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 71197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 71207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 71217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns whether this LayoutManager supports automatic item animations. 71227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * A LayoutManager wishing to support item animations should obey certain 71237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * rules as outlined in {@link #onLayoutChildren(Recycler, State)}. 71247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The default return value is <code>false</code>, so subclasses of LayoutManager 71257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * will not get predictive item animations by default. 71267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 71277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Whether item animations are enabled in a RecyclerView is determined both 71287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * by the return value from this method and the 71297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecyclerView#setItemAnimator(ItemAnimator) ItemAnimator} set on the 71307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView itself. If the RecyclerView has a non-null ItemAnimator but this 71317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * method returns false, then simple item animations will be enabled, in which 71327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * views that are moving onto or off of the screen are simply faded in/out. If 71337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the RecyclerView has a non-null ItemAnimator and this method returns true, 71347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * then there will be two calls to {@link #onLayoutChildren(Recycler, State)} to 71357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * setup up the information needed to more intelligently predict where appearing 71367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * and disappearing views should be animated from/to.</p> 71377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 71387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if predictive item animations should be enabled, false otherwise 71397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 71407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean supportsPredictiveItemAnimations() { 71417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 71427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 71437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 71447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 71457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Sets whether the LayoutManager should be queried for views outside of 71467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * its viewport while the UI thread is idle between frames. 71477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 71487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>If enabled, the LayoutManager will be queried for items to inflate/bind in between 71497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * view system traversals on devices running API 21 or greater. Default value is true.</p> 71507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 71517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>On platforms API level 21 and higher, the UI thread is idle between passing a frame 71527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to RenderThread and the starting up its next frame at the next VSync pulse. By 71537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * prefetching out of window views in this time period, delays from inflation and view 71547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * binding are much less likely to cause jank and stuttering during scrolls and flings.</p> 71557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 71567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>While prefetch is enabled, it will have the side effect of expanding the effective 71577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * size of the View cache to hold prefetched views.</p> 71587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 71597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param enabled <code>True</code> if items should be prefetched in between traversals. 71607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 71617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #isItemPrefetchEnabled() 71627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 71637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final void setItemPrefetchEnabled(boolean enabled) { 71647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (enabled != mItemPrefetchEnabled) { 71657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemPrefetchEnabled = enabled; 71667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPrefetchMaxCountObserved = 0; 71677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView != null) { 71687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.mRecycler.updateViewCacheSize(); 71697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 71707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 71717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 71727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 71737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 71747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Sets whether the LayoutManager should be queried for views outside of 71757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * its viewport while the UI thread is idle between frames. 71767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 71777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #setItemPrefetchEnabled(boolean) 71787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 71797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if item prefetch is enabled, false otherwise 71807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 71817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final boolean isItemPrefetchEnabled() { 71827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mItemPrefetchEnabled; 71837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 71847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 71857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 71867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Gather all positions from the LayoutManager to be prefetched, given specified momentum. 71877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 71887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>If item prefetch is enabled, this method is called in between traversals to gather 71897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * which positions the LayoutManager will soon need, given upcoming movement in subsequent 71907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * traversals.</p> 71917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 71927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>The LayoutManager should call {@link LayoutPrefetchRegistry#addPosition(int, int)} for 71937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * each item to be prepared, and these positions will have their ViewHolders created and 71947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * bound, if there is sufficient time available, in advance of being needed by a 71957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * scroll or layout.</p> 71967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 71977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dx X movement component. 71987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dy Y movement component. 71997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state State of RecyclerView 72007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param layoutPrefetchRegistry PrefetchRegistry to add prefetch entries into. 72017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 72027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #isItemPrefetchEnabled() 72037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #collectInitialPrefetchPositions(int, LayoutPrefetchRegistry) 72047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 72057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void collectAdjacentPrefetchPositions(int dx, int dy, State state, 72067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas LayoutPrefetchRegistry layoutPrefetchRegistry) {} 72077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 72087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 72097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Gather all positions from the LayoutManager to be prefetched in preperation for its 72107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView to come on screen, due to the movement of another, containing RecyclerView. 72117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 72127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>This method is only called when a RecyclerView is nested in another RecyclerView.</p> 72137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 72147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>If item prefetch is enabled for this LayoutManager, as well in another containing 72157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManager, this method is called in between draw traversals to gather 72167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * which positions this LayoutManager will first need, once it appears on the screen.</p> 72177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 72187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>For example, if this LayoutManager represents a horizontally scrolling list within a 72197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * vertically scrolling LayoutManager, this method would be called when the horizontal list 72207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * is about to come onscreen.</p> 72217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 72227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>The LayoutManager should call {@link LayoutPrefetchRegistry#addPosition(int, int)} for 72237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * each item to be prepared, and these positions will have their ViewHolders created and 72247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * bound, if there is sufficient time available, in advance of being needed by a 72257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * scroll or layout.</p> 72267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 72277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param adapterItemCount number of items in the associated adapter. 72287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param layoutPrefetchRegistry PrefetchRegistry to add prefetch entries into. 72297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 72307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #isItemPrefetchEnabled() 72317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #collectAdjacentPrefetchPositions(int, int, State, LayoutPrefetchRegistry) 72327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 72337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void collectInitialPrefetchPositions(int adapterItemCount, 72347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas LayoutPrefetchRegistry layoutPrefetchRegistry) {} 72357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 72367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void dispatchAttachedToWindow(RecyclerView view) { 72377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mIsAttachedToWindow = true; 72387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onAttachedToWindow(view); 72397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 72407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 72417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void dispatchDetachedFromWindow(RecyclerView view, Recycler recycler) { 72427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mIsAttachedToWindow = false; 72437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onDetachedFromWindow(view, recycler); 72447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 72457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 72467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 72477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns whether LayoutManager is currently attached to a RecyclerView which is attached 72487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to a window. 72497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 72507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return True if this LayoutManager is controlling a RecyclerView and the RecyclerView 72517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * is attached to window. 72527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 72537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean isAttachedToWindow() { 72547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mIsAttachedToWindow; 72557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 72567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 72577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 72587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Causes the Runnable to execute on the next animation time step. 72597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The runnable will be run on the user interface thread. 72607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 72617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Calling this method when LayoutManager is not attached to a RecyclerView has no effect. 72627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 72637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param action The Runnable that will be executed. 72647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 72657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #removeCallbacks 72667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 72677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void postOnAnimation(Runnable action) { 72687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView != null) { 72697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.postOnAnimation(action); 72707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 72717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 72727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 72737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 72747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Removes the specified Runnable from the message queue. 72757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 72767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Calling this method when LayoutManager is not attached to a RecyclerView has no effect. 72777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 72787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param action The Runnable to remove from the message handling queue 72797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 72807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if RecyclerView could ask the Handler to remove the Runnable, 72817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * false otherwise. When the returned value is true, the Runnable 72827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * may or may not have been actually removed from the message queue 72837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * (for instance, if the Runnable was not in the queue already.) 72847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 72857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #postOnAnimation 72867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 72877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean removeCallbacks(Runnable action) { 72887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView != null) { 72897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mRecyclerView.removeCallbacks(action); 72907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 72917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 72927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 72937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 72947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when this LayoutManager is both attached to a RecyclerView and that RecyclerView 72957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * is attached to a window. 72967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 72977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If the RecyclerView is re-attached with the same LayoutManager and Adapter, it may not 72987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * call {@link #onLayoutChildren(Recycler, State)} if nothing has changed and a layout was 72997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * not requested on the RecyclerView while it was detached. 73007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 73017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Subclass implementations should always call through to the superclass implementation. 73027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 73037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param view The RecyclerView this LayoutManager is bound to 73047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 73057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #onDetachedFromWindow(RecyclerView, Recycler) 73067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 73077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @CallSuper 73087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onAttachedToWindow(RecyclerView view) { 73097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 73107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 73117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 73127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @deprecated 73137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * override {@link #onDetachedFromWindow(RecyclerView, Recycler)} 73147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 73157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Deprecated 73167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onDetachedFromWindow(RecyclerView view) { 73177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 73187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 73197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 73207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 73217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when this LayoutManager is detached from its parent RecyclerView or when 73227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * its parent RecyclerView is detached from its window. 73237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 73247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManager should clear all of its View references as another LayoutManager might be 73257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * assigned to the RecyclerView. 73267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 73277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If the RecyclerView is re-attached with the same LayoutManager and Adapter, it may not 73287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * call {@link #onLayoutChildren(Recycler, State)} if nothing has changed and a layout was 73297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * not requested on the RecyclerView while it was detached. 73307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 73317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If your LayoutManager has View references that it cleans in on-detach, it should also 73327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * call {@link RecyclerView#requestLayout()} to ensure that it is re-laid out when 73337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView is re-attached. 73347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 73357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Subclass implementations should always call through to the superclass implementation. 73367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 73377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param view The RecyclerView this LayoutManager is bound to 73387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler The recycler to use if you prefer to recycle your children instead of 73397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * keeping them around. 73407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 73417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #onAttachedToWindow(RecyclerView) 73427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 73437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @CallSuper 73447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onDetachedFromWindow(RecyclerView view, Recycler recycler) { 73457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onDetachedFromWindow(view); 73467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 73477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 73487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 73497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Check if the RecyclerView is configured to clip child views to its padding. 73507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 73517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if this RecyclerView clips children to its padding, false otherwise 73527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 73537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean getClipToPadding() { 73547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mRecyclerView != null && mRecyclerView.mClipToPadding; 73557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 73567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 73577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 73587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Lay out all relevant child views from the given adapter. 73597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 73607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The LayoutManager is in charge of the behavior of item animations. By default, 73617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView has a non-null {@link #getItemAnimator() ItemAnimator}, and simple 73627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * item animations are enabled. This means that add/remove operations on the 73637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * adapter will result in animations to add new or appearing items, removed or 73647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * disappearing items, and moved items. If a LayoutManager returns false from 73657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #supportsPredictiveItemAnimations()}, which is the default, and runs a 73667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * normal layout operation during {@link #onLayoutChildren(Recycler, State)}, the 73677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView will have enough information to run those animations in a simple 73687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * way. For example, the default ItemAnimator, {@link DefaultItemAnimator}, will 73697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * simply fade views in and out, whether they are actually added/removed or whether 73707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * they are moved on or off the screen due to other add/remove operations. 73717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 73727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>A LayoutManager wanting a better item animation experience, where items can be 73737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animated onto and off of the screen according to where the items exist when they 73747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * are not on screen, then the LayoutManager should return true from 73757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #supportsPredictiveItemAnimations()} and add additional logic to 73767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #onLayoutChildren(Recycler, State)}. Supporting predictive animations 73777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * means that {@link #onLayoutChildren(Recycler, State)} will be called twice; 73787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * once as a "pre" layout step to determine where items would have been prior to 73797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * a real layout, and again to do the "real" layout. In the pre-layout phase, 73807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * items will remember their pre-layout positions to allow them to be laid out 73817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * appropriately. Also, {@link LayoutParams#isItemRemoved() removed} items will 73827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * be returned from the scrap to help determine correct placement of other items. 73837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * These removed items should not be added to the child list, but should be used 73847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to help calculate correct positioning of other views, including views that 73857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * were not previously onscreen (referred to as APPEARING views), but whose 73867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * pre-layout offscreen position can be determined given the extra 73877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * information about the pre-layout removed views.</p> 73887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 73897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>The second layout pass is the real layout in which only non-removed views 73907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * will be used. The only additional requirement during this pass is, if 73917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #supportsPredictiveItemAnimations()} returns true, to note which 73927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * views exist in the child list prior to layout and which are not there after 73937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * layout (referred to as DISAPPEARING views), and to position/layout those views 73947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * appropriately, without regard to the actual bounds of the RecyclerView. This allows 73957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the animation system to know the location to which to animate these disappearing 73967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * views.</p> 73977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 73987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>The default LayoutManager implementations for RecyclerView handle all of these 73997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * requirements for animations already. Clients of RecyclerView can either use one 74007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * of these layout managers directly or look at their implementations of 74017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * onLayoutChildren() to see how they account for the APPEARING and 74027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * DISAPPEARING views.</p> 74037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 74047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler Recycler to use for fetching potentially cached views for a 74057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * position 74067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state Transient state of RecyclerView 74077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 74087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onLayoutChildren(Recycler recycler, State state) { 74097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.e(TAG, "You must override onLayoutChildren(Recycler recycler, State state) "); 74107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 74117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 74127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 74137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called after a full layout calculation is finished. The layout calculation may include 74147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * multiple {@link #onLayoutChildren(Recycler, State)} calls due to animations or 74157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * layout measurement but it will include only one {@link #onLayoutCompleted(State)} call. 74167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method will be called at the end of {@link View#layout(int, int, int, int)} call. 74177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 74187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This is a good place for the LayoutManager to do some cleanup like pending scroll 74197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * position, saved state etc. 74207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 74217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state Transient state of RecyclerView 74227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 74237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onLayoutCompleted(State state) { 74247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 74257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 74267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 74277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Create a default <code>LayoutParams</code> object for a child of the RecyclerView. 74287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 74297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>LayoutManagers will often want to use a custom <code>LayoutParams</code> type 74307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to store extra information specific to the layout. Client code should subclass 74317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecyclerView.LayoutParams} for this purpose.</p> 74327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 74337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p><em>Important:</em> if you use your own custom <code>LayoutParams</code> type 74347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * you must also override 74357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #checkLayoutParams(LayoutParams)}, 74367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #generateLayoutParams(android.view.ViewGroup.LayoutParams)} and 74377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #generateLayoutParams(android.content.Context, android.util.AttributeSet)}.</p> 74387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 74397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return A new LayoutParams for a child view 74407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 74417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract LayoutParams generateDefaultLayoutParams(); 74427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 74437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 74447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Determines the validity of the supplied LayoutParams object. 74457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 74467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>This should check to make sure that the object is of the correct type 74477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * and all values are within acceptable ranges. The default implementation 74487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * returns <code>true</code> for non-null params.</p> 74497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 74507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param lp LayoutParams object to check 74517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if this LayoutParams object is valid, false otherwise 74527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 74537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean checkLayoutParams(LayoutParams lp) { 74547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return lp != null; 74557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 74567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 74577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 74587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Create a LayoutParams object suitable for this LayoutManager, copying relevant 74597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * values from the supplied LayoutParams object if possible. 74607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 74617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p><em>Important:</em> if you use your own custom <code>LayoutParams</code> type 74627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * you must also override 74637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #checkLayoutParams(LayoutParams)}, 74647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #generateLayoutParams(android.view.ViewGroup.LayoutParams)} and 74657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #generateLayoutParams(android.content.Context, android.util.AttributeSet)}.</p> 74667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 74677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param lp Source LayoutParams object to copy values from 74687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return a new LayoutParams object 74697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 74707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) { 74717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (lp instanceof LayoutParams) { 74727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return new LayoutParams((LayoutParams) lp); 74737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (lp instanceof MarginLayoutParams) { 74747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return new LayoutParams((MarginLayoutParams) lp); 74757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 74767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return new LayoutParams(lp); 74777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 74787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 74797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 74807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 74817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Create a LayoutParams object suitable for this LayoutManager from 74827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * an inflated layout resource. 74837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 74847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p><em>Important:</em> if you use your own custom <code>LayoutParams</code> type 74857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * you must also override 74867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #checkLayoutParams(LayoutParams)}, 74877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #generateLayoutParams(android.view.ViewGroup.LayoutParams)} and 74887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #generateLayoutParams(android.content.Context, android.util.AttributeSet)}.</p> 74897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 74907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param c Context for obtaining styled attributes 74917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param attrs AttributeSet describing the supplied arguments 74927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return a new LayoutParams object 74937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 74947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public LayoutParams generateLayoutParams(Context c, AttributeSet attrs) { 74957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return new LayoutParams(c, attrs); 74967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 74977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 74987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 74997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Scroll horizontally by dx pixels in screen coordinates and return the distance traveled. 75007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The default implementation does nothing and returns 0. 75017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 75027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dx distance to scroll by in pixels. X increases as scroll position 75037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * approaches the right. 75047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler Recycler to use for fetching potentially cached views for a 75057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * position 75067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state Transient state of RecyclerView 75077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The actual distance scrolled. The return value will be negative if dx was 75087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * negative and scrolling proceeeded in that direction. 75097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <code>Math.abs(result)</code> may be less than dx if a boundary was reached. 75107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 75117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int scrollHorizontallyBy(int dx, Recycler recycler, State state) { 75127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return 0; 75137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 75147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 75157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 75167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Scroll vertically by dy pixels in screen coordinates and return the distance traveled. 75177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The default implementation does nothing and returns 0. 75187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 75197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dy distance to scroll in pixels. Y increases as scroll position 75207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * approaches the bottom. 75217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler Recycler to use for fetching potentially cached views for a 75227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * position 75237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state Transient state of RecyclerView 75247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The actual distance scrolled. The return value will be negative if dy was 75257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * negative and scrolling proceeeded in that direction. 75267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <code>Math.abs(result)</code> may be less than dy if a boundary was reached. 75277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 75287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int scrollVerticallyBy(int dy, Recycler recycler, State state) { 75297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return 0; 75307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 75317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 75327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 75337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Query if horizontal scrolling is currently supported. The default implementation 75347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * returns false. 75357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 75367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return True if this LayoutManager can scroll the current contents horizontally 75377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 75387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean canScrollHorizontally() { 75397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 75407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 75417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 75427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 75437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Query if vertical scrolling is currently supported. The default implementation 75447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * returns false. 75457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 75467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return True if this LayoutManager can scroll the current contents vertically 75477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 75487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean canScrollVertically() { 75497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 75507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 75517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 75527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 75537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Scroll to the specified adapter position. 75547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 75557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Actual position of the item on the screen depends on the LayoutManager implementation. 75567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param position Scroll to this adapter position. 75577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 75587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void scrollToPosition(int position) { 75597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 75607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.e(TAG, "You MUST implement scrollToPosition. It will soon become abstract"); 75617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 75627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 75637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 75647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 75657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Smooth scroll to the specified adapter position.</p> 75667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>To support smooth scrolling, override this method, create your {@link SmoothScroller} 75677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * instance and call {@link #startSmoothScroll(SmoothScroller)}. 75687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * </p> 75697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recyclerView The RecyclerView to which this layout manager is attached 75707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state Current State of RecyclerView 75717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param position Scroll to this adapter position. 75727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 75737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void smoothScrollToPosition(RecyclerView recyclerView, State state, 75747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int position) { 75757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.e(TAG, "You must override smoothScrollToPosition to support smooth scrolling"); 75767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 75777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 75787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 75797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Starts a smooth scroll using the provided SmoothScroller.</p> 75807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Calling this method will cancel any previous smooth scroll request.</p> 75817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param smoothScroller Instance which defines how smooth scroll should be animated 75827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 75837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void startSmoothScroll(SmoothScroller smoothScroller) { 75847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mSmoothScroller != null && smoothScroller != mSmoothScroller 75857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && mSmoothScroller.isRunning()) { 75867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mSmoothScroller.stop(); 75877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 75887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mSmoothScroller = smoothScroller; 75897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mSmoothScroller.start(mRecyclerView, this); 75907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 75917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 75927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 75937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if RecycylerView is currently in the state of smooth scrolling. 75947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 75957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean isSmoothScrolling() { 75967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mSmoothScroller != null && mSmoothScroller.isRunning(); 75977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 75987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 75997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 76007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 76017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the resolved layout direction for this RecyclerView. 76027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 76037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return {@link android.view.View#LAYOUT_DIRECTION_RTL} if the layout 76047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * direction is RTL or returns 76057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link android.view.View#LAYOUT_DIRECTION_LTR} if the layout direction 76067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * is not RTL. 76077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 76087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getLayoutDirection() { 76097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mRecyclerView.getLayoutDirection(); 76107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 76117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 76127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 76137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Ends all animations on the view created by the {@link ItemAnimator}. 76147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 76157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param view The View for which the animations should be ended. 76167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see RecyclerView.ItemAnimator#endAnimations() 76177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 76187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void endAnimation(View view) { 76197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView.mItemAnimator != null) { 76207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.mItemAnimator.endAnimation(getChildViewHolderInt(view)); 76217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 76227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 76237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 76247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 76257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * To be called only during {@link #onLayoutChildren(Recycler, State)} to add a view 76267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to the layout that is known to be going away, either because it has been 76277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link Adapter#notifyItemRemoved(int) removed} or because it is actually not in the 76287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * visible portion of the container but is being laid out in order to inform RecyclerView 76297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * in how to animate the item out of view. 76307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 76317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Views added via this method are going to be invisible to LayoutManager after the 76327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * dispatchLayout pass is complete. They cannot be retrieved via {@link #getChildAt(int)} 76337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * or won't be included in {@link #getChildCount()} method. 76347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 76357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child View to add and then remove with animation. 76367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 76377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void addDisappearingView(View child) { 76387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas addDisappearingView(child, -1); 76397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 76407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 76417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 76427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * To be called only during {@link #onLayoutChildren(Recycler, State)} to add a view 76437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to the layout that is known to be going away, either because it has been 76447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link Adapter#notifyItemRemoved(int) removed} or because it is actually not in the 76457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * visible portion of the container but is being laid out in order to inform RecyclerView 76467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * in how to animate the item out of view. 76477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 76487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Views added via this method are going to be invisible to LayoutManager after the 76497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * dispatchLayout pass is complete. They cannot be retrieved via {@link #getChildAt(int)} 76507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * or won't be included in {@link #getChildCount()} method. 76517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 76527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child View to add and then remove with animation. 76537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param index Index of the view. 76547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 76557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void addDisappearingView(View child, int index) { 76567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas addViewInt(child, index, true); 76577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 76587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 76597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 76607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Add a view to the currently attached RecyclerView if needed. LayoutManagers should 76617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * use this method to add views obtained from a {@link Recycler} using 76627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link Recycler#getViewForPosition(int)}. 76637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 76647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child View to add 76657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 76667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void addView(View child) { 76677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas addView(child, -1); 76687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 76697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 76707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 76717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Add a view to the currently attached RecyclerView if needed. LayoutManagers should 76727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * use this method to add views obtained from a {@link Recycler} using 76737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link Recycler#getViewForPosition(int)}. 76747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 76757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child View to add 76767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param index Index to add child at 76777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 76787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void addView(View child, int index) { 76797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas addViewInt(child, index, false); 76807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 76817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 76827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void addViewInt(View child, int index, boolean disappearing) { 76837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder holder = getChildViewHolderInt(child); 76847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (disappearing || holder.isRemoved()) { 76857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // these views will be hidden at the end of the layout pass. 76867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.mViewInfoStore.addToDisappearedInLayout(holder); 76877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 76887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // This may look like unnecessary but may happen if layout manager supports 76897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // predictive layouts and adapter removed then re-added the same item. 76907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // In this case, added version will be visible in the post layout (because add is 76917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // deferred) but RV will still bind it to the same View. 76927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // So if a View re-appears in post layout pass, remove it from disappearing list. 76937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.mViewInfoStore.removeFromDisappearedInLayout(holder); 76947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 76957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 76967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.wasReturnedFromScrap() || holder.isScrap()) { 76977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (holder.isScrap()) { 76987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.unScrap(); 76997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 77007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.clearReturnedFromScrapFlag(); 77017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 77027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChildHelper.attachViewToParent(child, index, child.getLayoutParams(), false); 77037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DISPATCH_TEMP_DETACH) { 77047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas child.dispatchFinishTemporaryDetach(); 77057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 77067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (child.getParent() == mRecyclerView) { // it was not a scrap but a valid child 77077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // ensure in correct position 77087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int currentIndex = mChildHelper.indexOfChild(child); 77097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (index == -1) { 77107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas index = mChildHelper.getChildCount(); 77117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 77127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (currentIndex == -1) { 77137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException("Added View has RecyclerView as parent but" 77147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " view is not a real child. Unfiltered index:" 77157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + mRecyclerView.indexOfChild(child)); 77167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 77177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (currentIndex != index) { 77187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.mLayout.moveView(currentIndex, index); 77197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 77207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 77217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChildHelper.addView(child, index, false); 77227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas lp.mInsetsDirty = true; 77237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mSmoothScroller != null && mSmoothScroller.isRunning()) { 77247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mSmoothScroller.onChildAttachedToWindow(child); 77257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 77267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 77277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (lp.mPendingInvalidate) { 77287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 77297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.d(TAG, "consuming pending invalidate on child " + lp.mViewHolder); 77307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 77317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas holder.itemView.invalidate(); 77327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas lp.mPendingInvalidate = false; 77337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 77347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 77357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 77367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 77377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Remove a view from the currently attached RecyclerView if needed. LayoutManagers should 77387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * use this method to completely remove a child view that is no longer needed. 77397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManagers should strongly consider recycling removed views using 77407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link Recycler#recycleView(android.view.View)}. 77417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 77427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child View to remove 77437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 77447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void removeView(View child) { 77457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChildHelper.removeView(child); 77467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 77477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 77487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 77497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Remove a view from the currently attached RecyclerView if needed. LayoutManagers should 77507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * use this method to completely remove a child view that is no longer needed. 77517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManagers should strongly consider recycling removed views using 77527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link Recycler#recycleView(android.view.View)}. 77537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 77547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param index Index of the child view to remove 77557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 77567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void removeViewAt(int index) { 77577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View child = getChildAt(index); 77587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (child != null) { 77597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChildHelper.removeViewAt(index); 77607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 77617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 77627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 77637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 77647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Remove all views from the currently attached RecyclerView. This will not recycle 77657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * any of the affected views; the LayoutManager is responsible for doing so if desired. 77667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 77677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void removeAllViews() { 77687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Only remove non-animating views 77697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childCount = getChildCount(); 77707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = childCount - 1; i >= 0; i--) { 77717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChildHelper.removeViewAt(i); 77727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 77737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 77747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 77757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 77767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns offset of the RecyclerView's text baseline from the its top boundary. 77777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 77787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The offset of the RecyclerView's text baseline from the its top boundary; -1 if 77797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * there is no baseline. 77807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 77817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getBaseline() { 77827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return -1; 77837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 77847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 77857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 77867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the adapter position of the item represented by the given View. This does not 77877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * contain any adapter changes that might have happened after the last layout. 77887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 77897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param view The view to query 77907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The adapter position of the item which is rendered by this View. 77917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 77927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getPosition(View view) { 77937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return ((RecyclerView.LayoutParams) view.getLayoutParams()).getViewLayoutPosition(); 77947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 77957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 77967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 77977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the View type defined by the adapter. 77987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 77997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param view The view to query 78007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The type of the view assigned by the adapter. 78017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 78027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getItemViewType(View view) { 78037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return getChildViewHolderInt(view).getItemViewType(); 78047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 78057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 78067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 78077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Traverses the ancestors of the given view and returns the item view that contains it 78087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * and also a direct child of the LayoutManager. 78097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 78107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that this method may return null if the view is a child of the RecyclerView but 78117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * not a child of the LayoutManager (e.g. running a disappear animation). 78127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 78137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param view The view that is a descendant of the LayoutManager. 78147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 78157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The direct child of the LayoutManager which contains the given view or null if 78167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the provided view is not a descendant of this LayoutManager. 78177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 78187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see RecyclerView#getChildViewHolder(View) 78197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see RecyclerView#findContainingViewHolder(View) 78207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 78217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Nullable 78227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public View findContainingItemView(View view) { 78237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView == null) { 78247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 78257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 78267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas View found = mRecyclerView.findContainingItemView(view); 78277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (found == null) { 78287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 78297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 78307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mChildHelper.isHidden(found)) { 78317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 78327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 78337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return found; 78347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 78357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 78367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 78377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Finds the view which represents the given adapter position. 78387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 78397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method traverses each child since it has no information about child order. 78407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Override this method to improve performance if your LayoutManager keeps data about 78417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * child views. 78427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 78437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If a view is ignored via {@link #ignoreView(View)}, it is also ignored by this method. 78447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 78457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param position Position of the item in adapter 78467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The child view that represents the given position or null if the position is not 78477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * laid out 78487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 78497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public View findViewByPosition(int position) { 78507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childCount = getChildCount(); 78517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < childCount; i++) { 78527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas View child = getChildAt(i); 78537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder vh = getChildViewHolderInt(child); 78547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (vh == null) { 78557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas continue; 78567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 78577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (vh.getLayoutPosition() == position && !vh.shouldIgnore() 78587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && (mRecyclerView.mState.isPreLayout() || !vh.isRemoved())) { 78597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return child; 78607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 78617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 78627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 78637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 78647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 78657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 78667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Temporarily detach a child view. 78677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 78687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>LayoutManagers may want to perform a lightweight detach operation to rearrange 78697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * views currently attached to the RecyclerView. Generally LayoutManager implementations 78707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * will want to use {@link #detachAndScrapView(android.view.View, RecyclerView.Recycler)} 78717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * so that the detached view may be rebound and reused.</p> 78727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 78737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>If a LayoutManager uses this method to detach a view, it <em>must</em> 78747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #attachView(android.view.View, int, RecyclerView.LayoutParams) reattach} 78757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * or {@link #removeDetachedView(android.view.View) fully remove} the detached view 78767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * before the LayoutManager entry point method called by RecyclerView returns.</p> 78777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 78787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child to detach 78797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 78807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void detachView(View child) { 78817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int ind = mChildHelper.indexOfChild(child); 78827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (ind >= 0) { 78837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas detachViewInternal(ind, child); 78847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 78857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 78867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 78877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 78887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Temporarily detach a child view. 78897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 78907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>LayoutManagers may want to perform a lightweight detach operation to rearrange 78917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * views currently attached to the RecyclerView. Generally LayoutManager implementations 78927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * will want to use {@link #detachAndScrapView(android.view.View, RecyclerView.Recycler)} 78937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * so that the detached view may be rebound and reused.</p> 78947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 78957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>If a LayoutManager uses this method to detach a view, it <em>must</em> 78967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #attachView(android.view.View, int, RecyclerView.LayoutParams) reattach} 78977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * or {@link #removeDetachedView(android.view.View) fully remove} the detached view 78987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * before the LayoutManager entry point method called by RecyclerView returns.</p> 78997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 79007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param index Index of the child to detach 79017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 79027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void detachViewAt(int index) { 79037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas detachViewInternal(index, getChildAt(index)); 79047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 79057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 79067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void detachViewInternal(int index, View view) { 79077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DISPATCH_TEMP_DETACH) { 79087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas view.dispatchStartTemporaryDetach(); 79097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 79107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChildHelper.detachViewFromParent(index); 79117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 79127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 79137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 79147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Reattach a previously {@link #detachView(android.view.View) detached} view. 79157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method should not be used to reattach views that were previously 79167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #detachAndScrapView(android.view.View, RecyclerView.Recycler)} scrapped}. 79177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 79187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child to reattach 79197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param index Intended child index for child 79207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param lp LayoutParams for child 79217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 79227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void attachView(View child, int index, LayoutParams lp) { 79237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder vh = getChildViewHolderInt(child); 79247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (vh.isRemoved()) { 79257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.mViewInfoStore.addToDisappearedInLayout(vh); 79267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 79277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.mViewInfoStore.removeFromDisappearedInLayout(vh); 79287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 79297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChildHelper.attachViewToParent(child, index, lp, vh.isRemoved()); 79307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DISPATCH_TEMP_DETACH) { 79317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas child.dispatchFinishTemporaryDetach(); 79327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 79337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 79347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 79357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 79367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Reattach a previously {@link #detachView(android.view.View) detached} view. 79377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method should not be used to reattach views that were previously 79387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #detachAndScrapView(android.view.View, RecyclerView.Recycler)} scrapped}. 79397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 79407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child to reattach 79417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param index Intended child index for child 79427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 79437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void attachView(View child, int index) { 79447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas attachView(child, index, (LayoutParams) child.getLayoutParams()); 79457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 79467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 79477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 79487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Reattach a previously {@link #detachView(android.view.View) detached} view. 79497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method should not be used to reattach views that were previously 79507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #detachAndScrapView(android.view.View, RecyclerView.Recycler)} scrapped}. 79517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 79527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child to reattach 79537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 79547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void attachView(View child) { 79557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas attachView(child, -1); 79567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 79577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 79587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 79597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Finish removing a view that was previously temporarily 79607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #detachView(android.view.View) detached}. 79617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 79627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Detached child to remove 79637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 79647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void removeDetachedView(View child) { 79657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.removeDetachedView(child, false); 79667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 79677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 79687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 79697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Moves a View from one position to another. 79707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 79717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param fromIndex The View's initial index 79727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param toIndex The View's target index 79737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 79747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void moveView(int fromIndex, int toIndex) { 79757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas View view = getChildAt(fromIndex); 79767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (view == null) { 79777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalArgumentException("Cannot move a child from non-existing index:" 79787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + fromIndex); 79797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 79807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas detachViewAt(fromIndex); 79817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas attachView(view, toIndex); 79827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 79837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 79847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 79857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Detach a child view and add it to a {@link Recycler Recycler's} scrap heap. 79867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 79877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Scrapping a view allows it to be rebound and reused to show updated or 79887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * different data.</p> 79897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 79907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child to detach and scrap 79917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler Recycler to deposit the new scrap view into 79927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 79937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void detachAndScrapView(View child, Recycler recycler) { 79947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int index = mChildHelper.indexOfChild(child); 79957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas scrapOrRecycleView(recycler, index, child); 79967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 79977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 79987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 79997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Detach a child view and add it to a {@link Recycler Recycler's} scrap heap. 80007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 80017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Scrapping a view allows it to be rebound and reused to show updated or 80027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * different data.</p> 80037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 80047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param index Index of child to detach and scrap 80057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler Recycler to deposit the new scrap view into 80067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 80077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void detachAndScrapViewAt(int index, Recycler recycler) { 80087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View child = getChildAt(index); 80097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas scrapOrRecycleView(recycler, index, child); 80107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 80117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 80127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 80137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Remove a child view and recycle it using the given Recycler. 80147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 80157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child to remove and recycle 80167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler Recycler to use to recycle child 80177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 80187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void removeAndRecycleView(View child, Recycler recycler) { 80197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas removeView(child); 80207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recycler.recycleView(child); 80217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 80227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 80237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 80247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Remove a child view and recycle it using the given Recycler. 80257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 80267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param index Index of child to remove and recycle 80277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler Recycler to use to recycle child 80287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 80297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void removeAndRecycleViewAt(int index, Recycler recycler) { 80307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View view = getChildAt(index); 80317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas removeViewAt(index); 80327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recycler.recycleView(view); 80337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 80347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 80357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 80367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Return the current number of child views attached to the parent RecyclerView. 80377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This does not include child views that were temporarily detached and/or scrapped. 80387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 80397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Number of attached children 80407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 80417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getChildCount() { 80427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mChildHelper != null ? mChildHelper.getChildCount() : 0; 80437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 80447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 80457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 80467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Return the child view at the given index 80477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param index Index of child to return 80487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Child view at index 80497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 80507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public View getChildAt(int index) { 80517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mChildHelper != null ? mChildHelper.getChildAt(index) : null; 80527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 80537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 80547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 80557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Return the width measurement spec mode of the RecyclerView. 80567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 80577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This value is set only if the LayoutManager opts into the auto measure api via 80587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #setAutoMeasureEnabled(boolean)}. 80597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 80607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * When RecyclerView is running a layout, this value is always set to 80617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link View.MeasureSpec#EXACTLY} even if it was measured with a different spec mode. 80627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 80637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Width measure spec mode. 80647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 80657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see View.MeasureSpec#getMode(int) 80667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see View#onMeasure(int, int) 80677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 80687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getWidthMode() { 80697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mWidthMode; 80707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 80717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 80727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 80737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Return the height measurement spec mode of the RecyclerView. 80747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 80757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This value is set only if the LayoutManager opts into the auto measure api via 80767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #setAutoMeasureEnabled(boolean)}. 80777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 80787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * When RecyclerView is running a layout, this value is always set to 80797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link View.MeasureSpec#EXACTLY} even if it was measured with a different spec mode. 80807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 80817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Height measure spec mode. 80827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 80837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see View.MeasureSpec#getMode(int) 80847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see View#onMeasure(int, int) 80857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 80867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getHeightMode() { 80877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mHeightMode; 80887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 80897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 80907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 80917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Return the width of the parent RecyclerView 80927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 80937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Width in pixels 80947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 80957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getWidth() { 80967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mWidth; 80977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 80987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 80997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 81007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Return the height of the parent RecyclerView 81017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 81027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Height in pixels 81037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 81047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getHeight() { 81057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mHeight; 81067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 81077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 81087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 81097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Return the left padding of the parent RecyclerView 81107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 81117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Padding in pixels 81127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 81137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getPaddingLeft() { 81147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mRecyclerView != null ? mRecyclerView.getPaddingLeft() : 0; 81157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 81167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 81177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 81187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Return the top padding of the parent RecyclerView 81197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 81207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Padding in pixels 81217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 81227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getPaddingTop() { 81237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mRecyclerView != null ? mRecyclerView.getPaddingTop() : 0; 81247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 81257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 81267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 81277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Return the right padding of the parent RecyclerView 81287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 81297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Padding in pixels 81307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 81317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getPaddingRight() { 81327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mRecyclerView != null ? mRecyclerView.getPaddingRight() : 0; 81337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 81347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 81357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 81367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Return the bottom padding of the parent RecyclerView 81377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 81387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Padding in pixels 81397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 81407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getPaddingBottom() { 81417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mRecyclerView != null ? mRecyclerView.getPaddingBottom() : 0; 81427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 81437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 81447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 81457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Return the start padding of the parent RecyclerView 81467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 81477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Padding in pixels 81487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 81497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getPaddingStart() { 81507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mRecyclerView != null ? mRecyclerView.getPaddingStart() : 0; 81517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 81527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 81537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 81547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Return the end padding of the parent RecyclerView 81557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 81567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Padding in pixels 81577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 81587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getPaddingEnd() { 81597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mRecyclerView != null ? mRecyclerView.getPaddingEnd() : 0; 81607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 81617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 81627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 81637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns true if the RecyclerView this LayoutManager is bound to has focus. 81647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 81657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return True if the RecyclerView has focus, false otherwise. 81667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see View#isFocused() 81677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 81687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean isFocused() { 81697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mRecyclerView != null && mRecyclerView.isFocused(); 81707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 81717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 81727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 81737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns true if the RecyclerView this LayoutManager is bound to has or contains focus. 81747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 81757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if the RecyclerView has or contains focus 81767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see View#hasFocus() 81777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 81787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean hasFocus() { 81797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mRecyclerView != null && mRecyclerView.hasFocus(); 81807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 81817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 81827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 81837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the item View which has or contains focus. 81847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 81857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return A direct child of RecyclerView which has focus or contains the focused child. 81867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 81877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public View getFocusedChild() { 81887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView == null) { 81897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 81907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 81917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View focused = mRecyclerView.getFocusedChild(); 81927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (focused == null || mChildHelper.isHidden(focused)) { 81937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 81947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 81957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return focused; 81967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 81977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 81987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 81997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the number of items in the adapter bound to the parent RecyclerView. 82007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 82017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that this number is not necessarily equal to 82027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link State#getItemCount() State#getItemCount()}. In methods where {@link State} is 82037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * available, you should use {@link State#getItemCount() State#getItemCount()} instead. 82047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * For more details, check the documentation for 82057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link State#getItemCount() State#getItemCount()}. 82067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 82077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The number of items in the bound adapter 82087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see State#getItemCount() 82097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 82107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getItemCount() { 82117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final Adapter a = mRecyclerView != null ? mRecyclerView.getAdapter() : null; 82127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return a != null ? a.getItemCount() : 0; 82137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 82147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 82157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 82167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Offset all child views attached to the parent RecyclerView by dx pixels along 82177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the horizontal axis. 82187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 82197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dx Pixels to offset by 82207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 82217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void offsetChildrenHorizontal(int dx) { 82227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView != null) { 82237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.offsetChildrenHorizontal(dx); 82247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 82257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 82267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 82277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 82287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Offset all child views attached to the parent RecyclerView by dy pixels along 82297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the vertical axis. 82307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 82317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dy Pixels to offset by 82327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 82337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void offsetChildrenVertical(int dy) { 82347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView != null) { 82357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.offsetChildrenVertical(dy); 82367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 82377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 82387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 82397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 82407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Flags a view so that it will not be scrapped or recycled. 82417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 82427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Scope of ignoring a child is strictly restricted to position tracking, scrapping and 82437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * recyling. Methods like {@link #removeAndRecycleAllViews(Recycler)} will ignore the child 82447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * whereas {@link #removeAllViews()} or {@link #offsetChildrenHorizontal(int)} will not 82457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ignore the child. 82467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 82477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Before this child can be recycled again, you have to call 82487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #stopIgnoringView(View)}. 82497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 82507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * You can call this method only if your LayoutManger is in onLayout or onScroll callback. 82517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 82527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param view View to ignore. 82537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #stopIgnoringView(View) 82547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 82557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void ignoreView(View view) { 82567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (view.getParent() != mRecyclerView || mRecyclerView.indexOfChild(view) == -1) { 82577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // checking this because calling this method on a recycled or detached view may 82587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // cause loss of state. 82597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalArgumentException("View should be fully attached to be ignored"); 82607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 82617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder vh = getChildViewHolderInt(view); 82627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas vh.addFlags(ViewHolder.FLAG_IGNORE); 82637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.mViewInfoStore.removeViewHolder(vh); 82647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 82657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 82667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 82677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * View can be scrapped and recycled again. 82687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 82697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that calling this method removes all information in the view holder. 82707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 82717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * You can call this method only if your LayoutManger is in onLayout or onScroll callback. 82727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 82737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param view View to ignore. 82747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 82757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void stopIgnoringView(View view) { 82767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder vh = getChildViewHolderInt(view); 82777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas vh.stopIgnoring(); 82787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas vh.resetInternal(); 82797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas vh.addFlags(ViewHolder.FLAG_INVALID); 82807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 82817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 82827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 82837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Temporarily detach and scrap all currently attached child views. Views will be scrapped 82847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * into the given Recycler. The Recycler may prefer to reuse scrap views before 82857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * other views that were previously recycled. 82867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 82877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler Recycler to scrap views into 82887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 82897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void detachAndScrapAttachedViews(Recycler recycler) { 82907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childCount = getChildCount(); 82917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = childCount - 1; i >= 0; i--) { 82927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View v = getChildAt(i); 82937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas scrapOrRecycleView(recycler, i, v); 82947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 82957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 82967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 82977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void scrapOrRecycleView(Recycler recycler, int index, View view) { 82987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder viewHolder = getChildViewHolderInt(view); 82997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (viewHolder.shouldIgnore()) { 83007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 83017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.d(TAG, "ignoring view " + viewHolder); 83027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 83037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 83047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 83057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (viewHolder.isInvalid() && !viewHolder.isRemoved() 83067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && !mRecyclerView.mAdapter.hasStableIds()) { 83077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas removeViewAt(index); 83087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recycler.recycleViewHolderInternal(viewHolder); 83097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 83107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas detachViewAt(index); 83117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recycler.scrapView(view); 83127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.mViewInfoStore.onViewDetached(viewHolder); 83137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 83147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 83157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 83167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 83177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Recycles the scrapped views. 83187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 83197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * When a view is detached and removed, it does not trigger a ViewGroup invalidate. This is 83207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the expected behavior if scrapped views are used for animations. Otherwise, we need to 83217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * call remove and invalidate RecyclerView to ensure UI update. 83227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 83237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler Recycler 83247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 83257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void removeAndRecycleScrapInt(Recycler recycler) { 83267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int scrapCount = recycler.getScrapCount(); 83277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Loop backward, recycler might be changed by removeDetachedView() 83287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = scrapCount - 1; i >= 0; i--) { 83297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View scrap = recycler.getScrapViewAt(i); 83307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder vh = getChildViewHolderInt(scrap); 83317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (vh.shouldIgnore()) { 83327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas continue; 83337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 83347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // If the scrap view is animating, we need to cancel them first. If we cancel it 83357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // here, ItemAnimator callback may recycle it which will cause double recycling. 83367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // To avoid this, we mark it as not recycleable before calling the item animator. 83377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Since removeDetachedView calls a user API, a common mistake (ending animations on 83387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // the view) may recycle it too, so we guard it before we call user APIs. 83397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas vh.setIsRecyclable(false); 83407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (vh.isTmpDetached()) { 83417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.removeDetachedView(scrap, false); 83427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 83437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView.mItemAnimator != null) { 83447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.mItemAnimator.endAnimation(vh); 83457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 83467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas vh.setIsRecyclable(true); 83477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recycler.quickRecycleScrapView(scrap); 83487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 83497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recycler.clearScrap(); 83507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (scrapCount > 0) { 83517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.invalidate(); 83527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 83537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 83547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 83557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 83567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 83577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Measure a child view using standard measurement policy, taking the padding 83587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * of the parent RecyclerView and any added item decorations into account. 83597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 83607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>If the RecyclerView can be scrolled in either dimension the caller may 83617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * pass 0 as the widthUsed or heightUsed parameters as they will be irrelevant.</p> 83627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 83637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child view to measure 83647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param widthUsed Width in pixels currently consumed by other views, if relevant 83657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param heightUsed Height in pixels currently consumed by other views, if relevant 83667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 83677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void measureChild(View child, int widthUsed, int heightUsed) { 83687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 83697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 83707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final Rect insets = mRecyclerView.getItemDecorInsetsForChild(child); 83717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas widthUsed += insets.left + insets.right; 83727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas heightUsed += insets.top + insets.bottom; 83737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int widthSpec = getChildMeasureSpec(getWidth(), getWidthMode(), 83747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas getPaddingLeft() + getPaddingRight() + widthUsed, lp.width, 83757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas canScrollHorizontally()); 83767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int heightSpec = getChildMeasureSpec(getHeight(), getHeightMode(), 83777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas getPaddingTop() + getPaddingBottom() + heightUsed, lp.height, 83787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas canScrollVertically()); 83797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (shouldMeasureChild(child, widthSpec, heightSpec, lp)) { 83807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas child.measure(widthSpec, heightSpec); 83817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 83827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 83837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 83847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 83857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView internally does its own View measurement caching which should help with 83867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * WRAP_CONTENT. 83877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 83887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Use this method if the View is already measured once in this layout pass. 83897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 83907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean shouldReMeasureChild(View child, int widthSpec, int heightSpec, LayoutParams lp) { 83917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return !mMeasurementCacheEnabled 83927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || !isMeasurementUpToDate(child.getMeasuredWidth(), widthSpec, lp.width) 83937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || !isMeasurementUpToDate(child.getMeasuredHeight(), heightSpec, lp.height); 83947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 83957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 83967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // we may consider making this public 83977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 83987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView internally does its own View measurement caching which should help with 83997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * WRAP_CONTENT. 84007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 84017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Use this method if the View is not yet measured and you need to decide whether to 84027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * measure this View or not. 84037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 84047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean shouldMeasureChild(View child, int widthSpec, int heightSpec, LayoutParams lp) { 84057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return child.isLayoutRequested() 84067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || !mMeasurementCacheEnabled 84077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || !isMeasurementUpToDate(child.getWidth(), widthSpec, lp.width) 84087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || !isMeasurementUpToDate(child.getHeight(), heightSpec, lp.height); 84097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 84107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 84117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 84127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * In addition to the View Framework's measurement cache, RecyclerView uses its own 84137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * additional measurement cache for its children to avoid re-measuring them when not 84147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * necessary. It is on by default but it can be turned off via 84157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #setMeasurementCacheEnabled(boolean)}. 84167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 84177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return True if measurement cache is enabled, false otherwise. 84187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 84197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #setMeasurementCacheEnabled(boolean) 84207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 84217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean isMeasurementCacheEnabled() { 84227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mMeasurementCacheEnabled; 84237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 84247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 84257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 84267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Sets whether RecyclerView should use its own measurement cache for the children. This is 84277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * a more aggressive cache than the framework uses. 84287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 84297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param measurementCacheEnabled True to enable the measurement cache, false otherwise. 84307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 84317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #isMeasurementCacheEnabled() 84327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 84337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setMeasurementCacheEnabled(boolean measurementCacheEnabled) { 84347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mMeasurementCacheEnabled = measurementCacheEnabled; 84357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 84367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 84377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private static boolean isMeasurementUpToDate(int childSize, int spec, int dimension) { 84387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int specMode = MeasureSpec.getMode(spec); 84397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int specSize = MeasureSpec.getSize(spec); 84407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (dimension > 0 && childSize != dimension) { 84417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 84427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 84437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas switch (specMode) { 84447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case MeasureSpec.UNSPECIFIED: 84457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return true; 84467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case MeasureSpec.AT_MOST: 84477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return specSize >= childSize; 84487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case MeasureSpec.EXACTLY: 84497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return specSize == childSize; 84507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 84517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 84527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 84537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 84547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 84557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Measure a child view using standard measurement policy, taking the padding 84567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * of the parent RecyclerView, any added item decorations and the child margins 84577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * into account. 84587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 84597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>If the RecyclerView can be scrolled in either dimension the caller may 84607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * pass 0 as the widthUsed or heightUsed parameters as they will be irrelevant.</p> 84617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 84627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child view to measure 84637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param widthUsed Width in pixels currently consumed by other views, if relevant 84647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param heightUsed Height in pixels currently consumed by other views, if relevant 84657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 84667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void measureChildWithMargins(View child, int widthUsed, int heightUsed) { 84677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 84687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 84697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final Rect insets = mRecyclerView.getItemDecorInsetsForChild(child); 84707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas widthUsed += insets.left + insets.right; 84717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas heightUsed += insets.top + insets.bottom; 84727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 84737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int widthSpec = getChildMeasureSpec(getWidth(), getWidthMode(), 84747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas getPaddingLeft() + getPaddingRight() 84757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + lp.leftMargin + lp.rightMargin + widthUsed, lp.width, 84767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas canScrollHorizontally()); 84777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int heightSpec = getChildMeasureSpec(getHeight(), getHeightMode(), 84787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas getPaddingTop() + getPaddingBottom() 84797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + lp.topMargin + lp.bottomMargin + heightUsed, lp.height, 84807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas canScrollVertically()); 84817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (shouldMeasureChild(child, widthSpec, heightSpec, lp)) { 84827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas child.measure(widthSpec, heightSpec); 84837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 84847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 84857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 84867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 84877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Calculate a MeasureSpec value for measuring a child view in one dimension. 84887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 84897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param parentSize Size of the parent view where the child will be placed 84907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param padding Total space currently consumed by other elements of the parent 84917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param childDimension Desired size of the child view, or MATCH_PARENT/WRAP_CONTENT. 84927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Generally obtained from the child view's LayoutParams 84937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param canScroll true if the parent RecyclerView can scroll in this dimension 84947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 84957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return a MeasureSpec value for the child view 84967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @deprecated use {@link #getChildMeasureSpec(int, int, int, int, boolean)} 84977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 84987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Deprecated 84997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static int getChildMeasureSpec(int parentSize, int padding, int childDimension, 85007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean canScroll) { 85017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int size = Math.max(0, parentSize - padding); 85027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int resultSize = 0; 85037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int resultMode = 0; 85047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (canScroll) { 85057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (childDimension >= 0) { 85067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultSize = childDimension; 85077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultMode = MeasureSpec.EXACTLY; 85087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 85097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // MATCH_PARENT can't be applied since we can scroll in this dimension, wrap 85107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // instead using UNSPECIFIED. 85117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultSize = 0; 85127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultMode = MeasureSpec.UNSPECIFIED; 85137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 85147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 85157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (childDimension >= 0) { 85167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultSize = childDimension; 85177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultMode = MeasureSpec.EXACTLY; 85187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (childDimension == LayoutParams.MATCH_PARENT) { 85197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultSize = size; 85207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // TODO this should be my spec. 85217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultMode = MeasureSpec.EXACTLY; 85227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (childDimension == LayoutParams.WRAP_CONTENT) { 85237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultSize = size; 85247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultMode = MeasureSpec.AT_MOST; 85257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 85267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 85277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return MeasureSpec.makeMeasureSpec(resultSize, resultMode); 85287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 85297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 85307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 85317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Calculate a MeasureSpec value for measuring a child view in one dimension. 85327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 85337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param parentSize Size of the parent view where the child will be placed 85347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param parentMode The measurement spec mode of the parent 85357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param padding Total space currently consumed by other elements of parent 85367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param childDimension Desired size of the child view, or MATCH_PARENT/WRAP_CONTENT. 85377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Generally obtained from the child view's LayoutParams 85387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param canScroll true if the parent RecyclerView can scroll in this dimension 85397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 85407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return a MeasureSpec value for the child view 85417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 85427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static int getChildMeasureSpec(int parentSize, int parentMode, int padding, 85437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int childDimension, boolean canScroll) { 85447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int size = Math.max(0, parentSize - padding); 85457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int resultSize = 0; 85467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int resultMode = 0; 85477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (canScroll) { 85487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (childDimension >= 0) { 85497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultSize = childDimension; 85507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultMode = MeasureSpec.EXACTLY; 85517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (childDimension == LayoutParams.MATCH_PARENT) { 85527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas switch (parentMode) { 85537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case MeasureSpec.AT_MOST: 85547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case MeasureSpec.EXACTLY: 85557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultSize = size; 85567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultMode = parentMode; 85577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas break; 85587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case MeasureSpec.UNSPECIFIED: 85597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultSize = 0; 85607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultMode = MeasureSpec.UNSPECIFIED; 85617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas break; 85627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 85637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (childDimension == LayoutParams.WRAP_CONTENT) { 85647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultSize = 0; 85657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultMode = MeasureSpec.UNSPECIFIED; 85667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 85677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 85687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (childDimension >= 0) { 85697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultSize = childDimension; 85707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultMode = MeasureSpec.EXACTLY; 85717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (childDimension == LayoutParams.MATCH_PARENT) { 85727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultSize = size; 85737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultMode = parentMode; 85747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (childDimension == LayoutParams.WRAP_CONTENT) { 85757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultSize = size; 85767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (parentMode == MeasureSpec.AT_MOST || parentMode == MeasureSpec.EXACTLY) { 85777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultMode = MeasureSpec.AT_MOST; 85787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 85797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas resultMode = MeasureSpec.UNSPECIFIED; 85807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 85817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 85827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 85837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 85847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas //noinspection WrongConstant 85857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return MeasureSpec.makeMeasureSpec(resultSize, resultMode); 85867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 85877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 85887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 85897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the measured width of the given child, plus the additional size of 85907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * any insets applied by {@link ItemDecoration ItemDecorations}. 85917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 85927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child view to query 85937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return child's measured width plus <code>ItemDecoration</code> insets 85947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 85957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see View#getMeasuredWidth() 85967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 85977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getDecoratedMeasuredWidth(View child) { 85987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final Rect insets = ((LayoutParams) child.getLayoutParams()).mDecorInsets; 85997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return child.getMeasuredWidth() + insets.left + insets.right; 86007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 86017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 86027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 86037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the measured height of the given child, plus the additional size of 86047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * any insets applied by {@link ItemDecoration ItemDecorations}. 86057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 86067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child view to query 86077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return child's measured height plus <code>ItemDecoration</code> insets 86087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 86097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see View#getMeasuredHeight() 86107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 86117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getDecoratedMeasuredHeight(View child) { 86127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final Rect insets = ((LayoutParams) child.getLayoutParams()).mDecorInsets; 86137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return child.getMeasuredHeight() + insets.top + insets.bottom; 86147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 86157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 86167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 86177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Lay out the given child view within the RecyclerView using coordinates that 86187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * include any current {@link ItemDecoration ItemDecorations}. 86197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 86207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>LayoutManagers should prefer working in sizes and coordinates that include 86217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * item decoration insets whenever possible. This allows the LayoutManager to effectively 86227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ignore decoration insets within measurement and layout code. See the following 86237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * methods:</p> 86247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <ul> 86257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>{@link #layoutDecoratedWithMargins(View, int, int, int, int)}</li> 86267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>{@link #getDecoratedBoundsWithMargins(View, Rect)}</li> 86277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>{@link #measureChild(View, int, int)}</li> 86287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>{@link #measureChildWithMargins(View, int, int)}</li> 86297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>{@link #getDecoratedLeft(View)}</li> 86307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>{@link #getDecoratedTop(View)}</li> 86317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>{@link #getDecoratedRight(View)}</li> 86327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>{@link #getDecoratedBottom(View)}</li> 86337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>{@link #getDecoratedMeasuredWidth(View)}</li> 86347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>{@link #getDecoratedMeasuredHeight(View)}</li> 86357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * </ul> 86367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 86377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child to lay out 86387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param left Left edge, with item decoration insets included 86397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param top Top edge, with item decoration insets included 86407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param right Right edge, with item decoration insets included 86417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param bottom Bottom edge, with item decoration insets included 86427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 86437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see View#layout(int, int, int, int) 86447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #layoutDecoratedWithMargins(View, int, int, int, int) 86457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 86467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void layoutDecorated(View child, int left, int top, int right, int bottom) { 86477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final Rect insets = ((LayoutParams) child.getLayoutParams()).mDecorInsets; 86487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas child.layout(left + insets.left, top + insets.top, right - insets.right, 86497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas bottom - insets.bottom); 86507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 86517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 86527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 86537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Lay out the given child view within the RecyclerView using coordinates that 86547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * include any current {@link ItemDecoration ItemDecorations} and margins. 86557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 86567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>LayoutManagers should prefer working in sizes and coordinates that include 86577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * item decoration insets whenever possible. This allows the LayoutManager to effectively 86587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ignore decoration insets within measurement and layout code. See the following 86597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * methods:</p> 86607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <ul> 86617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>{@link #layoutDecorated(View, int, int, int, int)}</li> 86627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>{@link #measureChild(View, int, int)}</li> 86637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>{@link #measureChildWithMargins(View, int, int)}</li> 86647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>{@link #getDecoratedLeft(View)}</li> 86657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>{@link #getDecoratedTop(View)}</li> 86667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>{@link #getDecoratedRight(View)}</li> 86677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>{@link #getDecoratedBottom(View)}</li> 86687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>{@link #getDecoratedMeasuredWidth(View)}</li> 86697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>{@link #getDecoratedMeasuredHeight(View)}</li> 86707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * </ul> 86717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 86727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child to lay out 86737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param left Left edge, with item decoration insets and left margin included 86747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param top Top edge, with item decoration insets and top margin included 86757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param right Right edge, with item decoration insets and right margin included 86767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param bottom Bottom edge, with item decoration insets and bottom margin included 86777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 86787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see View#layout(int, int, int, int) 86797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #layoutDecorated(View, int, int, int, int) 86807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 86817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void layoutDecoratedWithMargins(View child, int left, int top, int right, 86827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int bottom) { 86837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 86847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final Rect insets = lp.mDecorInsets; 86857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas child.layout(left + insets.left + lp.leftMargin, top + insets.top + lp.topMargin, 86867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas right - insets.right - lp.rightMargin, 86877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas bottom - insets.bottom - lp.bottomMargin); 86887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 86897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 86907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 86917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Calculates the bounding box of the View while taking into account its matrix changes 86927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * (translation, scale etc) with respect to the RecyclerView. 86937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 86947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If {@code includeDecorInsets} is {@code true}, they are applied first before applying 86957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the View's matrix so that the decor offsets also go through the same transformation. 86967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 86977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child The ItemView whose bounding box should be calculated. 86987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param includeDecorInsets True if the decor insets should be included in the bounding box 86997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param out The rectangle into which the output will be written. 87007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 87017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void getTransformedBoundingBox(View child, boolean includeDecorInsets, Rect out) { 87027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (includeDecorInsets) { 87037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Rect insets = ((LayoutParams) child.getLayoutParams()).mDecorInsets; 87047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas out.set(-insets.left, -insets.top, 87057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas child.getWidth() + insets.right, child.getHeight() + insets.bottom); 87067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 87077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas out.set(0, 0, child.getWidth(), child.getHeight()); 87087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 87097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 87107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView != null) { 87117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final Matrix childMatrix = child.getMatrix(); 87127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (childMatrix != null && !childMatrix.isIdentity()) { 87137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final RectF tempRectF = mRecyclerView.mTempRectF; 87147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas tempRectF.set(out); 87157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas childMatrix.mapRect(tempRectF); 87167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas out.set( 87177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas (int) Math.floor(tempRectF.left), 87187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas (int) Math.floor(tempRectF.top), 87197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas (int) Math.ceil(tempRectF.right), 87207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas (int) Math.ceil(tempRectF.bottom) 87217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ); 87227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 87237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 87247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas out.offset(child.getLeft(), child.getTop()); 87257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 87267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 87277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 87287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the bounds of the view including its decoration and margins. 87297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 87307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param view The view element to check 87317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param outBounds A rect that will receive the bounds of the element including its 87327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * decoration and margins. 87337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 87347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void getDecoratedBoundsWithMargins(View view, Rect outBounds) { 87357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas RecyclerView.getDecoratedBoundsWithMarginsInt(view, outBounds); 87367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 87377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 87387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 87397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the left edge of the given child view within its parent, offset by any applied 87407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link ItemDecoration ItemDecorations}. 87417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 87427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child to query 87437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Child left edge with offsets applied 87447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #getLeftDecorationWidth(View) 87457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 87467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getDecoratedLeft(View child) { 87477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return child.getLeft() - getLeftDecorationWidth(child); 87487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 87497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 87507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 87517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the top edge of the given child view within its parent, offset by any applied 87527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link ItemDecoration ItemDecorations}. 87537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 87547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child to query 87557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Child top edge with offsets applied 87567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #getTopDecorationHeight(View) 87577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 87587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getDecoratedTop(View child) { 87597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return child.getTop() - getTopDecorationHeight(child); 87607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 87617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 87627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 87637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the right edge of the given child view within its parent, offset by any applied 87647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link ItemDecoration ItemDecorations}. 87657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 87667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child to query 87677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Child right edge with offsets applied 87687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #getRightDecorationWidth(View) 87697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 87707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getDecoratedRight(View child) { 87717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return child.getRight() + getRightDecorationWidth(child); 87727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 87737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 87747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 87757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the bottom edge of the given child view within its parent, offset by any applied 87767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link ItemDecoration ItemDecorations}. 87777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 87787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child to query 87797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Child bottom edge with offsets applied 87807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #getBottomDecorationHeight(View) 87817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 87827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getDecoratedBottom(View child) { 87837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return child.getBottom() + getBottomDecorationHeight(child); 87847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 87857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 87867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 87877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Calculates the item decor insets applied to the given child and updates the provided 87887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Rect instance with the inset values. 87897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <ul> 87907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>The Rect's left is set to the total width of left decorations.</li> 87917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>The Rect's top is set to the total height of top decorations.</li> 87927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>The Rect's right is set to the total width of right decorations.</li> 87937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <li>The Rect's bottom is set to total height of bottom decorations.</li> 87947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * </ul> 87957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 87967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that item decorations are automatically calculated when one of the LayoutManager's 87977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * measure child methods is called. If you need to measure the child with custom specs via 87987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link View#measure(int, int)}, you can use this method to get decorations. 87997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 88007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child The child view whose decorations should be calculated 88017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param outRect The Rect to hold result values 88027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 88037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void calculateItemDecorationsForChild(View child, Rect outRect) { 88047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView == null) { 88057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas outRect.set(0, 0, 0, 0); 88067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 88077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 88087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Rect insets = mRecyclerView.getItemDecorInsetsForChild(child); 88097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas outRect.set(insets); 88107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 88117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 88127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 88137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the total height of item decorations applied to child's top. 88147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 88157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that this value is not updated until the View is measured or 88167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #calculateItemDecorationsForChild(View, Rect)} is called. 88177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 88187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child to query 88197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The total height of item decorations applied to the child's top. 88207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #getDecoratedTop(View) 88217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #calculateItemDecorationsForChild(View, Rect) 88227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 88237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getTopDecorationHeight(View child) { 88247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return ((LayoutParams) child.getLayoutParams()).mDecorInsets.top; 88257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 88267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 88277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 88287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the total height of item decorations applied to child's bottom. 88297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 88307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that this value is not updated until the View is measured or 88317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #calculateItemDecorationsForChild(View, Rect)} is called. 88327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 88337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child to query 88347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The total height of item decorations applied to the child's bottom. 88357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #getDecoratedBottom(View) 88367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #calculateItemDecorationsForChild(View, Rect) 88377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 88387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getBottomDecorationHeight(View child) { 88397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return ((LayoutParams) child.getLayoutParams()).mDecorInsets.bottom; 88407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 88417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 88427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 88437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the total width of item decorations applied to child's left. 88447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 88457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that this value is not updated until the View is measured or 88467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #calculateItemDecorationsForChild(View, Rect)} is called. 88477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 88487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child to query 88497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The total width of item decorations applied to the child's left. 88507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #getDecoratedLeft(View) 88517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #calculateItemDecorationsForChild(View, Rect) 88527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 88537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getLeftDecorationWidth(View child) { 88547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return ((LayoutParams) child.getLayoutParams()).mDecorInsets.left; 88557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 88567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 88577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 88587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the total width of item decorations applied to child's right. 88597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 88607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that this value is not updated until the View is measured or 88617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #calculateItemDecorationsForChild(View, Rect)} is called. 88627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 88637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Child to query 88647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The total width of item decorations applied to the child's right. 88657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #getDecoratedRight(View) 88667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #calculateItemDecorationsForChild(View, Rect) 88677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 88687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getRightDecorationWidth(View child) { 88697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return ((LayoutParams) child.getLayoutParams()).mDecorInsets.right; 88707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 88717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 88727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 88737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when searching for a focusable view in the given direction has failed 88747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * for the current content of the RecyclerView. 88757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 88767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>This is the LayoutManager's opportunity to populate views in the given direction 88777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to fulfill the request if it can. The LayoutManager should attach and return 88787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the view to be focused. The default implementation returns null.</p> 88797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 88807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param focused The currently focused view 88817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param direction One of {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN}, 88827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link View#FOCUS_LEFT}, {@link View#FOCUS_RIGHT}, 88837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link View#FOCUS_BACKWARD}, {@link View#FOCUS_FORWARD} 88847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * or 0 for not applicable 88857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler The recycler to use for obtaining views for currently offscreen items 88867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state Transient state of RecyclerView 88877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The chosen view to be focused 88887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 88897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Nullable 88907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public View onFocusSearchFailed(View focused, int direction, Recycler recycler, 88917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas State state) { 88927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 88937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 88947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 88957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 88967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method gives a LayoutManager an opportunity to intercept the initial focus search 88977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * before the default behavior of {@link FocusFinder} is used. If this method returns 88987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * null FocusFinder will attempt to find a focusable child view. If it fails 88997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * then {@link #onFocusSearchFailed(View, int, RecyclerView.Recycler, RecyclerView.State)} 89007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * will be called to give the LayoutManager an opportunity to add new views for items 89017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * that did not have attached views representing them. The LayoutManager should not add 89027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * or remove views from this method. 89037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 89047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param focused The currently focused view 89057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param direction One of {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN}, 89067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link View#FOCUS_LEFT}, {@link View#FOCUS_RIGHT}, 89077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link View#FOCUS_BACKWARD}, {@link View#FOCUS_FORWARD} 89087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return A descendant view to focus or null to fall back to default behavior. 89097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The default implementation returns null. 89107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 89117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public View onInterceptFocusSearch(View focused, int direction) { 89127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 89137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 89147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 89157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 89167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when a child of the RecyclerView wants a particular rectangle to be positioned 89177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * onto the screen. See {@link ViewParent#requestChildRectangleOnScreen(android.view.View, 89187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * android.graphics.Rect, boolean)} for more details. 89197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 89207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>The base implementation will attempt to perform a standard programmatic scroll 89217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to bring the given rect into view, within the padded area of the RecyclerView.</p> 89227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 89237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child The direct child making the request. 89247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param rect The rectangle in the child's coordinates the child 89257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * wishes to be on the screen. 89267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param immediate True to forbid animated or delayed scrolling, 89277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * false otherwise 89287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Whether the group scrolled to handle the operation 89297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 89307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean requestChildRectangleOnScreen(RecyclerView parent, View child, Rect rect, 89317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean immediate) { 89327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int parentLeft = getPaddingLeft(); 89337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int parentTop = getPaddingTop(); 89347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int parentRight = getWidth() - getPaddingRight(); 89357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int parentBottom = getHeight() - getPaddingBottom(); 89367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childLeft = child.getLeft() + rect.left - child.getScrollX(); 89377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childTop = child.getTop() + rect.top - child.getScrollY(); 89387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childRight = childLeft + rect.width(); 89397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childBottom = childTop + rect.height(); 89407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 89417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int offScreenLeft = Math.min(0, childLeft - parentLeft); 89427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int offScreenTop = Math.min(0, childTop - parentTop); 89437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int offScreenRight = Math.max(0, childRight - parentRight); 89447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int offScreenBottom = Math.max(0, childBottom - parentBottom); 89457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 89467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Favor the "start" layout direction over the end when bringing one side or the other 89477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // of a large rect into view. If we decide to bring in end because start is already 89487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // visible, limit the scroll such that start won't go out of bounds. 89497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int dx; 89507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) { 89517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dx = offScreenRight != 0 ? offScreenRight 89527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas : Math.max(offScreenLeft, childRight - parentRight); 89537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 89547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dx = offScreenLeft != 0 ? offScreenLeft 89557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas : Math.min(childLeft - parentLeft, offScreenRight); 89567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 89577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 89587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Favor bringing the top into view over the bottom. If top is already visible and 89597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // we should scroll to make bottom visible, make sure top does not go out of bounds. 89607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int dy = offScreenTop != 0 ? offScreenTop 89617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas : Math.min(childTop - parentTop, offScreenBottom); 89627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 89637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (dx != 0 || dy != 0) { 89647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (immediate) { 89657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas parent.scrollBy(dx, dy); 89667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 89677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas parent.smoothScrollBy(dx, dy); 89687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 89697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return true; 89707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 89717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 89727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 89737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 89747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 89757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @deprecated Use {@link #onRequestChildFocus(RecyclerView, State, View, View)} 89767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 89777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Deprecated 89787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean onRequestChildFocus(RecyclerView parent, View child, View focused) { 89797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // eat the request if we are in the middle of a scroll or layout 89807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return isSmoothScrolling() || parent.isComputingLayout(); 89817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 89827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 89837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 89847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when a descendant view of the RecyclerView requests focus. 89857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 89867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>A LayoutManager wishing to keep focused views aligned in a specific 89877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * portion of the view may implement that behavior in an override of this method.</p> 89887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 89897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>If the LayoutManager executes different behavior that should override the default 89907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * behavior of scrolling the focused child on screen instead of running alongside it, 89917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * this method should return true.</p> 89927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 89937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param parent The RecyclerView hosting this LayoutManager 89947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state Current state of RecyclerView 89957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param child Direct child of the RecyclerView containing the newly focused view 89967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param focused The newly focused view. This may be the same view as child or it may be 89977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * null 89987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if the default scroll behavior should be suppressed 89997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 90007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean onRequestChildFocus(RecyclerView parent, State state, View child, 90017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas View focused) { 90027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return onRequestChildFocus(parent, child, focused); 90037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 90047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 90057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 90067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called if the RecyclerView this LayoutManager is bound to has a different adapter set. 90077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The LayoutManager may use this opportunity to clear caches and configure state such 90087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * that it can relayout appropriately with the new data and potentially new view types. 90097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 90107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>The default implementation removes all currently attached views.</p> 90117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 90127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param oldAdapter The previous adapter instance. Will be null if there was previously no 90137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * adapter. 90147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param newAdapter The new adapter instance. Might be null if 90157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #setAdapter(RecyclerView.Adapter)} is called with {@code null}. 90167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 90177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onAdapterChanged(Adapter oldAdapter, Adapter newAdapter) { 90187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 90197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 90207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 90217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called to populate focusable views within the RecyclerView. 90227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 90237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>The LayoutManager implementation should return <code>true</code> if the default 90247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * behavior of {@link ViewGroup#addFocusables(java.util.ArrayList, int)} should be 90257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * suppressed.</p> 90267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 90277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>The default implementation returns <code>false</code> to trigger RecyclerView 90287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to fall back to the default ViewGroup behavior.</p> 90297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 90307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recyclerView The RecyclerView hosting this LayoutManager 90317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param views List of output views. This method should add valid focusable views 90327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to this list. 90337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param direction One of {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN}, 90347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link View#FOCUS_LEFT}, {@link View#FOCUS_RIGHT}, 90357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link View#FOCUS_BACKWARD}, {@link View#FOCUS_FORWARD} 90367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param focusableMode The type of focusables to be added. 90377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 90387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true to suppress the default behavior, false to add default focusables after 90397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * this method returns. 90407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 90417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #FOCUSABLES_ALL 90427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #FOCUSABLES_TOUCH_MODE 90437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 90447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean onAddFocusables(RecyclerView recyclerView, ArrayList<View> views, 90457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int direction, int focusableMode) { 90467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 90477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 90487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 90497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 90507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when {@link Adapter#notifyDataSetChanged()} is triggered instead of giving 90517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * detailed information on what has actually changed. 90527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 90537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recyclerView 90547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 90557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onItemsChanged(RecyclerView recyclerView) { 90567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 90577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 90587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 90597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when items have been added to the adapter. The LayoutManager may choose to 90607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * requestLayout if the inserted items would require refreshing the currently visible set 90617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * of child views. (e.g. currently empty space would be filled by appended items, etc.) 90627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 90637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recyclerView 90647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param positionStart 90657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param itemCount 90667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 90677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onItemsAdded(RecyclerView recyclerView, int positionStart, int itemCount) { 90687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 90697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 90707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 90717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when items have been removed from the adapter. 90727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 90737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recyclerView 90747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param positionStart 90757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param itemCount 90767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 90777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onItemsRemoved(RecyclerView recyclerView, int positionStart, int itemCount) { 90787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 90797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 90807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 90817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when items have been changed in the adapter. 90827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * To receive payload, override {@link #onItemsUpdated(RecyclerView, int, int, Object)} 90837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * instead, then this callback will not be invoked. 90847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 90857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recyclerView 90867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param positionStart 90877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param itemCount 90887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 90897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onItemsUpdated(RecyclerView recyclerView, int positionStart, int itemCount) { 90907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 90917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 90927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 90937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when items have been changed in the adapter and with optional payload. 90947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Default implementation calls {@link #onItemsUpdated(RecyclerView, int, int)}. 90957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 90967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recyclerView 90977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param positionStart 90987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param itemCount 90997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param payload 91007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 91017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onItemsUpdated(RecyclerView recyclerView, int positionStart, int itemCount, 91027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Object payload) { 91037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onItemsUpdated(recyclerView, positionStart, itemCount); 91047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 91057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 91067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 91077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when an item is moved withing the adapter. 91087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 91097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that, an item may also change position in response to another ADD/REMOVE/MOVE 91107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * operation. This callback is only called if and only if {@link Adapter#notifyItemMoved} 91117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * is called. 91127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 91137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recyclerView 91147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param from 91157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param to 91167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param itemCount 91177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 91187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onItemsMoved(RecyclerView recyclerView, int from, int to, int itemCount) { 91197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 91207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 91217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 91227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 91237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 91247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Override this method if you want to support scroll bars.</p> 91257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 91267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Read {@link RecyclerView#computeHorizontalScrollExtent()} for details.</p> 91277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 91287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Default implementation returns 0.</p> 91297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 91307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state Current state of RecyclerView 91317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The horizontal extent of the scrollbar's thumb 91327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see RecyclerView#computeHorizontalScrollExtent() 91337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 91347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int computeHorizontalScrollExtent(State state) { 91357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return 0; 91367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 91377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 91387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 91397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Override this method if you want to support scroll bars.</p> 91407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 91417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Read {@link RecyclerView#computeHorizontalScrollOffset()} for details.</p> 91427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 91437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Default implementation returns 0.</p> 91447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 91457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state Current State of RecyclerView where you can find total item count 91467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The horizontal offset of the scrollbar's thumb 91477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see RecyclerView#computeHorizontalScrollOffset() 91487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 91497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int computeHorizontalScrollOffset(State state) { 91507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return 0; 91517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 91527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 91537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 91547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Override this method if you want to support scroll bars.</p> 91557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 91567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Read {@link RecyclerView#computeHorizontalScrollRange()} for details.</p> 91577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 91587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Default implementation returns 0.</p> 91597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 91607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state Current State of RecyclerView where you can find total item count 91617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The total horizontal range represented by the vertical scrollbar 91627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see RecyclerView#computeHorizontalScrollRange() 91637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 91647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int computeHorizontalScrollRange(State state) { 91657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return 0; 91667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 91677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 91687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 91697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Override this method if you want to support scroll bars.</p> 91707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 91717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Read {@link RecyclerView#computeVerticalScrollExtent()} for details.</p> 91727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 91737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Default implementation returns 0.</p> 91747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 91757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state Current state of RecyclerView 91767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The vertical extent of the scrollbar's thumb 91777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see RecyclerView#computeVerticalScrollExtent() 91787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 91797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int computeVerticalScrollExtent(State state) { 91807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return 0; 91817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 91827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 91837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 91847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Override this method if you want to support scroll bars.</p> 91857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 91867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Read {@link RecyclerView#computeVerticalScrollOffset()} for details.</p> 91877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 91887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Default implementation returns 0.</p> 91897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 91907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state Current State of RecyclerView where you can find total item count 91917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The vertical offset of the scrollbar's thumb 91927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see RecyclerView#computeVerticalScrollOffset() 91937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 91947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int computeVerticalScrollOffset(State state) { 91957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return 0; 91967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 91977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 91987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 91997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Override this method if you want to support scroll bars.</p> 92007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 92017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Read {@link RecyclerView#computeVerticalScrollRange()} for details.</p> 92027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 92037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Default implementation returns 0.</p> 92047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 92057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state Current State of RecyclerView where you can find total item count 92067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The total vertical range represented by the vertical scrollbar 92077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see RecyclerView#computeVerticalScrollRange() 92087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 92097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int computeVerticalScrollRange(State state) { 92107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return 0; 92117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 92127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 92137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 92147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Measure the attached RecyclerView. Implementations must call 92157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #setMeasuredDimension(int, int)} before returning. 92167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 92177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>The default implementation will handle EXACTLY measurements and respect 92187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the minimum width and height properties of the host RecyclerView if measured 92197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * as UNSPECIFIED. AT_MOST measurements will be treated as EXACTLY and the RecyclerView 92207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * will consume all available space.</p> 92217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 92227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler Recycler 92237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state Transient state of RecyclerView 92247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param widthSpec Width {@link android.view.View.MeasureSpec} 92257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param heightSpec Height {@link android.view.View.MeasureSpec} 92267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 92277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onMeasure(Recycler recycler, State state, int widthSpec, int heightSpec) { 92287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.defaultOnMeasure(widthSpec, heightSpec); 92297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 92307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 92317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 92327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link View#setMeasuredDimension(int, int) Set the measured dimensions} of the 92337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * host RecyclerView. 92347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 92357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param widthSize Measured width 92367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param heightSize Measured height 92377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 92387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setMeasuredDimension(int widthSize, int heightSize) { 92397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.setMeasuredDimension(widthSize, heightSize); 92407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 92417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 92427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 92437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The host RecyclerView's {@link View#getMinimumWidth()} 92447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 92457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getMinimumWidth() { 92467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mRecyclerView.getMinimumWidth(); 92477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 92487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 92497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 92507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The host RecyclerView's {@link View#getMinimumHeight()} 92517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 92527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getMinimumHeight() { 92537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mRecyclerView.getMinimumHeight(); 92547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 92557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 92567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Called when the LayoutManager should save its state. This is a good time to save your 92577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * scroll position, configuration and anything else that may be required to restore the same 92587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * layout state if the LayoutManager is recreated.</p> 92597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>RecyclerView does NOT verify if the LayoutManager has changed between state save and 92607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * restore. This will let you share information between your LayoutManagers but it is also 92617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * your responsibility to make sure they use the same parcelable class.</p> 92627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 92637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Necessary information for LayoutManager to be able to restore its state 92647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 92657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public Parcelable onSaveInstanceState() { 92667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 92677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 92687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 92697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 92707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onRestoreInstanceState(Parcelable state) { 92717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 92727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 92737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 92747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void stopSmoothScroller() { 92757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mSmoothScroller != null) { 92767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mSmoothScroller.stop(); 92777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 92787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 92797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 92807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void onSmoothScrollerStopped(SmoothScroller smoothScroller) { 92817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mSmoothScroller == smoothScroller) { 92827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mSmoothScroller = null; 92837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 92847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 92857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 92867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 92877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView calls this method to notify LayoutManager that scroll state has changed. 92887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 92897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state The new scroll state for RecyclerView 92907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 92917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onScrollStateChanged(int state) { 92927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 92937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 92947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 92957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Removes all views and recycles them using the given recycler. 92967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 92977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If you want to clean cached views as well, you should call {@link Recycler#clear()} too. 92987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 92997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If a View is marked as "ignored", it is not removed nor recycled. 93007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 93017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler Recycler to use to recycle children 93027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #removeAndRecycleView(View, Recycler) 93037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #removeAndRecycleViewAt(int, Recycler) 93047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #ignoreView(View) 93057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 93067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void removeAndRecycleAllViews(Recycler recycler) { 93077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = getChildCount() - 1; i >= 0; i--) { 93087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View view = getChildAt(i); 93097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!getChildViewHolderInt(view).shouldIgnore()) { 93107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas removeAndRecycleViewAt(i, recycler); 93117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 93127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 93137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 93147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 93157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // called by accessibility delegate 93167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 93177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onInitializeAccessibilityNodeInfo(mRecyclerView.mRecycler, mRecyclerView.mState, info); 93187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 93197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 93207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 93217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called by the AccessibilityDelegate when the information about the current layout should 93227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * be populated. 93237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 93247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Default implementation adds a {@link 93257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * android.view.accessibility.AccessibilityNodeInfo.CollectionInfo}. 93267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 93277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * You should override 93287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #getRowCountForAccessibility(RecyclerView.Recycler, RecyclerView.State)}, 93297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #getColumnCountForAccessibility(RecyclerView.Recycler, RecyclerView.State)}, 93307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #isLayoutHierarchical(RecyclerView.Recycler, RecyclerView.State)} and 93317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #getSelectionModeForAccessibility(RecyclerView.Recycler, RecyclerView.State)} for 93327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * more accurate accessibility information. 93337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 93347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler The Recycler that can be used to convert view positions into adapter 93357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * positions 93367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state The current state of RecyclerView 93377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param info The info that should be filled by the LayoutManager 93387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see View#onInitializeAccessibilityNodeInfo( 93397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas *android.view.accessibility.AccessibilityNodeInfo) 93407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #getRowCountForAccessibility(RecyclerView.Recycler, RecyclerView.State) 93417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #getColumnCountForAccessibility(RecyclerView.Recycler, RecyclerView.State) 93427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #isLayoutHierarchical(RecyclerView.Recycler, RecyclerView.State) 93437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #getSelectionModeForAccessibility(RecyclerView.Recycler, RecyclerView.State) 93447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 93457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onInitializeAccessibilityNodeInfo(Recycler recycler, State state, 93467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas AccessibilityNodeInfo info) { 93477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView.canScrollVertically(-1) 93487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || mRecyclerView.canScrollHorizontally(-1)) { 93497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); 93507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas info.setScrollable(true); 93517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 93527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView.canScrollVertically(1) 93537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || mRecyclerView.canScrollHorizontally(1)) { 93547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); 93557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas info.setScrollable(true); 93567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 93577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final AccessibilityNodeInfo.CollectionInfo collectionInfo = 93587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas AccessibilityNodeInfo.CollectionInfo 93597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas .obtain(getRowCountForAccessibility(recycler, state), 93607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas getColumnCountForAccessibility(recycler, state), 93617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas isLayoutHierarchical(recycler, state), 93627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas getSelectionModeForAccessibility(recycler, state)); 93637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas info.setCollectionInfo(collectionInfo); 93647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 93657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 93667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // called by accessibility delegate 93677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 93687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onInitializeAccessibilityEvent(mRecyclerView.mRecycler, mRecyclerView.mState, event); 93697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 93707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 93717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 93727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called by the accessibility delegate to initialize an accessibility event. 93737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 93747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Default implementation adds item count and scroll information to the event. 93757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 93767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler The Recycler that can be used to convert view positions into adapter 93777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * positions 93787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state The current state of RecyclerView 93797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param event The event instance to initialize 93807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see View#onInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent) 93817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 93827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onInitializeAccessibilityEvent(Recycler recycler, State state, 93837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas AccessibilityEvent event) { 93847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView == null || event == null) { 93857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 93867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 93877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas event.setScrollable(mRecyclerView.canScrollVertically(1) 93887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || mRecyclerView.canScrollVertically(-1) 93897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || mRecyclerView.canScrollHorizontally(-1) 93907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || mRecyclerView.canScrollHorizontally(1)); 93917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 93927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView.mAdapter != null) { 93937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas event.setItemCount(mRecyclerView.mAdapter.getItemCount()); 93947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 93957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 93967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 93977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // called by accessibility delegate 93987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void onInitializeAccessibilityNodeInfoForItem(View host, AccessibilityNodeInfo info) { 93997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewHolder vh = getChildViewHolderInt(host); 94007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // avoid trying to create accessibility node info for removed children 94017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (vh != null && !vh.isRemoved() && !mChildHelper.isHidden(vh.itemView)) { 94027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onInitializeAccessibilityNodeInfoForItem(mRecyclerView.mRecycler, 94037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.mState, host, info); 94047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 94057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 94067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 94077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 94087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called by the AccessibilityDelegate when the accessibility information for a specific 94097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * item should be populated. 94107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 94117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Default implementation adds basic positioning information about the item. 94127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 94137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler The Recycler that can be used to convert view positions into adapter 94147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * positions 94157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state The current state of RecyclerView 94167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param host The child for which accessibility node info should be populated 94177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param info The info to fill out about the item 94187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see android.widget.AbsListView#onInitializeAccessibilityNodeInfoForItem(View, int, 94197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * android.view.accessibility.AccessibilityNodeInfo) 94207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 94217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onInitializeAccessibilityNodeInfoForItem(Recycler recycler, State state, 94227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas View host, AccessibilityNodeInfo info) { 94237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int rowIndexGuess = canScrollVertically() ? getPosition(host) : 0; 94247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int columnIndexGuess = canScrollHorizontally() ? getPosition(host) : 0; 94257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final AccessibilityNodeInfo.CollectionItemInfo itemInfo = 94267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas AccessibilityNodeInfo.CollectionItemInfo.obtain(rowIndexGuess, 1, 94277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas columnIndexGuess, 1, false, false); 94287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas info.setCollectionItemInfo(itemInfo); 94297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 94307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 94317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 94327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * A LayoutManager can call this method to force RecyclerView to run simple animations in 94337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the next layout pass, even if there is not any trigger to do so. (e.g. adapter data 94347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * change). 94357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 94367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that, calling this method will not guarantee that RecyclerView will run animations 94377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * at all. For example, if there is not any {@link ItemAnimator} set, RecyclerView will 94387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * not run any animations but will still clear this flag after the layout is complete. 94397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 94407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 94417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void requestSimpleAnimationsInNextLayout() { 94427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRequestedSimpleAnimations = true; 94437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 94447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 94457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 94467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the selection mode for accessibility. Should be 94477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link AccessibilityNodeInfo.CollectionInfo#SELECTION_MODE_NONE}, 94487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link AccessibilityNodeInfo.CollectionInfo#SELECTION_MODE_SINGLE} or 94497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link AccessibilityNodeInfo.CollectionInfo#SELECTION_MODE_MULTIPLE}. 94507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 94517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Default implementation returns 94527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link AccessibilityNodeInfo.CollectionInfo#SELECTION_MODE_NONE}. 94537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 94547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler The Recycler that can be used to convert view positions into adapter 94557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * positions 94567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state The current state of RecyclerView 94577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Selection mode for accessibility. Default implementation returns 94587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link AccessibilityNodeInfo.CollectionInfo#SELECTION_MODE_NONE}. 94597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 94607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getSelectionModeForAccessibility(Recycler recycler, State state) { 94617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return AccessibilityNodeInfo.CollectionInfo.SELECTION_MODE_NONE; 94627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 94637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 94647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 94657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the number of rows for accessibility. 94667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 94677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Default implementation returns the number of items in the adapter if LayoutManager 94687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * supports vertical scrolling or 1 if LayoutManager does not support vertical 94697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * scrolling. 94707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 94717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler The Recycler that can be used to convert view positions into adapter 94727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * positions 94737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state The current state of RecyclerView 94747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The number of rows in LayoutManager for accessibility. 94757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 94767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getRowCountForAccessibility(Recycler recycler, State state) { 94777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView == null || mRecyclerView.mAdapter == null) { 94787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return 1; 94797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 94807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return canScrollVertically() ? mRecyclerView.mAdapter.getItemCount() : 1; 94817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 94827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 94837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 94847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the number of columns for accessibility. 94857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 94867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Default implementation returns the number of items in the adapter if LayoutManager 94877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * supports horizontal scrolling or 1 if LayoutManager does not support horizontal 94887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * scrolling. 94897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 94907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler The Recycler that can be used to convert view positions into adapter 94917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * positions 94927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state The current state of RecyclerView 94937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The number of rows in LayoutManager for accessibility. 94947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 94957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getColumnCountForAccessibility(Recycler recycler, State state) { 94967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView == null || mRecyclerView.mAdapter == null) { 94977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return 1; 94987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 94997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return canScrollHorizontally() ? mRecyclerView.mAdapter.getItemCount() : 1; 95007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 95017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 95027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 95037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns whether layout is hierarchical or not to be used for accessibility. 95047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 95057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Default implementation returns false. 95067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 95077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler The Recycler that can be used to convert view positions into adapter 95087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * positions 95097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state The current state of RecyclerView 95107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return True if layout is hierarchical. 95117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 95127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean isLayoutHierarchical(Recycler recycler, State state) { 95137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 95147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 95157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 95167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // called by accessibility delegate 95177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean performAccessibilityAction(int action, Bundle args) { 95187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return performAccessibilityAction(mRecyclerView.mRecycler, mRecyclerView.mState, 95197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas action, args); 95207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 95217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 95227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 95237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called by AccessibilityDelegate when an action is requested from the RecyclerView. 95247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 95257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler The Recycler that can be used to convert view positions into adapter 95267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * positions 95277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state The current state of RecyclerView 95287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param action The action to perform 95297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param args Optional action arguments 95307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see View#performAccessibilityAction(int, android.os.Bundle) 95317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 95327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean performAccessibilityAction(Recycler recycler, State state, int action, 95337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Bundle args) { 95347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView == null) { 95357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 95367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 95377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int vScroll = 0, hScroll = 0; 95387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas switch (action) { 95397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: 95407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView.canScrollVertically(-1)) { 95417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas vScroll = -(getHeight() - getPaddingTop() - getPaddingBottom()); 95427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 95437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView.canScrollHorizontally(-1)) { 95447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas hScroll = -(getWidth() - getPaddingLeft() - getPaddingRight()); 95457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 95467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas break; 95477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: 95487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView.canScrollVertically(1)) { 95497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas vScroll = getHeight() - getPaddingTop() - getPaddingBottom(); 95507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 95517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRecyclerView.canScrollHorizontally(1)) { 95527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas hScroll = getWidth() - getPaddingLeft() - getPaddingRight(); 95537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 95547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas break; 95557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 95567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (vScroll == 0 && hScroll == 0) { 95577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 95587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 955938343bc35c874cfdfb2bfd071d8618f0f19e6bfdEugene Susla mRecyclerView.smoothScrollBy(hScroll, vScroll); 95607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return true; 95617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 95627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 95637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // called by accessibility delegate 95647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean performAccessibilityActionForItem(View view, int action, Bundle args) { 95657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return performAccessibilityActionForItem(mRecyclerView.mRecycler, mRecyclerView.mState, 95667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas view, action, args); 95677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 95687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 95697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 95707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called by AccessibilityDelegate when an accessibility action is requested on one of the 95717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * children of LayoutManager. 95727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 95737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Default implementation does not do anything. 95747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 95757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recycler The Recycler that can be used to convert view positions into adapter 95767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * positions 95777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state The current state of RecyclerView 95787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param view The child view on which the action is performed 95797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param action The action to perform 95807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param args Optional action arguments 95817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if action is handled 95827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see View#performAccessibilityAction(int, android.os.Bundle) 95837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 95847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean performAccessibilityActionForItem(Recycler recycler, State state, View view, 95857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int action, Bundle args) { 95867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 95877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 95887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 95897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 95907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Parse the xml attributes to get the most common properties used by layout managers. 95917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 95927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return an object containing the properties as specified in the attrs. 95937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 95947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static Properties getProperties(Context context, AttributeSet attrs, 95957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int defStyleAttr, int defStyleRes) { 95967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Properties properties = new Properties(); 95977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RecyclerView, 95987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas defStyleAttr, defStyleRes); 95997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas properties.orientation = a.getInt(R.styleable.RecyclerView_orientation, VERTICAL); 96007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas properties.spanCount = a.getInt(R.styleable.RecyclerView_spanCount, 1); 96017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas properties.reverseLayout = a.getBoolean(R.styleable.RecyclerView_reverseLayout, false); 96027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas properties.stackFromEnd = a.getBoolean(R.styleable.RecyclerView_stackFromEnd, false); 96037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas a.recycle(); 96047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return properties; 96057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 96067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 96077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void setExactMeasureSpecsFrom(RecyclerView recyclerView) { 96087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas setMeasureSpecs( 96097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas MeasureSpec.makeMeasureSpec(recyclerView.getWidth(), MeasureSpec.EXACTLY), 96107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas MeasureSpec.makeMeasureSpec(recyclerView.getHeight(), MeasureSpec.EXACTLY) 96117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ); 96127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 96137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 96147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 96157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Internal API to allow LayoutManagers to be measured twice. 96167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 96177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This is not public because LayoutManagers should be able to handle their layouts in one 96187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * pass but it is very convenient to make existing LayoutManagers support wrapping content 96197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * when both orientations are undefined. 96207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 96217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This API will be removed after default LayoutManagers properly implement wrap content in 96227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * non-scroll orientation. 96237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 96247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean shouldMeasureTwice() { 96257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 96267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 96277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 96287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean hasFlexibleChildInBothOrientations() { 96297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int childCount = getChildCount(); 96307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < childCount; i++) { 96317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View child = getChildAt(i); 96327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final ViewGroup.LayoutParams lp = child.getLayoutParams(); 96337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (lp.width < 0 && lp.height < 0) { 96347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return true; 96357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 96367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 96377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 96387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 96397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 96407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 96417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Some general properties that a LayoutManager may want to use. 96427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 96437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static class Properties { 96447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_android_orientation */ 96457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int orientation; 96467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_spanCount */ 96477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int spanCount; 96487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_reverseLayout */ 96497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean reverseLayout; 96507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_stackFromEnd */ 96517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean stackFromEnd; 96527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 96537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 96547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 96557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 96567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * An ItemDecoration allows the application to add a special drawing and layout offset 96577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to specific item views from the adapter's data set. This can be useful for drawing dividers 96587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * between items, highlights, visual grouping boundaries and more. 96597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 96607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>All ItemDecorations are drawn in the order they were added, before the item 96617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * views (in {@link ItemDecoration#onDraw(Canvas, RecyclerView, RecyclerView.State) onDraw()} 96627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * and after the items (in {@link ItemDecoration#onDrawOver(Canvas, RecyclerView, 96637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView.State)}.</p> 96647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 96657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract static class ItemDecoration { 96667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 96677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Draw any appropriate decorations into the Canvas supplied to the RecyclerView. 96687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Any content drawn by this method will be drawn before the item views are drawn, 96697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * and will thus appear underneath the views. 96707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 96717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param c Canvas to draw into 96727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param parent RecyclerView this ItemDecoration is drawing into 96737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state The current state of RecyclerView 96747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 96757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onDraw(Canvas c, RecyclerView parent, State state) { 96767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onDraw(c, parent); 96777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 96787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 96797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 96807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @deprecated 96817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Override {@link #onDraw(Canvas, RecyclerView, RecyclerView.State)} 96827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 96837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Deprecated 96847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onDraw(Canvas c, RecyclerView parent) { 96857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 96867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 96877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 96887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Draw any appropriate decorations into the Canvas supplied to the RecyclerView. 96897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Any content drawn by this method will be drawn after the item views are drawn 96907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * and will thus appear over the views. 96917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 96927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param c Canvas to draw into 96937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param parent RecyclerView this ItemDecoration is drawing into 96947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state The current state of RecyclerView. 96957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 96967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onDrawOver(Canvas c, RecyclerView parent, State state) { 96977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onDrawOver(c, parent); 96987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 96997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 97007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 97017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @deprecated 97027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Override {@link #onDrawOver(Canvas, RecyclerView, RecyclerView.State)} 97037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 97047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Deprecated 97057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onDrawOver(Canvas c, RecyclerView parent) { 97067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 97077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 97087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 97097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 97107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @deprecated 97117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Use {@link #getItemOffsets(Rect, View, RecyclerView, State)} 97127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 97137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Deprecated 97147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) { 97157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas outRect.set(0, 0, 0, 0); 97167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 97177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 97187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 97197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Retrieve any offsets for the given item. Each field of <code>outRect</code> specifies 97207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the number of pixels that the item view should be inset by, similar to padding or margin. 97217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The default implementation sets the bounds of outRect to 0 and returns. 97227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 97237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 97247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If this ItemDecoration does not affect the positioning of item views, it should set 97257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * all four fields of <code>outRect</code> (left, top, right, bottom) to zero 97267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * before returning. 97277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 97287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 97297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If you need to access Adapter for additional data, you can call 97307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecyclerView#getChildAdapterPosition(View)} to get the adapter position of the 97317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * View. 97327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 97337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param outRect Rect to receive the output. 97347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param view The child view to decorate 97357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param parent RecyclerView this ItemDecoration is decorating 97367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state The current state of RecyclerView. 97377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 97387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) { 97397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas getItemOffsets(outRect, ((LayoutParams) view.getLayoutParams()).getViewLayoutPosition(), 97407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas parent); 97417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 97427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 97437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 97447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 97457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * An OnItemTouchListener allows the application to intercept touch events in progress at the 97467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * view hierarchy level of the RecyclerView before those touch events are considered for 97477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView's own scrolling behavior. 97487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 97497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>This can be useful for applications that wish to implement various forms of gestural 97507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * manipulation of item views within the RecyclerView. OnItemTouchListeners may intercept 97517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * a touch interaction already in progress even if the RecyclerView is already handling that 97527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * gesture stream itself for the purposes of scrolling.</p> 97537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 97547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see SimpleOnItemTouchListener 97557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 97567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public interface OnItemTouchListener { 97577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 97587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Silently observe and/or take over touch events sent to the RecyclerView 97597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * before they are handled by either the RecyclerView itself or its child views. 97607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 97617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>The onInterceptTouchEvent methods of each attached OnItemTouchListener will be run 97627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * in the order in which each listener was added, before any other touch processing 97637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * by the RecyclerView itself or child views occurs.</p> 97647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 97657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param e MotionEvent describing the touch event. All coordinates are in 97667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the RecyclerView's coordinate system. 97677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if this OnItemTouchListener wishes to begin intercepting touch events, false 97687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to continue with the current behavior and continue observing future events in 97697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the gesture. 97707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 97717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e); 97727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 97737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 97747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Process a touch event as part of a gesture that was claimed by returning true from 97757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * a previous call to {@link #onInterceptTouchEvent}. 97767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 97777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param e MotionEvent describing the touch event. All coordinates are in 97787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the RecyclerView's coordinate system. 97797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 97807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void onTouchEvent(RecyclerView rv, MotionEvent e); 97817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 97827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 97837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when a child of RecyclerView does not want RecyclerView and its ancestors to 97847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * intercept touch events with 97857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link ViewGroup#onInterceptTouchEvent(MotionEvent)}. 97867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 97877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param disallowIntercept True if the child does not want the parent to 97887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * intercept touch events. 97897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see ViewParent#requestDisallowInterceptTouchEvent(boolean) 97907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 97917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept); 97927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 97937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 97947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 97957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * An implementation of {@link RecyclerView.OnItemTouchListener} that has empty method bodies 97967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * and default return values. 97977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 97987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * You may prefer to extend this class if you don't need to override all methods. Another 97997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * benefit of using this class is future compatibility. As the interface may change, we'll 98007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * always provide a default implementation on this class so that your code won't break when 98017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * you update to a new version of the support library. 98027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 98037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static class SimpleOnItemTouchListener implements RecyclerView.OnItemTouchListener { 98047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 98057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { 98067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 98077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 98087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 98097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 98107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onTouchEvent(RecyclerView rv, MotionEvent e) { 98117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 98127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 98137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 98147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { 98157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 98167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 98177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 98187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 98197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 98207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * An OnScrollListener can be added to a RecyclerView to receive messages when a scrolling event 98217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * has occurred on that RecyclerView. 98227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 98237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see RecyclerView#addOnScrollListener(OnScrollListener) 98247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see RecyclerView#clearOnChildAttachStateChangeListeners() 98257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 98267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 98277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract static class OnScrollListener { 98287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 98297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Callback method to be invoked when RecyclerView's scroll state changes. 98307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 98317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recyclerView The RecyclerView whose scroll state has changed. 98327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param newState The updated scroll state. One of {@link #SCROLL_STATE_IDLE}, 98337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #SCROLL_STATE_DRAGGING} or {@link #SCROLL_STATE_SETTLING}. 98347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 98357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onScrollStateChanged(RecyclerView recyclerView, int newState){} 98367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 98377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 98387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Callback method to be invoked when the RecyclerView has been scrolled. This will be 98397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * called after the scroll has completed. 98407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 98417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This callback will also be called if visible item range changes after a layout 98427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * calculation. In that case, dx and dy will be 0. 98437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 98447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recyclerView The RecyclerView which scrolled. 98457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dx The amount of horizontal scroll. 98467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dy The amount of vertical scroll. 98477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 98487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onScrolled(RecyclerView recyclerView, int dx, int dy){} 98497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 98507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 98517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 98527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * A RecyclerListener can be set on a RecyclerView to receive messages whenever 98537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * a view is recycled. 98547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 98557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see RecyclerView#setRecyclerListener(RecyclerListener) 98567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 98577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public interface RecyclerListener { 98587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 98597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 98607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method is called whenever the view in the ViewHolder is recycled. 98617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 98627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView calls this method right before clearing ViewHolder's internal data and 98637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * sending it to RecycledViewPool. This way, if ViewHolder was holding valid information 98647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * before being recycled, you can call {@link ViewHolder#getAdapterPosition()} to get 98657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * its adapter position. 98667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 98677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param holder The ViewHolder containing the view that was recycled 98687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 98697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void onViewRecycled(ViewHolder holder); 98707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 98717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 98727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 98737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * A Listener interface that can be attached to a RecylcerView to get notified 98747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * whenever a ViewHolder is attached to or detached from RecyclerView. 98757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 98767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public interface OnChildAttachStateChangeListener { 98777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 98787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 98797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when a view is attached to the RecyclerView. 98807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 98817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param view The View which is attached to the RecyclerView 98827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 98837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void onChildViewAttachedToWindow(View view); 98847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 98857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 98867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when a view is detached from RecyclerView. 98877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 98887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param view The View which is being detached from the RecyclerView 98897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 98907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void onChildViewDetachedFromWindow(View view); 98917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 98927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 98937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 98947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * A ViewHolder describes an item view and metadata about its place within the RecyclerView. 98957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 98967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>{@link Adapter} implementations should subclass ViewHolder and add fields for caching 98977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * potentially expensive {@link View#findViewById(int)} results.</p> 98987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 98997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>While {@link LayoutParams} belong to the {@link LayoutManager}, 99007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link ViewHolder ViewHolders} belong to the adapter. Adapters should feel free to use 99017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * their own custom ViewHolder implementations to store data that makes binding view contents 99027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * easier. Implementations should assume that individual item views will hold strong references 99037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to <code>ViewHolder</code> objects and that <code>RecyclerView</code> instances may hold 99047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * strong references to extra off-screen item views for caching purposes</p> 99057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 99067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract static class ViewHolder { 99077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final View itemView; 99087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas WeakReference<RecyclerView> mNestedRecyclerView; 99097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int mPosition = NO_POSITION; 99107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int mOldPosition = NO_POSITION; 99117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas long mItemId = NO_ID; 99127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int mItemViewType = INVALID_TYPE; 99137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int mPreLayoutPosition = NO_POSITION; 99147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 99157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // The item that this holder is shadowing during an item change event/animation 99167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder mShadowedHolder = null; 99177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // The item that is shadowing this holder during an item change event/animation 99187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder mShadowingHolder = null; 99197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 99207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 99217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This ViewHolder has been bound to a position; mPosition, mItemId and mItemViewType 99227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * are all valid. 99237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 99247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final int FLAG_BOUND = 1 << 0; 99257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 99267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 99277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The data this ViewHolder's view reflects is stale and needs to be rebound 99287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * by the adapter. mPosition and mItemId are consistent. 99297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 99307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final int FLAG_UPDATE = 1 << 1; 99317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 99327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 99337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This ViewHolder's data is invalid. The identity implied by mPosition and mItemId 99347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * are not to be trusted and may no longer match the item view type. 99357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This ViewHolder must be fully rebound to different data. 99367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 99377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final int FLAG_INVALID = 1 << 2; 99387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 99397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 99407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This ViewHolder points at data that represents an item previously removed from the 99417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * data set. Its view may still be used for things like outgoing animations. 99427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 99437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final int FLAG_REMOVED = 1 << 3; 99447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 99457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 99467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This ViewHolder should not be recycled. This flag is set via setIsRecyclable() 99477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * and is intended to keep views around during animations. 99487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 99497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final int FLAG_NOT_RECYCLABLE = 1 << 4; 99507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 99517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 99527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This ViewHolder is returned from scrap which means we are expecting an addView call 99537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * for this itemView. When returned from scrap, ViewHolder stays in the scrap list until 99547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the end of the layout pass and then recycled by RecyclerView if it is not added back to 99557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the RecyclerView. 99567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 99577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final int FLAG_RETURNED_FROM_SCRAP = 1 << 5; 99587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 99597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 99607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This ViewHolder is fully managed by the LayoutManager. We do not scrap, recycle or remove 99617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * it unless LayoutManager is replaced. 99627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * It is still fully visible to the LayoutManager. 99637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 99647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final int FLAG_IGNORE = 1 << 7; 99657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 99667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 99677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * When the View is detached form the parent, we set this flag so that we can take correct 99687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * action when we need to remove it or add it back. 99697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 99707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final int FLAG_TMP_DETACHED = 1 << 8; 99717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 99727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 99737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Set when we can no longer determine the adapter position of this ViewHolder until it is 99747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * rebound to a new position. It is different than FLAG_INVALID because FLAG_INVALID is 99757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * set even when the type does not match. Also, FLAG_ADAPTER_POSITION_UNKNOWN is set as soon 99767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * as adapter notification arrives vs FLAG_INVALID is set lazily before layout is 99777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * re-calculated. 99787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 99797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final int FLAG_ADAPTER_POSITION_UNKNOWN = 1 << 9; 99807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 99817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 99827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Set when a addChangePayload(null) is called 99837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 99847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final int FLAG_ADAPTER_FULLUPDATE = 1 << 10; 99857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 99867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 99877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Used by ItemAnimator when a ViewHolder's position changes 99887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 99897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final int FLAG_MOVED = 1 << 11; 99907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 99917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 99927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Used by ItemAnimator when a ViewHolder appears in pre-layout 99937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 99947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final int FLAG_APPEARED_IN_PRE_LAYOUT = 1 << 12; 99957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 99967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final int PENDING_ACCESSIBILITY_STATE_NOT_SET = -1; 99977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 99987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 99997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Used when a ViewHolder starts the layout pass as a hidden ViewHolder but is re-used from 100007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * hidden list (as if it was scrap) without being recycled in between. 100017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 100027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * When a ViewHolder is hidden, there are 2 paths it can be re-used: 100037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * a) Animation ends, view is recycled and used from the recycle pool. 100047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * b) LayoutManager asks for the View for that position while the ViewHolder is hidden. 100057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 100067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This flag is used to represent "case b" where the ViewHolder is reused without being 100077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * recycled (thus "bounced" from the hidden list). This state requires special handling 100087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * because the ViewHolder must be added to pre layout maps for animations as if it was 100097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * already there. 100107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 100117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final int FLAG_BOUNCED_FROM_HIDDEN_LIST = 1 << 13; 100127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 100137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mFlags; 100147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 100157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private static final List<Object> FULLUPDATE_PAYLOADS = Collections.EMPTY_LIST; 100167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 100177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas List<Object> mPayloads = null; 100187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas List<Object> mUnmodifiedPayloads = null; 100197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 100207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mIsRecyclableCount = 0; 100217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 100227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // If non-null, view is currently considered scrap and may be reused for other data by the 100237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // scrap container. 100247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private Recycler mScrapContainer = null; 100257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Keeps whether this ViewHolder lives in Change scrap or Attached scrap 100267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private boolean mInChangeScrap = false; 100277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 100287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Saves isImportantForAccessibility value for the view item while it's in hidden state and 100297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // marked as unimportant for accessibility. 100307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mWasImportantForAccessibilityBeforeHidden = 100317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas View.IMPORTANT_FOR_ACCESSIBILITY_AUTO; 100327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // set if we defer the accessibility state change of the view holder 100337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @VisibleForTesting 100347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int mPendingAccessibilityState = PENDING_ACCESSIBILITY_STATE_NOT_SET; 100357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 100367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 100377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Is set when VH is bound from the adapter and cleaned right before it is sent to 100387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecycledViewPool}. 100397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 100407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas RecyclerView mOwnerRecyclerView; 100417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 100427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public ViewHolder(View itemView) { 100437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (itemView == null) { 100447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalArgumentException("itemView may not be null"); 100457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 100467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas this.itemView = itemView; 100477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 100487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 100497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void flagRemovedAndOffsetPosition(int mNewPosition, int offset, boolean applyToPreLayout) { 100507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas addFlags(ViewHolder.FLAG_REMOVED); 100517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas offsetPosition(offset, applyToPreLayout); 100527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPosition = mNewPosition; 100537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 100547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 100557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void offsetPosition(int offset, boolean applyToPreLayout) { 100567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mOldPosition == NO_POSITION) { 100577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mOldPosition = mPosition; 100587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 100597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mPreLayoutPosition == NO_POSITION) { 100607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPreLayoutPosition = mPosition; 100617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 100627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (applyToPreLayout) { 100637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPreLayoutPosition += offset; 100647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 100657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPosition += offset; 100667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (itemView.getLayoutParams() != null) { 100677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ((LayoutParams) itemView.getLayoutParams()).mInsetsDirty = true; 100687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 100697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 100707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 100717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void clearOldPosition() { 100727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mOldPosition = NO_POSITION; 100737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPreLayoutPosition = NO_POSITION; 100747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 100757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 100767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void saveOldPosition() { 100777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mOldPosition == NO_POSITION) { 100787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mOldPosition = mPosition; 100797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 100807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 100817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 100827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean shouldIgnore() { 100837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return (mFlags & FLAG_IGNORE) != 0; 100847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 100857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 100867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 100877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @deprecated This method is deprecated because its meaning is ambiguous due to the async 100887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * handling of adapter updates. Please use {@link #getLayoutPosition()} or 100897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #getAdapterPosition()} depending on your use case. 100907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 100917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #getLayoutPosition() 100927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #getAdapterPosition() 100937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 100947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Deprecated 100957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final int getPosition() { 100967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mPreLayoutPosition == NO_POSITION ? mPosition : mPreLayoutPosition; 100977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 100987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 100997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 101007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the position of the ViewHolder in terms of the latest layout pass. 101017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 101027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This position is mostly used by RecyclerView components to be consistent while 101037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView lazily processes adapter updates. 101047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 101057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * For performance and animation reasons, RecyclerView batches all adapter updates until the 101067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * next layout pass. This may cause mismatches between the Adapter position of the item and 101077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the position it had in the latest layout calculations. 101087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 101097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManagers should always call this method while doing calculations based on item 101107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * positions. All methods in {@link RecyclerView.LayoutManager}, {@link RecyclerView.State}, 101117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecyclerView.Recycler} that receive a position expect it to be the layout position 101127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * of the item. 101137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 101147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If LayoutManager needs to call an external method that requires the adapter position of 101157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the item, it can use {@link #getAdapterPosition()} or 101167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecyclerView.Recycler#convertPreLayoutPositionToPostLayout(int)}. 101177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 101187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Returns the adapter position of the ViewHolder in the latest layout pass. 101197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #getAdapterPosition() 101207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 101217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final int getLayoutPosition() { 101227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mPreLayoutPosition == NO_POSITION ? mPosition : mPreLayoutPosition; 101237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 101247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 101257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 101267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the Adapter position of the item represented by this ViewHolder. 101277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 101287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that this might be different than the {@link #getLayoutPosition()} if there are 101297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * pending adapter updates but a new layout pass has not happened yet. 101307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 101317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView does not handle any adapter updates until the next layout traversal. This 101327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * may create temporary inconsistencies between what user sees on the screen and what 101337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * adapter contents have. This inconsistency is not important since it will be less than 101347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 16ms but it might be a problem if you want to use ViewHolder position to access the 101357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * adapter. Sometimes, you may need to get the exact adapter position to do 101367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * some actions in response to user events. In that case, you should use this method which 101377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * will calculate the Adapter position of the ViewHolder. 101387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 101397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that if you've called {@link RecyclerView.Adapter#notifyDataSetChanged()}, until the 101407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * next layout pass, the return value of this method will be {@link #NO_POSITION}. 101417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 101427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The adapter position of the item if it still exists in the adapter. 101437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecyclerView#NO_POSITION} if item has been removed from the adapter, 101447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecyclerView.Adapter#notifyDataSetChanged()} has been called after the last 101457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * layout pass or the ViewHolder has already been recycled. 101467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 101477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final int getAdapterPosition() { 101487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mOwnerRecyclerView == null) { 101497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return NO_POSITION; 101507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 101517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mOwnerRecyclerView.getAdapterPositionFor(this); 101527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 101537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 101547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 101557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * When LayoutManager supports animations, RecyclerView tracks 3 positions for ViewHolders 101567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to perform animations. 101577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 101587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If a ViewHolder was laid out in the previous onLayout call, old position will keep its 101597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * adapter index in the previous layout. 101607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 101617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The previous adapter index of the Item represented by this ViewHolder or 101627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #NO_POSITION} if old position does not exists or cleared (pre-layout is 101637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * complete). 101647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 101657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final int getOldPosition() { 101667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mOldPosition; 101677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 101687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 101697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 101707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns The itemId represented by this ViewHolder. 101717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 101727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The item's id if adapter has stable ids, {@link RecyclerView#NO_ID} 101737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * otherwise 101747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 101757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final long getItemId() { 101767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mItemId; 101777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 101787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 101797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 101807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The view type of this ViewHolder. 101817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 101827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final int getItemViewType() { 101837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mItemViewType; 101847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 101857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 101867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean isScrap() { 101877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mScrapContainer != null; 101887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 101897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 101907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void unScrap() { 101917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScrapContainer.unscrapView(this); 101927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 101937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 101947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean wasReturnedFromScrap() { 101957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return (mFlags & FLAG_RETURNED_FROM_SCRAP) != 0; 101967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 101977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 101987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void clearReturnedFromScrapFlag() { 101997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mFlags = mFlags & ~FLAG_RETURNED_FROM_SCRAP; 102007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 102017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 102027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void clearTmpDetachFlag() { 102037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mFlags = mFlags & ~FLAG_TMP_DETACHED; 102047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 102057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 102067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void stopIgnoring() { 102077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mFlags = mFlags & ~FLAG_IGNORE; 102087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 102097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 102107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void setScrapContainer(Recycler recycler, boolean isChangeScrap) { 102117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mScrapContainer = recycler; 102127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mInChangeScrap = isChangeScrap; 102137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 102147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 102157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean isInvalid() { 102167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return (mFlags & FLAG_INVALID) != 0; 102177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 102187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 102197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean needsUpdate() { 102207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return (mFlags & FLAG_UPDATE) != 0; 102217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 102227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 102237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean isBound() { 102247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return (mFlags & FLAG_BOUND) != 0; 102257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 102267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 102277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean isRemoved() { 102287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return (mFlags & FLAG_REMOVED) != 0; 102297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 102307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 102317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean hasAnyOfTheFlags(int flags) { 102327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return (mFlags & flags) != 0; 102337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 102347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 102357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean isTmpDetached() { 102367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return (mFlags & FLAG_TMP_DETACHED) != 0; 102377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 102387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 102397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean isAdapterPositionUnknown() { 102407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return (mFlags & FLAG_ADAPTER_POSITION_UNKNOWN) != 0 || isInvalid(); 102417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 102427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 102437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void setFlags(int flags, int mask) { 102447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mFlags = (mFlags & ~mask) | (flags & mask); 102457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 102467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 102477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void addFlags(int flags) { 102487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mFlags |= flags; 102497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 102507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 102517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void addChangePayload(Object payload) { 102527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (payload == null) { 102537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas addFlags(FLAG_ADAPTER_FULLUPDATE); 102547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if ((mFlags & FLAG_ADAPTER_FULLUPDATE) == 0) { 102557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas createPayloadsIfNeeded(); 102567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPayloads.add(payload); 102577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 102587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 102597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 102607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void createPayloadsIfNeeded() { 102617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mPayloads == null) { 102627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPayloads = new ArrayList<Object>(); 102637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mUnmodifiedPayloads = Collections.unmodifiableList(mPayloads); 102647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 102657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 102667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 102677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void clearPayload() { 102687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mPayloads != null) { 102697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPayloads.clear(); 102707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 102717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mFlags = mFlags & ~FLAG_ADAPTER_FULLUPDATE; 102727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 102737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 102747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas List<Object> getUnmodifiedPayloads() { 102757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if ((mFlags & FLAG_ADAPTER_FULLUPDATE) == 0) { 102767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mPayloads == null || mPayloads.size() == 0) { 102777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Initial state, no update being called. 102787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return FULLUPDATE_PAYLOADS; 102797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 102807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // there are none-null payloads 102817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mUnmodifiedPayloads; 102827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 102837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // a full update has been called. 102847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return FULLUPDATE_PAYLOADS; 102857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 102867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 102877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 102887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void resetInternal() { 102897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mFlags = 0; 102907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPosition = NO_POSITION; 102917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mOldPosition = NO_POSITION; 102927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemId = NO_ID; 102937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPreLayoutPosition = NO_POSITION; 102947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mIsRecyclableCount = 0; 102957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mShadowedHolder = null; 102967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mShadowingHolder = null; 102977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas clearPayload(); 102987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mWasImportantForAccessibilityBeforeHidden = View.IMPORTANT_FOR_ACCESSIBILITY_AUTO; 102997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPendingAccessibilityState = PENDING_ACCESSIBILITY_STATE_NOT_SET; 103007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas clearNestedRecyclerViewIfNotNested(this); 103017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 103027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 103037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 103047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when the child view enters the hidden state 103057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 103067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void onEnteredHiddenState(RecyclerView parent) { 103077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // While the view item is in hidden state, make it invisible for the accessibility. 103087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mWasImportantForAccessibilityBeforeHidden = 103097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas itemView.getImportantForAccessibility(); 103107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas parent.setChildImportantForAccessibilityInternal(this, 103117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); 103127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 103137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 103147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 103157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when the child view leaves the hidden state 103167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 103177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void onLeftHiddenState(RecyclerView parent) { 103187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas parent.setChildImportantForAccessibilityInternal(this, 103197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mWasImportantForAccessibilityBeforeHidden); 103207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mWasImportantForAccessibilityBeforeHidden = View.IMPORTANT_FOR_ACCESSIBILITY_AUTO; 103217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 103227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 103237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 103247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public String toString() { 103257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final StringBuilder sb = new StringBuilder("ViewHolder{" 103267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + Integer.toHexString(hashCode()) + " position=" + mPosition + " id=" + mItemId 103277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + ", oldPos=" + mOldPosition + ", pLpos:" + mPreLayoutPosition); 103287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (isScrap()) { 103297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas sb.append(" scrap ") 103307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas .append(mInChangeScrap ? "[changeScrap]" : "[attachedScrap]"); 103317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 103327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (isInvalid()) sb.append(" invalid"); 103337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!isBound()) sb.append(" unbound"); 103347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (needsUpdate()) sb.append(" update"); 103357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (isRemoved()) sb.append(" removed"); 103367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (shouldIgnore()) sb.append(" ignored"); 103377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (isTmpDetached()) sb.append(" tmpDetached"); 103387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!isRecyclable()) sb.append(" not recyclable(" + mIsRecyclableCount + ")"); 103397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (isAdapterPositionUnknown()) sb.append(" undefined adapter position"); 103407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 103417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (itemView.getParent() == null) sb.append(" no parent"); 103427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas sb.append("}"); 103437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return sb.toString(); 103447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 103457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 103467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 103477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Informs the recycler whether this item can be recycled. Views which are not 103487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * recyclable will not be reused for other items until setIsRecyclable() is 103497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * later set to true. Calls to setIsRecyclable() should always be paired (one 103507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * call to setIsRecyclabe(false) should always be matched with a later call to 103517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * setIsRecyclable(true)). Pairs of calls may be nested, as the state is internally 103527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * reference-counted. 103537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 103547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param recyclable Whether this item is available to be recycled. Default value 103557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * is true. 103567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 103577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #isRecyclable() 103587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 103597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final void setIsRecyclable(boolean recyclable) { 103607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mIsRecyclableCount = recyclable ? mIsRecyclableCount - 1 : mIsRecyclableCount + 1; 103617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mIsRecyclableCount < 0) { 103627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mIsRecyclableCount = 0; 103637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 103647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new RuntimeException("isRecyclable decremented below 0: " 103657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "unmatched pair of setIsRecyable() calls for " + this); 103667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 103677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.e(VIEW_LOG_TAG, "isRecyclable decremented below 0: " 103687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "unmatched pair of setIsRecyable() calls for " + this); 103697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (!recyclable && mIsRecyclableCount == 1) { 103707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mFlags |= FLAG_NOT_RECYCLABLE; 103717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (recyclable && mIsRecyclableCount == 0) { 103727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mFlags &= ~FLAG_NOT_RECYCLABLE; 103737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 103747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 103757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.d(TAG, "setIsRecyclable val:" + recyclable + ":" + this); 103767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 103777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 103787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 103797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 103807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if this item is available to be recycled, false otherwise. 103817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 103827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #setIsRecyclable(boolean) 103837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 103847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final boolean isRecyclable() { 103857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return (mFlags & FLAG_NOT_RECYCLABLE) == 0 103867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas && !itemView.hasTransientState(); 103877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 103887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 103897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 103907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns whether we have animations referring to this view holder or not. 103917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This is similar to isRecyclable flag but does not check transient state. 103927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 103937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private boolean shouldBeKeptAsChild() { 103947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return (mFlags & FLAG_NOT_RECYCLABLE) != 0; 103957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 103967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 103977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 103987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return True if ViewHolder is not referenced by RecyclerView animations but has 103997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * transient state which will prevent it from being recycled. 104007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 104017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private boolean doesTransientStatePreventRecycling() { 104027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return (mFlags & FLAG_NOT_RECYCLABLE) == 0 && itemView.hasTransientState(); 104037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 104047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 104057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean isUpdated() { 104067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return (mFlags & FLAG_UPDATE) != 0; 104077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 104087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 104097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 104107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 104117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method is here so that we can control the important for a11y changes and test it. 104127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 104137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @VisibleForTesting 104147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean setChildImportantForAccessibilityInternal(ViewHolder viewHolder, 104157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int importantForAccessibility) { 104167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (isComputingLayout()) { 104177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas viewHolder.mPendingAccessibilityState = importantForAccessibility; 104187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPendingAccessibilityImportanceChange.add(viewHolder); 104197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return false; 104207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 104217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas viewHolder.itemView.setImportantForAccessibility(importantForAccessibility); 104227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return true; 104237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 104247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 104257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void dispatchPendingImportantForAccessibilityChanges() { 104267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = mPendingAccessibilityImportanceChange.size() - 1; i >= 0; i--) { 104277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder viewHolder = mPendingAccessibilityImportanceChange.get(i); 104287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (viewHolder.itemView.getParent() != this || viewHolder.shouldIgnore()) { 104297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas continue; 104307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 104317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int state = viewHolder.mPendingAccessibilityState; 104327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (state != ViewHolder.PENDING_ACCESSIBILITY_STATE_NOT_SET) { 104337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas //noinspection WrongConstant 104347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas viewHolder.itemView.setImportantForAccessibility(state); 104357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas viewHolder.mPendingAccessibilityState = 104367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder.PENDING_ACCESSIBILITY_STATE_NOT_SET; 104377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 104387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 104397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPendingAccessibilityImportanceChange.clear(); 104407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 104417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 104427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int getAdapterPositionFor(ViewHolder viewHolder) { 104437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (viewHolder.hasAnyOfTheFlags(ViewHolder.FLAG_INVALID 104447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas | ViewHolder.FLAG_REMOVED | ViewHolder.FLAG_ADAPTER_POSITION_UNKNOWN) 104457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas || !viewHolder.isBound()) { 104467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return RecyclerView.NO_POSITION; 104477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 104487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mAdapterHelper.applyPendingUpdatesToPosition(viewHolder.mPosition); 104497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 104507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 104517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 104527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link android.view.ViewGroup.MarginLayoutParams LayoutParams} subclass for children of 104537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecyclerView}. Custom {@link LayoutManager layout managers} are encouraged 104547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to create their own subclass of this <code>LayoutParams</code> class 104557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to store any additional required per-child view metadata about the layout. 104567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 104577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static class LayoutParams extends android.view.ViewGroup.MarginLayoutParams { 104587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder mViewHolder; 104597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final Rect mDecorInsets = new Rect(); 104607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean mInsetsDirty = true; 104617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Flag is set to true if the view is bound while it is detached from RV. 104627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // In this case, we need to manually call invalidate after view is added to guarantee that 104637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // invalidation is populated through the View hierarchy 104647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean mPendingInvalidate = false; 104657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 104667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public LayoutParams(Context c, AttributeSet attrs) { 104677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super(c, attrs); 104687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 104697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 104707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public LayoutParams(int width, int height) { 104717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super(width, height); 104727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 104737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 104747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public LayoutParams(MarginLayoutParams source) { 104757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super(source); 104767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 104777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 104787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public LayoutParams(ViewGroup.LayoutParams source) { 104797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super(source); 104807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 104817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 104827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public LayoutParams(LayoutParams source) { 104837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super((ViewGroup.LayoutParams) source); 104847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 104857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 104867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 104877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns true if the view this LayoutParams is attached to needs to have its content 104887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * updated from the corresponding adapter. 104897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 104907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if the view should have its content updated 104917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 104927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean viewNeedsUpdate() { 104937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mViewHolder.needsUpdate(); 104947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 104957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 104967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 104977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns true if the view this LayoutParams is attached to is now representing 104987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * potentially invalid data. A LayoutManager should scrap/recycle it. 104997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 105007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if the view is invalid 105017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 105027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean isViewInvalid() { 105037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mViewHolder.isInvalid(); 105047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 105057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 105067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 105077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns true if the adapter data item corresponding to the view this LayoutParams 105087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * is attached to has been removed from the data set. A LayoutManager may choose to 105097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * treat it differently in order to animate its outgoing or disappearing state. 105107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 105117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if the item the view corresponds to was removed from the data set 105127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 105137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean isItemRemoved() { 105147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mViewHolder.isRemoved(); 105157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 105167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 105177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 105187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns true if the adapter data item corresponding to the view this LayoutParams 105197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * is attached to has been changed in the data set. A LayoutManager may choose to 105207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * treat it differently in order to animate its changing state. 105217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 105227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if the item the view corresponds to was changed in the data set 105237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 105247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean isItemChanged() { 105257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mViewHolder.isUpdated(); 105267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 105277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 105287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 105297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @deprecated use {@link #getViewLayoutPosition()} or {@link #getViewAdapterPosition()} 105307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 105317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Deprecated 105327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getViewPosition() { 105337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mViewHolder.getPosition(); 105347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 105357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 105367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 105377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the adapter position that the view this LayoutParams is attached to corresponds 105387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to as of latest layout calculation. 105397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 105407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return the adapter position this view as of latest layout pass 105417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 105427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getViewLayoutPosition() { 105437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mViewHolder.getLayoutPosition(); 105447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 105457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 105467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 105477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the up-to-date adapter position that the view this LayoutParams is attached to 105487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * corresponds to. 105497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 105507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return the up-to-date adapter position this view. It may return 105517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecyclerView#NO_POSITION} if item represented by this View has been removed or 105527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * its up-to-date position cannot be calculated. 105537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 105547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getViewAdapterPosition() { 105557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mViewHolder.getAdapterPosition(); 105567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 105577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 105587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 105597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 105607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Observer base class for watching changes to an {@link Adapter}. 105617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * See {@link Adapter#registerAdapterDataObserver(AdapterDataObserver)}. 105627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 105637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract static class AdapterDataObserver { 105647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onChanged() { 105657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Do nothing 105667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 105677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 105687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onItemRangeChanged(int positionStart, int itemCount) { 105697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // do nothing 105707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 105717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 105727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onItemRangeChanged(int positionStart, int itemCount, Object payload) { 105737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // fallback to onItemRangeChanged(positionStart, itemCount) if app 105747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // does not override this method. 105757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onItemRangeChanged(positionStart, itemCount); 105767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 105777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 105787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onItemRangeInserted(int positionStart, int itemCount) { 105797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // do nothing 105807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 105817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 105827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onItemRangeRemoved(int positionStart, int itemCount) { 105837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // do nothing 105847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 105857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 105867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { 105877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // do nothing 105887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 105897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 105907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 105917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 105927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Base class for smooth scrolling. Handles basic tracking of the target view position and 105937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * provides methods to trigger a programmatic scroll.</p> 105947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 105957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see LinearSmoothScroller 105967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 105977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract static class SmoothScroller { 105987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 105997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mTargetPosition = RecyclerView.NO_POSITION; 106007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 106017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private RecyclerView mRecyclerView; 106027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 106037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private LayoutManager mLayoutManager; 106047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 106057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private boolean mPendingInitialRun; 106067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 106077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private boolean mRunning; 106087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 106097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private View mTargetView; 106107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 106117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private final Action mRecyclingAction; 106127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 106137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public SmoothScroller() { 106147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclingAction = new Action(0, 0); 106157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 106167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 106177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 106187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Starts a smooth scroll for the given target position. 106197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>In each animation step, {@link RecyclerView} will check 106207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * for the target view and call either 106217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #onTargetFound(android.view.View, RecyclerView.State, SmoothScroller.Action)} or 106227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #onSeekTargetStep(int, int, RecyclerView.State, SmoothScroller.Action)} until 106237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * SmoothScroller is stopped.</p> 106247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 106257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Note that if RecyclerView finds the target view, it will automatically stop the 106267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * SmoothScroller. This <b>does not</b> mean that scroll will stop, it only means it will 106277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * stop calling SmoothScroller in each animation step.</p> 106287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 106297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void start(RecyclerView recyclerView, LayoutManager layoutManager) { 106307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView = recyclerView; 106317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayoutManager = layoutManager; 106327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mTargetPosition == RecyclerView.NO_POSITION) { 106337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalArgumentException("Invalid target position"); 106347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 106357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.mState.mTargetPosition = mTargetPosition; 106367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRunning = true; 106377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPendingInitialRun = true; 106387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTargetView = findViewByPosition(getTargetPosition()); 106397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onStart(); 106407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.mViewFlinger.postOnAnimation(); 106417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 106427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 106437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setTargetPosition(int targetPosition) { 106447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTargetPosition = targetPosition; 106457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 106467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 106477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 106487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The LayoutManager to which this SmoothScroller is attached. Will return 106497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <code>null</code> after the SmoothScroller is stopped. 106507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 106517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Nullable 106527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public LayoutManager getLayoutManager() { 106537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mLayoutManager; 106547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 106557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 106567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 106577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Stops running the SmoothScroller in each animation callback. Note that this does not 106587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * cancel any existing {@link Action} updated by 106597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #onTargetFound(android.view.View, RecyclerView.State, SmoothScroller.Action)} or 106607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #onSeekTargetStep(int, int, RecyclerView.State, SmoothScroller.Action)}. 106617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 106627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas protected final void stop() { 106637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!mRunning) { 106647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 106657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 106667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onStop(); 106677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.mState.mTargetPosition = RecyclerView.NO_POSITION; 106687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTargetView = null; 106697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTargetPosition = RecyclerView.NO_POSITION; 106707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPendingInitialRun = false; 106717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRunning = false; 106727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // trigger a cleanup 106737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayoutManager.onSmoothScrollerStopped(this); 106747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // clear references to avoid any potential leak by a custom smooth scroller 106757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayoutManager = null; 106767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView = null; 106777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 106787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 106797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 106807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns true if SmoothScroller has been started but has not received the first 106817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animation 106827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * callback yet. 106837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 106847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return True if this SmoothScroller is waiting to start 106857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 106867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean isPendingInitialRun() { 106877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mPendingInitialRun; 106887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 106897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 106907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 106917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 106927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return True if SmoothScroller is currently active 106937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 106947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean isRunning() { 106957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mRunning; 106967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 106977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 106987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 106997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the adapter position of the target item 107007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 107017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Adapter position of the target item or 107027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecyclerView#NO_POSITION} if no target view is set. 107037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 107047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getTargetPosition() { 107057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mTargetPosition; 107067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 107077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 107087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void onAnimation(int dx, int dy) { 107097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final RecyclerView recyclerView = mRecyclerView; 107107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!mRunning || mTargetPosition == RecyclerView.NO_POSITION || recyclerView == null) { 107117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas stop(); 107127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 107137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPendingInitialRun = false; 107147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mTargetView != null) { 107157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // verify target position 107167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (getChildPosition(mTargetView) == mTargetPosition) { 107177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onTargetFound(mTargetView, recyclerView.mState, mRecyclingAction); 107187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclingAction.runIfNecessary(recyclerView); 107197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas stop(); 107207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 107217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.e(TAG, "Passed over target position while smooth scrolling."); 107227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTargetView = null; 107237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 107247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 107257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRunning) { 107267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onSeekTargetStep(dx, dy, recyclerView.mState, mRecyclingAction); 107277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean hadJumpTarget = mRecyclingAction.hasJumpTarget(); 107287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclingAction.runIfNecessary(recyclerView); 107297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (hadJumpTarget) { 107307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // It is not stopped so needs to be restarted 107317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mRunning) { 107327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mPendingInitialRun = true; 107337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recyclerView.mViewFlinger.postOnAnimation(); 107347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 107357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas stop(); // done 107367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 107377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 107387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 107397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 107407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 107417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 107427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see RecyclerView#getChildLayoutPosition(android.view.View) 107437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 107447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getChildPosition(View view) { 107457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mRecyclerView.getChildLayoutPosition(view); 107467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 107477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 107487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 107497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see RecyclerView.LayoutManager#getChildCount() 107507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 107517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getChildCount() { 107527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mRecyclerView.mLayout.getChildCount(); 107537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 107547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 107557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 107567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see RecyclerView.LayoutManager#findViewByPosition(int) 107577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 107587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public View findViewByPosition(int position) { 107597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mRecyclerView.mLayout.findViewByPosition(position); 107607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 107617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 107627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 107637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see RecyclerView#scrollToPosition(int) 107647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @deprecated Use {@link Action#jumpTo(int)}. 107657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 107667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Deprecated 107677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void instantScrollToPosition(int position) { 107687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRecyclerView.scrollToPosition(position); 107697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 107707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 107717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas protected void onChildAttachedToWindow(View child) { 107727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (getChildPosition(child) == getTargetPosition()) { 107737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTargetView = child; 107747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (DEBUG) { 107757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.d(TAG, "smooth scroll target view has been attached"); 107767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 107777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 107787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 107797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 107807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 107817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Normalizes the vector. 107827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param scrollVector The vector that points to the target scroll position 107837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 107847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas protected void normalize(PointF scrollVector) { 107857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final double magnitude = Math.sqrt(scrollVector.x * scrollVector.x + scrollVector.y 107867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * scrollVector.y); 107877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas scrollVector.x /= magnitude; 107887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas scrollVector.y /= magnitude; 107897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 107907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 107917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 107927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when smooth scroll is started. This might be a good time to do setup. 107937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 107947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas protected abstract void onStart(); 107957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 107967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 107977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when smooth scroller is stopped. This is a good place to cleanup your state etc. 107987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #stop() 107997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 108007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas protected abstract void onStop(); 108017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 108027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 108037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>RecyclerView will call this method each time it scrolls until it can find the target 108047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * position in the layout.</p> 108057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>SmoothScroller should check dx, dy and if scroll should be changed, update the 108067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * provided {@link Action} to define the next scroll.</p> 108077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 108087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dx Last scroll amount horizontally 108097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dy Last scroll amount vertically 108107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state Transient state of RecyclerView 108117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param action If you want to trigger a new smooth scroll and cancel the previous one, 108127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * update this object. 108137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 108147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas protected abstract void onSeekTargetStep(int dx, int dy, State state, Action action); 108157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 108167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 108177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when the target position is laid out. This is the last callback SmoothScroller 108187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * will receive and it should update the provided {@link Action} to define the scroll 108197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * details towards the target view. 108207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param targetView The view element which render the target position. 108217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state Transient state of RecyclerView 108227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param action Action instance that you should update to define final scroll action 108237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * towards the targetView 108247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 108257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas protected abstract void onTargetFound(View targetView, State state, Action action); 108267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 108277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 108287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Holds information about a smooth scroll request by a {@link SmoothScroller}. 108297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 108307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static class Action { 108317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 108327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static final int UNDEFINED_DURATION = Integer.MIN_VALUE; 108337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 108347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mDx; 108357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 108367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mDy; 108377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 108387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mDuration; 108397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 108407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mJumpToPosition = NO_POSITION; 108417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 108427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private Interpolator mInterpolator; 108437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 108447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private boolean mChanged = false; 108457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 108467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // we track this variable to inform custom implementer if they are updating the action 108477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // in every animation callback 108487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mConsecutiveUpdates = 0; 108497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 108507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 108517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dx Pixels to scroll horizontally 108527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dy Pixels to scroll vertically 108537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 108547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public Action(int dx, int dy) { 108557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas this(dx, dy, UNDEFINED_DURATION, null); 108567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 108577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 108587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 108597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dx Pixels to scroll horizontally 108607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dy Pixels to scroll vertically 108617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param duration Duration of the animation in milliseconds 108627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 108637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public Action(int dx, int dy, int duration) { 108647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas this(dx, dy, duration, null); 108657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 108667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 108677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 108687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dx Pixels to scroll horizontally 108697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dy Pixels to scroll vertically 108707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param duration Duration of the animation in milliseconds 108717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param interpolator Interpolator to be used when calculating scroll position in each 108727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animation step 108737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 108747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public Action(int dx, int dy, int duration, Interpolator interpolator) { 108757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mDx = dx; 108767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mDy = dy; 108777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mDuration = duration; 108787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mInterpolator = interpolator; 108797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 108807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 108817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 108827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Instead of specifying pixels to scroll, use the target position to jump using 108837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecyclerView#scrollToPosition(int)}. 108847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 108857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * You may prefer using this method if scroll target is really far away and you prefer 108867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to jump to a location and smooth scroll afterwards. 108877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 108887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that calling this method takes priority over other update methods such as 108897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #update(int, int, int, Interpolator)}, {@link #setX(float)}, 108907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #setY(float)} and #{@link #setInterpolator(Interpolator)}. If you call 108917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #jumpTo(int)}, the other changes will not be considered for this animation 108927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * frame. 108937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 108947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param targetPosition The target item position to scroll to using instant scrolling. 108957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 108967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void jumpTo(int targetPosition) { 108977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mJumpToPosition = targetPosition; 108987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 108997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 109007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean hasJumpTarget() { 109017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mJumpToPosition >= 0; 109027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 109037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 109047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void runIfNecessary(RecyclerView recyclerView) { 109057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mJumpToPosition >= 0) { 109067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int position = mJumpToPosition; 109077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mJumpToPosition = NO_POSITION; 109087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recyclerView.jumpToPositionForSmoothScroller(position); 109097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChanged = false; 109107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 109117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 109127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mChanged) { 109137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas validate(); 109147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mInterpolator == null) { 109157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mDuration == UNDEFINED_DURATION) { 109167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recyclerView.mViewFlinger.smoothScrollBy(mDx, mDy); 109177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 109187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recyclerView.mViewFlinger.smoothScrollBy(mDx, mDy, mDuration); 109197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 109207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 109217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas recyclerView.mViewFlinger.smoothScrollBy( 109227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mDx, mDy, mDuration, mInterpolator); 109237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 109247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mConsecutiveUpdates++; 109257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mConsecutiveUpdates > 10) { 109267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // A new action is being set in every animation step. This looks like a bad 109277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // implementation. Inform developer. 109287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Log.e(TAG, "Smooth Scroll action is being updated too frequently. Make sure" 109297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " you are not changing it unless necessary"); 109307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 109317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChanged = false; 109327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 109337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mConsecutiveUpdates = 0; 109347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 109357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 109367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 109377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private void validate() { 109387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mInterpolator != null && mDuration < 1) { 109397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException("If you provide an interpolator, you must" 109407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + " set a positive duration"); 109417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else if (mDuration < 1) { 109427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException("Scroll duration must be a positive number"); 109437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 109447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 109457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 109467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getDx() { 109477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mDx; 109487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 109497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 109507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setDx(int dx) { 109517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChanged = true; 109527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mDx = dx; 109537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 109547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 109557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getDy() { 109567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mDy; 109577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 109587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 109597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setDy(int dy) { 109607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChanged = true; 109617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mDy = dy; 109627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 109637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 109647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getDuration() { 109657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mDuration; 109667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 109677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 109687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setDuration(int duration) { 109697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChanged = true; 109707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mDuration = duration; 109717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 109727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 109737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public Interpolator getInterpolator() { 109747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mInterpolator; 109757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 109767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 109777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 109787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Sets the interpolator to calculate scroll steps 109797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param interpolator The interpolator to use. If you specify an interpolator, you must 109807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * also set the duration. 109817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #setDuration(int) 109827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 109837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setInterpolator(Interpolator interpolator) { 109847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChanged = true; 109857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mInterpolator = interpolator; 109867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 109877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 109887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 109897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Updates the action with given parameters. 109907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dx Pixels to scroll horizontally 109917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param dy Pixels to scroll vertically 109927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param duration Duration of the animation in milliseconds 109937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param interpolator Interpolator to be used when calculating scroll position in each 109947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animation step 109957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 109967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void update(int dx, int dy, int duration, Interpolator interpolator) { 109977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mDx = dx; 109987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mDy = dy; 109997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mDuration = duration; 110007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mInterpolator = interpolator; 110017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChanged = true; 110027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 110037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 110047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 110057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 110067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * An interface which is optionally implemented by custom {@link RecyclerView.LayoutManager} 110077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to provide a hint to a {@link SmoothScroller} about the location of the target position. 110087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 110097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public interface ScrollVectorProvider { 110107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 110117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Should calculate the vector that points to the direction where the target position 110127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * can be found. 110137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 110147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method is used by the {@link LinearSmoothScroller} to initiate a scroll towards 110157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the target position. 110167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 110177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The magnitude of the vector is not important. It is always normalized before being 110187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * used by the {@link LinearSmoothScroller}. 110197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 110207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManager should not check whether the position exists in the adapter or not. 110217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 110227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param targetPosition the target position to which the returned vector should point 110237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 110247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return the scroll vector for a given position. 110257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 110267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas PointF computeScrollVectorForPosition(int targetPosition); 110277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 110287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 110297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 110307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static class AdapterDataObservable extends Observable<AdapterDataObserver> { 110317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean hasObservers() { 110327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return !mObservers.isEmpty(); 110337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 110347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 110357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void notifyChanged() { 110367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // since onChanged() is implemented by the app, it could do anything, including 110377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // removing itself from {@link mObservers} - and that could cause problems if 110387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // an iterator is used on the ArrayList {@link mObservers}. 110397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // to avoid such problems, just march thru the list in the reverse order. 110407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = mObservers.size() - 1; i >= 0; i--) { 110417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mObservers.get(i).onChanged(); 110427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 110437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 110447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 110457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void notifyItemRangeChanged(int positionStart, int itemCount) { 110467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas notifyItemRangeChanged(positionStart, itemCount, null); 110477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 110487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 110497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void notifyItemRangeChanged(int positionStart, int itemCount, Object payload) { 110507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // since onItemRangeChanged() is implemented by the app, it could do anything, including 110517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // removing itself from {@link mObservers} - and that could cause problems if 110527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // an iterator is used on the ArrayList {@link mObservers}. 110537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // to avoid such problems, just march thru the list in the reverse order. 110547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = mObservers.size() - 1; i >= 0; i--) { 110557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mObservers.get(i).onItemRangeChanged(positionStart, itemCount, payload); 110567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 110577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 110587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 110597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void notifyItemRangeInserted(int positionStart, int itemCount) { 110607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // since onItemRangeInserted() is implemented by the app, it could do anything, 110617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // including removing itself from {@link mObservers} - and that could cause problems if 110627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // an iterator is used on the ArrayList {@link mObservers}. 110637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // to avoid such problems, just march thru the list in the reverse order. 110647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = mObservers.size() - 1; i >= 0; i--) { 110657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mObservers.get(i).onItemRangeInserted(positionStart, itemCount); 110667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 110677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 110687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 110697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void notifyItemRangeRemoved(int positionStart, int itemCount) { 110707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // since onItemRangeRemoved() is implemented by the app, it could do anything, including 110717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // removing itself from {@link mObservers} - and that could cause problems if 110727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // an iterator is used on the ArrayList {@link mObservers}. 110737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // to avoid such problems, just march thru the list in the reverse order. 110747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = mObservers.size() - 1; i >= 0; i--) { 110757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mObservers.get(i).onItemRangeRemoved(positionStart, itemCount); 110767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 110777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 110787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 110797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void notifyItemMoved(int fromPosition, int toPosition) { 110807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = mObservers.size() - 1; i >= 0; i--) { 110817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mObservers.get(i).onItemRangeMoved(fromPosition, toPosition, 1); 110827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 110837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 110847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 110857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 110867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 110877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This is public so that the CREATOR can be access on cold launch. 110887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @hide 110897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 110907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static class SavedState extends AbsSavedState { 110917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 110927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas Parcelable mLayoutState; 110937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 110947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 110957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * called by CREATOR 110967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 110977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas SavedState(Parcel in) { 110987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super(in); 110997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayoutState = in.readParcelable(LayoutManager.class.getClassLoader()); 111007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 111017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 111027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 111037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called by onSaveInstanceState 111047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 111057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas SavedState(Parcelable superState) { 111067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super(superState); 111077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 111087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 111097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 111107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void writeToParcel(Parcel dest, int flags) { 111117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas super.writeToParcel(dest, flags); 111127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas dest.writeParcelable(mLayoutState, 0); 111137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 111147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 111157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void copyFrom(SavedState other) { 111167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayoutState = other.mLayoutState; 111177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 111187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 111197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() { 111207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 111217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public SavedState createFromParcel(Parcel in) { 111227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return new SavedState(in); 111237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 111247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 111257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 111267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public SavedState[] newArray(int size) { 111277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return new SavedState[size]; 111287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 111297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas }; 111307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 111317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 111327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Contains useful information about the current RecyclerView state like target scroll 111337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * position or view focus. State object can also keep arbitrary data, identified by resource 111347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ids.</p> 111357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Often times, RecyclerView components will need to pass information between each other. 111367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * To provide a well defined data bus between components, RecyclerView passes the same State 111377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * object to component callbacks and these components can use it to exchange data.</p> 111387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>If you implement custom components, you can use State's put/get/remove methods to pass 111397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * data between your components without needing to manage their lifecycles.</p> 111407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 111417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static class State { 111427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final int STEP_START = 1; 111437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final int STEP_LAYOUT = 1 << 1; 111447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas static final int STEP_ANIMATIONS = 1 << 2; 111457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 111467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void assertLayoutStep(int accepted) { 111477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if ((accepted & mLayoutStep) == 0) { 111487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas throw new IllegalStateException("Layout state should be one of " 111497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + Integer.toBinaryString(accepted) + " but it is " 111507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + Integer.toBinaryString(mLayoutStep)); 111517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 111527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 111537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 111547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 111557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** Owned by SmoothScroller */ 111567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private int mTargetPosition = RecyclerView.NO_POSITION; 111577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 111587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private SparseArray<Object> mData; 111597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 111607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas //////////////////////////////////////////////////////////////////////////////////////////// 111617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Fields below are carried from one layout pass to the next 111627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas //////////////////////////////////////////////////////////////////////////////////////////// 111637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 111647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 111657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Number of items adapter had in the previous layout. 111667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 111677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int mPreviousLayoutItemCount = 0; 111687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 111697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 111707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Number of items that were NOT laid out but has been deleted from the adapter after the 111717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * previous layout. 111727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 111737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int mDeletedInvisibleItemCountSincePreviousLayout = 0; 111747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 111757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas //////////////////////////////////////////////////////////////////////////////////////////// 111767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Fields below must be updated or cleared before they are used (generally before a pass) 111777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas //////////////////////////////////////////////////////////////////////////////////////////// 111787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 111797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @IntDef(flag = true, value = { 111807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas STEP_START, STEP_LAYOUT, STEP_ANIMATIONS 111817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas }) 111827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Retention(RetentionPolicy.SOURCE) 111837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @interface LayoutState {} 111847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 111857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @LayoutState 111867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int mLayoutStep = STEP_START; 111877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 111887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 111897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Number of items adapter has. 111907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 111917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int mItemCount = 0; 111927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 111937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean mStructureChanged = false; 111947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 111957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean mInPreLayout = false; 111967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 111977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean mTrackOldChangeHolders = false; 111987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 111997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean mIsMeasuring = false; 112007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 112017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas //////////////////////////////////////////////////////////////////////////////////////////// 112027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // Fields below are always reset outside of the pass (or passes) that use them 112037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas //////////////////////////////////////////////////////////////////////////////////////////// 112047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 112057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean mRunSimpleAnimations = false; 112067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 112077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean mRunPredictiveAnimations = false; 112087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 112097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 112107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This data is saved before a layout calculation happens. After the layout is finished, 112117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * if the previously focused view has been replaced with another view for the same item, we 112127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * move the focus to the new item automatically. 112137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 112147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int mFocusedItemPosition; 112157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas long mFocusedItemId; 112167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // when a sub child has focus, record its id and see if we can directly request focus on 112177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // that one instead 112187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int mFocusedSubChildId; 112197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 112207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas //////////////////////////////////////////////////////////////////////////////////////////// 112217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 112227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas State reset() { 112237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTargetPosition = RecyclerView.NO_POSITION; 112247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mData != null) { 112257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mData.clear(); 112267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 112277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemCount = 0; 112287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mStructureChanged = false; 112297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mIsMeasuring = false; 112307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return this; 112317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 112327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 112337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 112347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Prepare for a prefetch occurring on the RecyclerView in between traversals, potentially 112357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * prior to any layout passes. 112367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 112377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Don't touch any state stored between layout passes, only reset per-layout state, so 112387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * that Recycler#getViewForPosition() can function safely.</p> 112397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 112407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void prepareForNestedPrefetch(Adapter adapter) { 112417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mLayoutStep = STEP_START; 112427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mItemCount = adapter.getItemCount(); 112437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mStructureChanged = false; 112447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mInPreLayout = false; 112457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mTrackOldChangeHolders = false; 112467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mIsMeasuring = false; 112477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 112487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 112497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 112507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns true if the RecyclerView is currently measuring the layout. This value is 112517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@code true} only if the LayoutManager opted into the auto measure API and RecyclerView 112527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * has non-exact measurement specs. 112537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 112547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that if the LayoutManager supports predictive animations and it is calculating the 112557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * pre-layout step, this value will be {@code false} even if the RecyclerView is in 112567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@code onMeasure} call. This is because pre-layout means the previous state of the 112577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView and measurements made for that state cannot change the RecyclerView's size. 112587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManager is always guaranteed to receive another call to 112597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link LayoutManager#onLayoutChildren(Recycler, State)} when this happens. 112607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 112617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return True if the RecyclerView is currently calculating its bounds, false otherwise. 112627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 112637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean isMeasuring() { 112647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mIsMeasuring; 112657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 112667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 112677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 112687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns true if 112697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return 112707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 112717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean isPreLayout() { 112727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mInPreLayout; 112737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 112747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 112757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 112767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns whether RecyclerView will run predictive animations in this layout pass 112777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * or not. 112787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 112797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if RecyclerView is calculating predictive animations to be run at the end 112807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * of the layout pass. 112817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 112827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean willRunPredictiveAnimations() { 112837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mRunPredictiveAnimations; 112847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 112857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 112867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 112877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns whether RecyclerView will run simple animations in this layout pass 112887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * or not. 112897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 112907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if RecyclerView is calculating simple animations to be run at the end of 112917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the layout pass. 112927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 112937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean willRunSimpleAnimations() { 112947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mRunSimpleAnimations; 112957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 112967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 112977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 112987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Removes the mapping from the specified id, if there was any. 112997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param resourceId Id of the resource you want to remove. It is suggested to use R.id.* to 113007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * preserve cross functionality and avoid conflicts. 113017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 113027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void remove(int resourceId) { 113037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mData == null) { 113047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return; 113057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 113067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mData.remove(resourceId); 113077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 113087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 113097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 113107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Gets the Object mapped from the specified id, or <code>null</code> 113117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * if no such data exists. 113127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 113137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param resourceId Id of the resource you want to remove. It is suggested to use R.id.* 113147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to 113157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * preserve cross functionality and avoid conflicts. 113167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 113177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public <T> T get(int resourceId) { 113187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mData == null) { 113197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return null; 113207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 113217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return (T) mData.get(resourceId); 113227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 113237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 113247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 113257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Adds a mapping from the specified id to the specified value, replacing the previous 113267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * mapping from the specified key if there was one. 113277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 113287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param resourceId Id of the resource you want to add. It is suggested to use R.id.* to 113297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * preserve cross functionality and avoid conflicts. 113307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param data The data you want to associate with the resourceId. 113317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 113327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void put(int resourceId, Object data) { 113337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mData == null) { 113347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mData = new SparseArray<Object>(); 113357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 113367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mData.put(resourceId, data); 113377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 113387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 113397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 113407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If scroll is triggered to make a certain item visible, this value will return the 113417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * adapter index of that item. 113427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return Adapter index of the target item or 113437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecyclerView#NO_POSITION} if there is no target 113447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * position. 113457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 113467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getTargetScrollPosition() { 113477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mTargetPosition; 113487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 113497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 113507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 113517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns if current scroll has a target position. 113527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if scroll is being triggered to make a certain position visible 113537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #getTargetScrollPosition() 113547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 113557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean hasTargetScrollPosition() { 113567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mTargetPosition != RecyclerView.NO_POSITION; 113577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 113587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 113597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 113607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if the structure of the data set has changed since the last call to 113617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * onLayoutChildren, false otherwise 113627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 113637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean didStructureChange() { 113647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mStructureChanged; 113657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 113667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 113677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 113687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the total number of items that can be laid out. Note that this number is not 113697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * necessarily equal to the number of items in the adapter, so you should always use this 113707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * number for your position calculations and never access the adapter directly. 113717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 113727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView listens for Adapter's notify events and calculates the effects of adapter 113737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * data changes on existing Views. These calculations are used to decide which animations 113747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * should be run. 113757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 113767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * To support predictive animations, RecyclerView may rewrite or reorder Adapter changes to 113777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * present the correct state to LayoutManager in pre-layout pass. 113787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 113797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * For example, a newly added item is not included in pre-layout item count because 113807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * pre-layout reflects the contents of the adapter before the item is added. Behind the 113817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * scenes, RecyclerView offsets {@link Recycler#getViewForPosition(int)} calls such that 113827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManager does not know about the new item's existence in pre-layout. The item will 113837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * be available in second layout pass and will be included in the item count. Similar 113847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * adjustments are made for moved and removed items as well. 113857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 113867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * You can get the adapter's item count via {@link LayoutManager#getItemCount()} method. 113877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 113887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The number of items currently available 113897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see LayoutManager#getItemCount() 113907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 113917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int getItemCount() { 113927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mInPreLayout 113937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ? (mPreviousLayoutItemCount - mDeletedInvisibleItemCountSincePreviousLayout) 113947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas : mItemCount; 113957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 113967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 113977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 113987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public String toString() { 113997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return "State{" 114007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + "mTargetPosition=" + mTargetPosition 114017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + ", mData=" + mData 114027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + ", mItemCount=" + mItemCount 114037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + ", mPreviousLayoutItemCount=" + mPreviousLayoutItemCount 114047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + ", mDeletedInvisibleItemCountSincePreviousLayout=" 114057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + mDeletedInvisibleItemCountSincePreviousLayout 114067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + ", mStructureChanged=" + mStructureChanged 114077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + ", mInPreLayout=" + mInPreLayout 114087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + ", mRunSimpleAnimations=" + mRunSimpleAnimations 114097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + ", mRunPredictiveAnimations=" + mRunPredictiveAnimations 114107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas + '}'; 114117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 114127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 114137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 114147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 114157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This class defines the behavior of fling if the developer wishes to handle it. 114167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 114177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Subclasses of {@link OnFlingListener} can be used to implement custom fling behavior. 114187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 114197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #setOnFlingListener(OnFlingListener) 114207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 114217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract static class OnFlingListener { 114227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 114237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 114247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Override this to handle a fling given the velocities in both x and y directions. 114257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that this method will only be called if the associated {@link LayoutManager} 114267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * supports scrolling and the fling is not handled by nested scrolls first. 114277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 114287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param velocityX the fling velocity on the X axis 114297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param velocityY the fling velocity on the Y axis 114307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 114317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if the fling washandled, false otherwise. 114327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 114337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract boolean onFling(int velocityX, int velocityY); 114347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 114357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 114367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 114377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Internal listener that manages items after animations finish. This is how items are 114387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * retained (not recycled) during animations, but allowed to be recycled afterwards. 114397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * It depends on the contract with the ItemAnimator to call the appropriate dispatch*Finished() 114407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * method on the animator's listener when it is done animating any item. 114417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 114427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private class ItemAnimatorRestoreListener implements ItemAnimator.ItemAnimatorListener { 114437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 114447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ItemAnimatorRestoreListener() { 114457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 114467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 114477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 114487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onAnimationFinished(ViewHolder item) { 114497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas item.setIsRecyclable(true); 114507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (item.mShadowedHolder != null && item.mShadowingHolder == null) { // old vh 114517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas item.mShadowedHolder = null; 114527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 114537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // always null this because an OldViewHolder can never become NewViewHolder w/o being 114547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas // recycled. 114557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas item.mShadowingHolder = null; 114567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!item.shouldBeKeptAsChild()) { 114577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!removeAnimatingView(item.itemView) && item.isTmpDetached()) { 114587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas removeDetachedView(item.itemView, false); 114597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 114607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 114617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 114627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 114637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 114647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 114657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This class defines the animations that take place on items as changes are made 114667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to the adapter. 114677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 114687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Subclasses of ItemAnimator can be used to implement custom animations for actions on 114697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ViewHolder items. The RecyclerView will manage retaining these items while they 114707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * are being animated, but implementors must call {@link #dispatchAnimationFinished(ViewHolder)} 114717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * when a ViewHolder's animation is finished. In other words, there must be a matching 114727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #dispatchAnimationFinished(ViewHolder)} call for each 114737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #animateAppearance(ViewHolder, ItemHolderInfo, ItemHolderInfo) animateAppearance()}, 114747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #animateChange(ViewHolder, ViewHolder, ItemHolderInfo, ItemHolderInfo) 114757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animateChange()} 114767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #animatePersistence(ViewHolder, ItemHolderInfo, ItemHolderInfo) animatePersistence()}, 114777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * and 114787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #animateDisappearance(ViewHolder, ItemHolderInfo, ItemHolderInfo) 114797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animateDisappearance()} call. 114807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 114817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>By default, RecyclerView uses {@link DefaultItemAnimator}.</p> 114827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 114837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #setItemAnimator(ItemAnimator) 114847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 114857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @SuppressWarnings("UnusedParameters") 114867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract static class ItemAnimator { 114877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 114887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 114897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The Item represented by this ViewHolder is updated. 114907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 114917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #recordPreLayoutInformation(State, ViewHolder, int, List) 114927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 114937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static final int FLAG_CHANGED = ViewHolder.FLAG_UPDATE; 114947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 114957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 114967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The Item represented by this ViewHolder is removed from the adapter. 114977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 114987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #recordPreLayoutInformation(State, ViewHolder, int, List) 114997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 115007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static final int FLAG_REMOVED = ViewHolder.FLAG_REMOVED; 115017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 115027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 115037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Adapter {@link Adapter#notifyDataSetChanged()} has been called and the content 115047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * represented by this ViewHolder is invalid. 115057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 115067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #recordPreLayoutInformation(State, ViewHolder, int, List) 115077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 115087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static final int FLAG_INVALIDATED = ViewHolder.FLAG_INVALID; 115097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 115107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 115117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The position of the Item represented by this ViewHolder has been changed. This flag is 115127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * not bound to {@link Adapter#notifyItemMoved(int, int)}. It might be set in response to 115137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * any adapter change that may have a side effect on this item. (e.g. The item before this 115147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * one has been removed from the Adapter). 115157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 115167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #recordPreLayoutInformation(State, ViewHolder, int, List) 115177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 115187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static final int FLAG_MOVED = ViewHolder.FLAG_MOVED; 115197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 115207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 115217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This ViewHolder was not laid out but has been added to the layout in pre-layout state 115227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * by the {@link LayoutManager}. This means that the item was already in the Adapter but 115237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * invisible and it may become visible in the post layout phase. LayoutManagers may prefer 115247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to add new items in pre-layout to specify their virtual location when they are invisible 115257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * (e.g. to specify the item should <i>animate in</i> from below the visible area). 115267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 115277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #recordPreLayoutInformation(State, ViewHolder, int, List) 115287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 115297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static final int FLAG_APPEARED_IN_PRE_LAYOUT = 115307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas ViewHolder.FLAG_APPEARED_IN_PRE_LAYOUT; 115317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 115327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 115337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The set of flags that might be passed to 115347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #recordPreLayoutInformation(State, ViewHolder, int, List)}. 115357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 115367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @IntDef(flag = true, value = { 115377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas FLAG_CHANGED, FLAG_REMOVED, FLAG_MOVED, FLAG_INVALIDATED, 115387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas FLAG_APPEARED_IN_PRE_LAYOUT 115397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas }) 115407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Retention(RetentionPolicy.SOURCE) 115417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public @interface AdapterChanges {} 115427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private ItemAnimatorListener mListener = null; 115437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private ArrayList<ItemAnimatorFinishedListener> mFinishedListeners = 115447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas new ArrayList<ItemAnimatorFinishedListener>(); 115457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 115467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private long mAddDuration = 120; 115477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private long mRemoveDuration = 120; 115487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private long mMoveDuration = 250; 115497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas private long mChangeDuration = 250; 115507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 115517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 115527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Gets the current duration for which all move animations will run. 115537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 115547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The current move duration 115557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 115567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public long getMoveDuration() { 115577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mMoveDuration; 115587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 115597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 115607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 115617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Sets the duration for which all move animations will run. 115627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 115637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param moveDuration The move duration 115647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 115657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setMoveDuration(long moveDuration) { 115667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mMoveDuration = moveDuration; 115677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 115687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 115697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 115707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Gets the current duration for which all add animations will run. 115717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 115727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The current add duration 115737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 115747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public long getAddDuration() { 115757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mAddDuration; 115767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 115777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 115787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 115797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Sets the duration for which all add animations will run. 115807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 115817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param addDuration The add duration 115827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 115837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setAddDuration(long addDuration) { 115847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mAddDuration = addDuration; 115857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 115867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 115877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 115887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Gets the current duration for which all remove animations will run. 115897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 115907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The current remove duration 115917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 115927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public long getRemoveDuration() { 115937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mRemoveDuration; 115947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 115957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 115967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 115977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Sets the duration for which all remove animations will run. 115987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 115997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param removeDuration The remove duration 116007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 116017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setRemoveDuration(long removeDuration) { 116027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mRemoveDuration = removeDuration; 116037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 116047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 116057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 116067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Gets the current duration for which all change animations will run. 116077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 116087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The current change duration 116097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 116107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public long getChangeDuration() { 116117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mChangeDuration; 116127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 116137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 116147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 116157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Sets the duration for which all change animations will run. 116167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 116177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param changeDuration The change duration 116187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 116197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void setChangeDuration(long changeDuration) { 116207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mChangeDuration = changeDuration; 116217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 116227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 116237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 116247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Internal only: 116257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Sets the listener that must be called when the animator is finished 116267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animating the item (or immediately if no animation happens). This is set 116277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * internally and is not intended to be set by external code. 116287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 116297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param listener The listener that must be called. 116307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 116317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void setListener(ItemAnimatorListener listener) { 116327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mListener = listener; 116337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 116347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 116357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 116367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called by the RecyclerView before the layout begins. Item animator should record 116377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * necessary information about the View before it is potentially rebound, moved or removed. 116387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 116397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The data returned from this method will be passed to the related <code>animate**</code> 116407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * methods. 116417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 116427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that this method may be called after pre-layout phase if LayoutManager adds new 116437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Views to the layout in pre-layout pass. 116447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 116457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The default implementation returns an {@link ItemHolderInfo} which holds the bounds of 116467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the View and the adapter change flags. 116477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 116487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state The current State of RecyclerView which includes some useful data 116497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * about the layout that will be calculated. 116507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param viewHolder The ViewHolder whose information should be recorded. 116517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param changeFlags Additional information about what changes happened in the Adapter 116527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * about the Item represented by this ViewHolder. For instance, if 116537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * item is deleted from the adapter, {@link #FLAG_REMOVED} will be set. 116547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param payloads The payload list that was previously passed to 116557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link Adapter#notifyItemChanged(int, Object)} or 116567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link Adapter#notifyItemRangeChanged(int, int, Object)}. 116577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 116587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return An ItemHolderInfo instance that preserves necessary information about the 116597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ViewHolder. This object will be passed back to related <code>animate**</code> methods 116607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * after layout is complete. 116617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 116627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #recordPostLayoutInformation(State, ViewHolder) 116637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #animateAppearance(ViewHolder, ItemHolderInfo, ItemHolderInfo) 116647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #animateDisappearance(ViewHolder, ItemHolderInfo, ItemHolderInfo) 116657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #animateChange(ViewHolder, ViewHolder, ItemHolderInfo, ItemHolderInfo) 116667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #animatePersistence(ViewHolder, ItemHolderInfo, ItemHolderInfo) 116677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 116687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public @NonNull ItemHolderInfo recordPreLayoutInformation(@NonNull State state, 116697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @NonNull ViewHolder viewHolder, @AdapterChanges int changeFlags, 116707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @NonNull List<Object> payloads) { 116717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return obtainHolderInfo().setFrom(viewHolder); 116727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 116737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 116747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 116757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called by the RecyclerView after the layout is complete. Item animator should record 116767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * necessary information about the View's final state. 116777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 116787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The data returned from this method will be passed to the related <code>animate**</code> 116797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * methods. 116807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 116817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The default implementation returns an {@link ItemHolderInfo} which holds the bounds of 116827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the View. 116837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 116847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param state The current State of RecyclerView which includes some useful data about 116857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the layout that will be calculated. 116867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param viewHolder The ViewHolder whose information should be recorded. 116877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 116887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return An ItemHolderInfo that preserves necessary information about the ViewHolder. 116897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This object will be passed back to related <code>animate**</code> methods when 116907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView decides how items should be animated. 116917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 116927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #recordPreLayoutInformation(State, ViewHolder, int, List) 116937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #animateAppearance(ViewHolder, ItemHolderInfo, ItemHolderInfo) 116947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #animateDisappearance(ViewHolder, ItemHolderInfo, ItemHolderInfo) 116957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #animateChange(ViewHolder, ViewHolder, ItemHolderInfo, ItemHolderInfo) 116967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #animatePersistence(ViewHolder, ItemHolderInfo, ItemHolderInfo) 116977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 116987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public @NonNull ItemHolderInfo recordPostLayoutInformation(@NonNull State state, 116997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @NonNull ViewHolder viewHolder) { 117007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return obtainHolderInfo().setFrom(viewHolder); 117017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 117027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 117037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 117047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called by the RecyclerView when a ViewHolder has disappeared from the layout. 117057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 117067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This means that the View was a child of the LayoutManager when layout started but has 117077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * been removed by the LayoutManager. It might have been removed from the adapter or simply 117087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * become invisible due to other factors. You can distinguish these two cases by checking 117097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the change flags that were passed to 117107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #recordPreLayoutInformation(State, ViewHolder, int, List)}. 117117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 117127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that when a ViewHolder both changes and disappears in the same layout pass, the 117137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animation callback method which will be called by the RecyclerView depends on the 117147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ItemAnimator's decision whether to re-use the same ViewHolder or not, and also the 117157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManager's decision whether to layout the changed version of a disappearing 117167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ViewHolder or not. RecyclerView will call 117177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #animateChange(ViewHolder, ViewHolder, ItemHolderInfo, ItemHolderInfo) 117187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animateChange} instead of {@code animateDisappearance} if and only if the ItemAnimator 117197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * returns {@code false} from 117207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #canReuseUpdatedViewHolder(ViewHolder) canReuseUpdatedViewHolder} and the 117217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManager lays out a new disappearing view that holds the updated information. 117227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Built-in LayoutManagers try to avoid laying out updated versions of disappearing views. 117237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 117247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If LayoutManager supports predictive animations, it might provide a target disappear 117257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * location for the View by laying it out in that location. When that happens, 117267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView will call {@link #recordPostLayoutInformation(State, ViewHolder)} and the 117277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * response of that call will be passed to this method as the <code>postLayoutInfo</code>. 117287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 117297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ItemAnimator must call {@link #dispatchAnimationFinished(ViewHolder)} when the animation 117307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * is complete (or instantly call {@link #dispatchAnimationFinished(ViewHolder)} if it 117317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * decides not to animate the view). 117327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 117337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param viewHolder The ViewHolder which should be animated 117347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param preLayoutInfo The information that was returned from 117357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #recordPreLayoutInformation(State, ViewHolder, int, List)}. 117367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param postLayoutInfo The information that was returned from 117377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #recordPostLayoutInformation(State, ViewHolder)}. Might be 117387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * null if the LayoutManager did not layout the item. 117397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 117407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if a later call to {@link #runPendingAnimations()} is requested, 117417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * false otherwise. 117427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 117437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract boolean animateDisappearance(@NonNull ViewHolder viewHolder, 117447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @NonNull ItemHolderInfo preLayoutInfo, @Nullable ItemHolderInfo postLayoutInfo); 117457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 117467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 117477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called by the RecyclerView when a ViewHolder is added to the layout. 117487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 117497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * In detail, this means that the ViewHolder was <b>not</b> a child when the layout started 117507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * but has been added by the LayoutManager. It might be newly added to the adapter or 117517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * simply become visible due to other factors. 117527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 117537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ItemAnimator must call {@link #dispatchAnimationFinished(ViewHolder)} when the animation 117547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * is complete (or instantly call {@link #dispatchAnimationFinished(ViewHolder)} if it 117557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * decides not to animate the view). 117567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 117577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param viewHolder The ViewHolder which should be animated 117587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param preLayoutInfo The information that was returned from 117597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #recordPreLayoutInformation(State, ViewHolder, int, List)}. 117607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Might be null if Item was just added to the adapter or 117617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManager does not support predictive animations or it could 117627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * not predict that this ViewHolder will become visible. 117637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param postLayoutInfo The information that was returned from {@link 117647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * #recordPreLayoutInformation(State, ViewHolder, int, List)}. 117657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 117667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if a later call to {@link #runPendingAnimations()} is requested, 117677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * false otherwise. 117687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 117697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract boolean animateAppearance(@NonNull ViewHolder viewHolder, 117707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Nullable ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo); 117717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 117727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 117737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called by the RecyclerView when a ViewHolder is present in both before and after the 117747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * layout and RecyclerView has not received a {@link Adapter#notifyItemChanged(int)} call 117757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * for it or a {@link Adapter#notifyDataSetChanged()} call. 117767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 117777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This ViewHolder still represents the same data that it was representing when the layout 117787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * started but its position / size may be changed by the LayoutManager. 117797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 117807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If the Item's layout position didn't change, RecyclerView still calls this method because 117817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * it does not track this information (or does not necessarily know that an animation is 117827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * not required). Your ItemAnimator should handle this case and if there is nothing to 117837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animate, it should call {@link #dispatchAnimationFinished(ViewHolder)} and return 117847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <code>false</code>. 117857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 117867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ItemAnimator must call {@link #dispatchAnimationFinished(ViewHolder)} when the animation 117877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * is complete (or instantly call {@link #dispatchAnimationFinished(ViewHolder)} if it 117887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * decides not to animate the view). 117897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 117907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param viewHolder The ViewHolder which should be animated 117917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param preLayoutInfo The information that was returned from 117927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #recordPreLayoutInformation(State, ViewHolder, int, List)}. 117937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param postLayoutInfo The information that was returned from {@link 117947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * #recordPreLayoutInformation(State, ViewHolder, int, List)}. 117957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 117967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if a later call to {@link #runPendingAnimations()} is requested, 117977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * false otherwise. 117987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 117997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract boolean animatePersistence(@NonNull ViewHolder viewHolder, 118007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @NonNull ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo); 118017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 118027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 118037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called by the RecyclerView when an adapter item is present both before and after the 118047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * layout and RecyclerView has received a {@link Adapter#notifyItemChanged(int)} call 118057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * for it. This method may also be called when 118067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link Adapter#notifyDataSetChanged()} is called and adapter has stable ids so that 118077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView could still rebind views to the same ViewHolders. If viewType changes when 118087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link Adapter#notifyDataSetChanged()} is called, this method <b>will not</b> be called, 118097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * instead, {@link #animateAppearance(ViewHolder, ItemHolderInfo, ItemHolderInfo)} will be 118107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * called for the new ViewHolder and the old one will be recycled. 118117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 118127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If this method is called due to a {@link Adapter#notifyDataSetChanged()} call, there is 118137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * a good possibility that item contents didn't really change but it is rebound from the 118147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * adapter. {@link DefaultItemAnimator} will skip animating the View if its location on the 118157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * screen didn't change and your animator should handle this case as well and avoid creating 118167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * unnecessary animations. 118177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 118187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * When an item is updated, ItemAnimator has a chance to ask RecyclerView to keep the 118197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * previous presentation of the item as-is and supply a new ViewHolder for the updated 118207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * presentation (see: {@link #canReuseUpdatedViewHolder(ViewHolder, List)}. 118217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This is useful if you don't know the contents of the Item and would like 118227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to cross-fade the old and the new one ({@link DefaultItemAnimator} uses this technique). 118237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 118247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * When you are writing a custom item animator for your layout, it might be more performant 118257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * and elegant to re-use the same ViewHolder and animate the content changes manually. 118267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 118277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * When {@link Adapter#notifyItemChanged(int)} is called, the Item's view type may change. 118287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If the Item's view type has changed or ItemAnimator returned <code>false</code> for 118297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * this ViewHolder when {@link #canReuseUpdatedViewHolder(ViewHolder, List)} was called, the 118307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <code>oldHolder</code> and <code>newHolder</code> will be different ViewHolder instances 118317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * which represent the same Item. In that case, only the new ViewHolder is visible 118327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to the LayoutManager but RecyclerView keeps old ViewHolder attached for animations. 118337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 118347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ItemAnimator must call {@link #dispatchAnimationFinished(ViewHolder)} for each distinct 118357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ViewHolder when their animation is complete 118367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * (or instantly call {@link #dispatchAnimationFinished(ViewHolder)} if it decides not to 118377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animate the view). 118387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 118397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If oldHolder and newHolder are the same instance, you should call 118407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #dispatchAnimationFinished(ViewHolder)} <b>only once</b>. 118417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 118427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that when a ViewHolder both changes and disappears in the same layout pass, the 118437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animation callback method which will be called by the RecyclerView depends on the 118447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ItemAnimator's decision whether to re-use the same ViewHolder or not, and also the 118457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManager's decision whether to layout the changed version of a disappearing 118467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ViewHolder or not. RecyclerView will call 118477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@code animateChange} instead of 118487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #animateDisappearance(ViewHolder, ItemHolderInfo, ItemHolderInfo) 118497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animateDisappearance} if and only if the ItemAnimator returns {@code false} from 118507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #canReuseUpdatedViewHolder(ViewHolder) canReuseUpdatedViewHolder} and the 118517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * LayoutManager lays out a new disappearing view that holds the updated information. 118527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Built-in LayoutManagers try to avoid laying out updated versions of disappearing views. 118537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 118547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param oldHolder The ViewHolder before the layout is started, might be the same 118557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * instance with newHolder. 118567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param newHolder The ViewHolder after the layout is finished, might be the same 118577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * instance with oldHolder. 118587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param preLayoutInfo The information that was returned from 118597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #recordPreLayoutInformation(State, ViewHolder, int, List)}. 118607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param postLayoutInfo The information that was returned from {@link 118617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * #recordPreLayoutInformation(State, ViewHolder, int, List)}. 118627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 118637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if a later call to {@link #runPendingAnimations()} is requested, 118647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * false otherwise. 118657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 118667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract boolean animateChange(@NonNull ViewHolder oldHolder, 118677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @NonNull ViewHolder newHolder, 118687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @NonNull ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo); 118697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 118707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @AdapterChanges static int buildAdapterChangeFlagsForAnimations(ViewHolder viewHolder) { 118717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int flags = viewHolder.mFlags & (FLAG_INVALIDATED | FLAG_REMOVED | FLAG_CHANGED); 118727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (viewHolder.isInvalid()) { 118737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return FLAG_INVALIDATED; 118747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 118757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if ((flags & FLAG_INVALIDATED) == 0) { 118767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int oldPos = viewHolder.getOldPosition(); 118777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int pos = viewHolder.getAdapterPosition(); 118787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (oldPos != NO_POSITION && pos != NO_POSITION && oldPos != pos) { 118797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas flags |= FLAG_MOVED; 118807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 118817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 118827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return flags; 118837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 118847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 118857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 118867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when there are pending animations waiting to be started. This state 118877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * is governed by the return values from 118887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #animateAppearance(ViewHolder, ItemHolderInfo, ItemHolderInfo) 118897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animateAppearance()}, 118907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #animateChange(ViewHolder, ViewHolder, ItemHolderInfo, ItemHolderInfo) 118917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animateChange()} 118927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #animatePersistence(ViewHolder, ItemHolderInfo, ItemHolderInfo) 118937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animatePersistence()}, and 118947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #animateDisappearance(ViewHolder, ItemHolderInfo, ItemHolderInfo) 118957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animateDisappearance()}, which inform the RecyclerView that the ItemAnimator wants to be 118967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * called later to start the associated animations. runPendingAnimations() will be scheduled 118977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * to be run on the next frame. 118987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 118997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract void runPendingAnimations(); 119007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 119017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 119027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Method called when an animation on a view should be ended immediately. 119037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This could happen when other events, like scrolling, occur, so that 119047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animating views can be quickly put into their proper end locations. 119057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Implementations should ensure that any animations running on the item 119067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * are canceled and affected properties are set to their end values. 119077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Also, {@link #dispatchAnimationFinished(ViewHolder)} should be called for each finished 119087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animation since the animations are effectively done when this method is called. 119097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 119107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param item The item for which an animation should be stopped. 119117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 119127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract void endAnimation(ViewHolder item); 119137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 119147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 119157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Method called when all item animations should be ended immediately. 119167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This could happen when other events, like scrolling, occur, so that 119177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animating views can be quickly put into their proper end locations. 119187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Implementations should ensure that any animations running on any items 119197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * are canceled and affected properties are set to their end values. 119207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Also, {@link #dispatchAnimationFinished(ViewHolder)} should be called for each finished 119217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animation since the animations are effectively done when this method is called. 119227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 119237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract void endAnimations(); 119247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 119257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 119267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Method which returns whether there are any item animations currently running. 119277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method can be used to determine whether to delay other actions until 119287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animations end. 119297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 119307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if there are any item animations currently running, false otherwise. 119317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 119327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public abstract boolean isRunning(); 119337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 119347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 119357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Method to be called by subclasses when an animation is finished. 119367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 119377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * For each call RecyclerView makes to 119387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #animateAppearance(ViewHolder, ItemHolderInfo, ItemHolderInfo) 119397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animateAppearance()}, 119407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #animatePersistence(ViewHolder, ItemHolderInfo, ItemHolderInfo) 119417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animatePersistence()}, or 119427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #animateDisappearance(ViewHolder, ItemHolderInfo, ItemHolderInfo) 119437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animateDisappearance()}, there 119447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * should 119457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * be a matching {@link #dispatchAnimationFinished(ViewHolder)} call by the subclass. 119467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 119477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * For {@link #animateChange(ViewHolder, ViewHolder, ItemHolderInfo, ItemHolderInfo) 119487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animateChange()}, subclass should call this method for both the <code>oldHolder</code> 119497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * and <code>newHolder</code> (if they are not the same instance). 119507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 119517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param viewHolder The ViewHolder whose animation is finished. 119527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #onAnimationFinished(ViewHolder) 119537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 119547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final void dispatchAnimationFinished(ViewHolder viewHolder) { 119557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onAnimationFinished(viewHolder); 119567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mListener != null) { 119577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mListener.onAnimationFinished(viewHolder); 119587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 119597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 119607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 119617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 119627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called after {@link #dispatchAnimationFinished(ViewHolder)} is called by the 119637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ItemAnimator. 119647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 119657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param viewHolder The ViewHolder whose animation is finished. There might still be other 119667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animations running on this ViewHolder. 119677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #dispatchAnimationFinished(ViewHolder) 119687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 119697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onAnimationFinished(ViewHolder viewHolder) { 119707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 119717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 119727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 119737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Method to be called by subclasses when an animation is started. 119747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 119757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * For each call RecyclerView makes to 119767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #animateAppearance(ViewHolder, ItemHolderInfo, ItemHolderInfo) 119777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animateAppearance()}, 119787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #animatePersistence(ViewHolder, ItemHolderInfo, ItemHolderInfo) 119797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animatePersistence()}, or 119807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #animateDisappearance(ViewHolder, ItemHolderInfo, ItemHolderInfo) 119817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animateDisappearance()}, there should be a matching 119827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #dispatchAnimationStarted(ViewHolder)} call by the subclass. 119837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 119847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * For {@link #animateChange(ViewHolder, ViewHolder, ItemHolderInfo, ItemHolderInfo) 119857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animateChange()}, subclass should call this method for both the <code>oldHolder</code> 119867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * and <code>newHolder</code> (if they are not the same instance). 119877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 119887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If your ItemAnimator decides not to animate a ViewHolder, it should call 119897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #dispatchAnimationFinished(ViewHolder)} <b>without</b> calling 119907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #dispatchAnimationStarted(ViewHolder)}. 119917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 119927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param viewHolder The ViewHolder whose animation is starting. 119937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #onAnimationStarted(ViewHolder) 119947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 119957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final void dispatchAnimationStarted(ViewHolder viewHolder) { 119967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas onAnimationStarted(viewHolder); 119977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 119987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 119997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 120007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Called when a new animation is started on the given ViewHolder. 120017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 120027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param viewHolder The ViewHolder which started animating. Note that the ViewHolder 120037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * might already be animating and this might be another animation. 120047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #dispatchAnimationStarted(ViewHolder) 120057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 120067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public void onAnimationStarted(ViewHolder viewHolder) { 120077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 120087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 120097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 120107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 120117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Like {@link #isRunning()}, this method returns whether there are any item 120127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animations currently running. Additionally, the listener passed in will be called 120137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * when there are no item animations running, either immediately (before the method 120147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * returns) if no animations are currently running, or when the currently running 120157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * animations are {@link #dispatchAnimationsFinished() finished}. 120167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 120177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p>Note that the listener is transient - it is either called immediately and not 120187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * stored at all, or stored only until it is called when running animations 120197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * are finished sometime later.</p> 120207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 120217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param listener A listener to be called immediately if no animations are running 120227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * or later when currently-running animations have finished. A null listener is 120237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * equivalent to calling {@link #isRunning()}. 120247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return true if there are any item animations currently running, false otherwise. 120257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 120267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final boolean isRunning(ItemAnimatorFinishedListener listener) { 120277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas boolean running = isRunning(); 120287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (listener != null) { 120297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (!running) { 120307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas listener.onAnimationsFinished(); 120317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 120327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mFinishedListeners.add(listener); 120337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 120347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 120357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return running; 120367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 120377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 120387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 120397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * When an item is changed, ItemAnimator can decide whether it wants to re-use 120407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the same ViewHolder for animations or RecyclerView should create a copy of the 120417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * item and ItemAnimator will use both to run the animation (e.g. cross-fade). 120427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 120437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that this method will only be called if the {@link ViewHolder} still has the same 120447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * type ({@link Adapter#getItemViewType(int)}). Otherwise, ItemAnimator will always receive 120457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * both {@link ViewHolder}s in the 120467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #animateChange(ViewHolder, ViewHolder, ItemHolderInfo, ItemHolderInfo)} method. 120477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 120487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If your application is using change payloads, you can override 120497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #canReuseUpdatedViewHolder(ViewHolder, List)} to decide based on payloads. 120507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 120517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param viewHolder The ViewHolder which represents the changed item's old content. 120527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 120537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return True if RecyclerView should just rebind to the same ViewHolder or false if 120547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView should create a new ViewHolder and pass this ViewHolder to the 120557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ItemAnimator to animate. Default implementation returns <code>true</code>. 120567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 120577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #canReuseUpdatedViewHolder(ViewHolder, List) 120587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 120597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean canReuseUpdatedViewHolder(@NonNull ViewHolder viewHolder) { 120607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return true; 120617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 120627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 120637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 120647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * When an item is changed, ItemAnimator can decide whether it wants to re-use 120657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the same ViewHolder for animations or RecyclerView should create a copy of the 120667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * item and ItemAnimator will use both to run the animation (e.g. cross-fade). 120677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 120687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Note that this method will only be called if the {@link ViewHolder} still has the same 120697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * type ({@link Adapter#getItemViewType(int)}). Otherwise, ItemAnimator will always receive 120707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * both {@link ViewHolder}s in the 120717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #animateChange(ViewHolder, ViewHolder, ItemHolderInfo, ItemHolderInfo)} method. 120727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 120737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param viewHolder The ViewHolder which represents the changed item's old content. 120747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param payloads A non-null list of merged payloads that were sent with change 120757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * notifications. Can be empty if the adapter is invalidated via 120767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecyclerView.Adapter#notifyDataSetChanged()}. The same list of 120777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * payloads will be passed into 120787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link RecyclerView.Adapter#onBindViewHolder(ViewHolder, int, List)} 120797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * method <b>if</b> this method returns <code>true</code>. 120807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 120817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return True if RecyclerView should just rebind to the same ViewHolder or false if 120827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * RecyclerView should create a new ViewHolder and pass this ViewHolder to the 120837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ItemAnimator to animate. Default implementation calls 120847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #canReuseUpdatedViewHolder(ViewHolder)}. 120857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 120867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #canReuseUpdatedViewHolder(ViewHolder) 120877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 120887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public boolean canReuseUpdatedViewHolder(@NonNull ViewHolder viewHolder, 120897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @NonNull List<Object> payloads) { 120907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return canReuseUpdatedViewHolder(viewHolder); 120917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 120927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 120937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 120947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This method should be called by ItemAnimator implementations to notify 120957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * any listeners that all pending and active item animations are finished. 120967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 120977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public final void dispatchAnimationsFinished() { 120987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final int count = mFinishedListeners.size(); 120997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas for (int i = 0; i < count; ++i) { 121007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mFinishedListeners.get(i).onAnimationsFinished(); 121017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 121027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas mFinishedListeners.clear(); 121037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 121047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 121057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 121067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns a new {@link ItemHolderInfo} which will be used to store information about the 121077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ViewHolder. This information will later be passed into <code>animate**</code> methods. 121087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 121097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * You can override this method if you want to extend {@link ItemHolderInfo} and provide 121107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * your own instances. 121117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 121127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return A new {@link ItemHolderInfo}. 121137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 121147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public ItemHolderInfo obtainHolderInfo() { 121157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return new ItemHolderInfo(); 121167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 121177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 121187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 121197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The interface to be implemented by listeners to animation events from this 121207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * ItemAnimator. This is used internally and is not intended for developers to 121217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * create directly. 121227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 121237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas interface ItemAnimatorListener { 121247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void onAnimationFinished(ViewHolder item); 121257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 121267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 121277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 121287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This interface is used to inform listeners when all pending or running animations 121297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * in an ItemAnimator are finished. This can be used, for example, to delay an action 121307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * in a data set until currently-running animations are complete. 121317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 121327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see #isRunning(ItemAnimatorFinishedListener) 121337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 121347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public interface ItemAnimatorFinishedListener { 121357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 121367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Notifies when all pending or running animations in an ItemAnimator are finished. 121377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 121387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas void onAnimationsFinished(); 121397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 121407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 121417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 121427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * A simple data structure that holds information about an item's bounds. 121437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * This information is used in calculating item animations. Default implementation of 121447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #recordPreLayoutInformation(RecyclerView.State, ViewHolder, int, List)} and 121457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #recordPostLayoutInformation(RecyclerView.State, ViewHolder)} returns this data 121467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * structure. You can extend this class if you would like to keep more information about 121477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the Views. 121487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 121497149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * If you want to provide your own implementation but still use `super` methods to record 121507149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * basic information, you can override {@link #obtainHolderInfo()} to provide your own 121517149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * instances. 121527149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 121537149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public static class ItemHolderInfo { 121547149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 121557149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 121567149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The left edge of the View (excluding decorations) 121577149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 121587149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int left; 121597149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 121607149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 121617149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The top edge of the View (excluding decorations) 121627149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 121637149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int top; 121647149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 121657149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 121667149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The right edge of the View (excluding decorations) 121677149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 121687149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int right; 121697149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 121707149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 121717149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The bottom edge of the View (excluding decorations) 121727149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 121737149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int bottom; 121747149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 121757149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 121767149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * The change flags that were passed to 121777149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #recordPreLayoutInformation(RecyclerView.State, ViewHolder, int, List)}. 121787149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 121797149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @AdapterChanges 121807149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public int changeFlags; 121817149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 121827149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public ItemHolderInfo() { 121837149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 121847149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 121857149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 121867149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Sets the {@link #left}, {@link #top}, {@link #right} and {@link #bottom} values from 121877149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the given ViewHolder. Clears all {@link #changeFlags}. 121887149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 121897149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param holder The ViewHolder whose bounds should be copied. 121907149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return This {@link ItemHolderInfo} 121917149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 121927149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public ItemHolderInfo setFrom(RecyclerView.ViewHolder holder) { 121937149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return setFrom(holder, 0); 121947149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 121957149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 121967149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 121977149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Sets the {@link #left}, {@link #top}, {@link #right} and {@link #bottom} values from 121987149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * the given ViewHolder and sets the {@link #changeFlags} to the given flags parameter. 121997149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 122007149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param holder The ViewHolder whose bounds should be copied. 122017149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param flags The adapter change flags that were passed into 122027149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * {@link #recordPreLayoutInformation(RecyclerView.State, ViewHolder, int, 122037149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * List)}. 122047149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return This {@link ItemHolderInfo} 122057149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 122067149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public ItemHolderInfo setFrom(RecyclerView.ViewHolder holder, 122077149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @AdapterChanges int flags) { 122087149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas final View view = holder.itemView; 122097149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas this.left = view.getLeft(); 122107149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas this.top = view.getTop(); 122117149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas this.right = view.getRight(); 122127149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas this.bottom = view.getBottom(); 122137149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return this; 122147149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 122157149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 122167149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 122177149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 122187149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas @Override 122197149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas protected int getChildDrawingOrder(int childCount, int i) { 122207149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas if (mChildDrawingOrderCallback == null) { 122217149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return super.getChildDrawingOrder(childCount, i); 122227149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } else { 122237149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas return mChildDrawingOrderCallback.onGetChildDrawingOrder(childCount, i); 122247149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 122257149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 122267149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas 122277149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 122287149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * A callback interface that can be used to alter the drawing order of RecyclerView children. 122297149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * <p> 122307149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * It works using the {@link ViewGroup#getChildDrawingOrder(int, int)} method, so any case 122317149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * that applies to that method also applies to this callback. For example, changing the drawing 122327149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * order of two views will not have any effect if their elevation values are different since 122337149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * elevation overrides the result of this callback. 122347149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 122357149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas public interface ChildDrawingOrderCallback { 122367149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas /** 122377149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * Returns the index of the child to draw for this iteration. Override this 122387149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * if you want to change the drawing order of children. By default, it 122397149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * returns i. 122407149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 122417149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @param i The current iteration. 122427149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @return The index of the child to draw this iteration. 122437149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * 122447149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas * @see RecyclerView#setChildDrawingOrderCallback(RecyclerView.ChildDrawingOrderCallback) 122457149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas */ 122467149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas int onGetChildDrawingOrder(int childCount, int i); 122477149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas } 122487149a63961c5fe6706160bc717a3b6cbb083ca54Aurimas Liutikas} 12249