1f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell/* 2f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * Copyright (C) 2013 The Android Open Source Project 3f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * 4f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * you may not use this file except in compliance with the License. 6f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * You may obtain a copy of the License at 7f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * 8f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * http://www.apache.org/licenses/LICENSE-2.0 9f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * 10f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * Unless required by applicable law or agreed to in writing, software 11f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * distributed under the License is distributed on an "AS IS" BASIS, 12f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * See the License for the specific language governing permissions and 14f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * limitations under the License. 15f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell */ 16f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 17f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 18f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellpackage com.example.android.supportv7.widget; 19f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 20f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.app.Activity; 21f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.content.Context; 22f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.os.Bundle; 23f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.util.DisplayMetrics; 24f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.view.Menu; 25f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.view.MenuItem; 26f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.view.View; 27f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.view.ViewGroup; 28f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 29def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.recyclerview.widget.DividerItemDecoration; 30def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.recyclerview.widget.RecyclerView; 31def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikas 327febb12feeade9937fc0bd1a8e5967251c4aad24Aurimas Liutikasimport com.example.android.supportv7.Cheeses; 337febb12feeade9937fc0bd1a8e5967251c4aad24Aurimas Liutikasimport com.example.android.supportv7.widget.adapter.SimpleStringAdapter; 347febb12feeade9937fc0bd1a8e5967251c4aad24Aurimas Liutikas 35f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellpublic class RecyclerViewActivity extends Activity { 36e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar 37bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell private static final String TAG = "RecyclerViewActivity"; 38bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell 39f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell private RecyclerView mRecyclerView; 40f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 41f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 42f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell protected void onCreate(Bundle savedInstanceState) { 43f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell super.onCreate(savedInstanceState); 44f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 45f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final RecyclerView rv = new RecyclerView(this); 46f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell rv.setLayoutManager(new MyLayoutManager(this)); 47f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell rv.setHasFixedSize(true); 48f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell rv.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 49f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell ViewGroup.LayoutParams.MATCH_PARENT)); 50e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar rv.setAdapter(new SimpleStringAdapter(this, Cheeses.sCheeseStrings) { 51e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar @Override 52e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar public SimpleStringAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, 53e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar int viewType) { 54e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar final SimpleStringAdapter.ViewHolder vh = super 55e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar .onCreateViewHolder(parent, viewType); 56e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar vh.itemView.setOnClickListener(new View.OnClickListener() { 57e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar @Override 58e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar public void onClick(View v) { 594fa1fe35a2e2f6aa8973bbb698f5191b7acc8d95Yigit Boyar final int pos = vh.getAdapterPosition(); 604fa1fe35a2e2f6aa8973bbb698f5191b7acc8d95Yigit Boyar if (pos == RecyclerView.NO_POSITION) { 614fa1fe35a2e2f6aa8973bbb698f5191b7acc8d95Yigit Boyar return; 624fa1fe35a2e2f6aa8973bbb698f5191b7acc8d95Yigit Boyar } 63e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar if (pos + 1 < getItemCount()) { 64e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar swap(pos, pos + 1); 65e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar } 66e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar } 67e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar }); 68e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar return vh; 69e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar } 70e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar }); 717febb12feeade9937fc0bd1a8e5967251c4aad24Aurimas Liutikas rv.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL)); 72f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell setContentView(rv); 73f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell mRecyclerView = rv; 74f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 75f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 76f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 77f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public boolean onCreateOptionsMenu(Menu menu) { 78f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell super.onCreateOptionsMenu(menu); 79458543f38db49fdcb1764f007ded33820964c3feAurimas Liutikas menu.add("Layout").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); 80f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return true; 81f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 82f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 83f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 84f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public boolean onOptionsItemSelected(MenuItem item) { 85f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell mRecyclerView.requestLayout(); 86f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return super.onOptionsItemSelected(item); 87f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 88f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 89f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell private static final int SCROLL_DISTANCE = 80; // dp 90f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 91f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell /** 92f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * A basic ListView-style LayoutManager. 93f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell */ 94f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell class MyLayoutManager extends RecyclerView.LayoutManager { 95e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar 96f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell private static final String TAG = "MyLayoutManager"; 97e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar 98f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell private int mFirstPosition; 99e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar 100f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell private final int mScrollDistance; 101f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 102f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public MyLayoutManager(Context c) { 103f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final DisplayMetrics dm = c.getResources().getDisplayMetrics(); 104f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell mScrollDistance = (int) (SCROLL_DISTANCE * dm.density + 0.5f); 105f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 106f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 107f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 1082a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { 10990e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int parentBottom = getHeight() - getPaddingBottom(); 11090e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final View oldTopView = getChildCount() > 0 ? getChildAt(0) : null; 11190e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell int oldTop = getPaddingTop(); 112549b58504ef397f4c1524ec370bbd0569027e315Adam Powell if (oldTopView != null) { 113549b58504ef397f4c1524ec370bbd0569027e315Adam Powell oldTop = oldTopView.getTop(); 114549b58504ef397f4c1524ec370bbd0569027e315Adam Powell } 115549b58504ef397f4c1524ec370bbd0569027e315Adam Powell 11651edefe34ae8f6a1a1d08f9596360286a0f2d238Adam Powell detachAndScrapAttachedViews(recycler); 117f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 118549b58504ef397f4c1524ec370bbd0569027e315Adam Powell int top = oldTop; 119f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell int bottom; 12090e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int left = getPaddingLeft(); 12190e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int right = getWidth() - getPaddingRight(); 122f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 1232a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar final int count = state.getItemCount(); 124f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell for (int i = 0; mFirstPosition + i < count && top < parentBottom; i++, top = bottom) { 1252a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar View v = recycler.getViewForPosition(mFirstPosition + i); 126f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell addView(v, i); 12763c8ab9435d707a23e2045af3be410ea7deed895Adam Powell measureChildWithMargins(v, 0, 0); 128bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell bottom = top + getDecoratedMeasuredHeight(v); 129bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell layoutDecorated(v, left, top, right, bottom); 130f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 131f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 132f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 133f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 134f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public RecyclerView.LayoutParams generateDefaultLayoutParams() { 135f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 136f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell ViewGroup.LayoutParams.WRAP_CONTENT); 137f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 138f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 139f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 140f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public boolean canScrollVertically() { 141f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return true; 142f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 143f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 144f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 1452a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, 1462a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar RecyclerView.State state) { 14790e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell if (getChildCount() == 0) { 148f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return 0; 149f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 150f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 151f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell int scrolled = 0; 15290e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int left = getPaddingLeft(); 15390e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int right = getWidth() - getPaddingRight(); 154f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (dy < 0) { 155f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell while (scrolled > dy) { 15690e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final View topView = getChildAt(0); 157bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell final int hangingTop = Math.max(-getDecoratedTop(topView), 0); 158f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int scrollBy = Math.min(scrolled - dy, hangingTop); 159f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell scrolled -= scrollBy; 16090e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell offsetChildrenVertical(scrollBy); 161f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (mFirstPosition > 0 && scrolled > dy) { 162f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell mFirstPosition--; 1632a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar View v = recycler.getViewForPosition(mFirstPosition); 164f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell addView(v, 0); 16563c8ab9435d707a23e2045af3be410ea7deed895Adam Powell measureChildWithMargins(v, 0, 0); 166bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell final int bottom = getDecoratedTop(topView); 167bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell final int top = bottom - getDecoratedMeasuredHeight(v); 168bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell layoutDecorated(v, left, top, right, bottom); 169f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } else { 170f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell break; 171f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 172f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 173f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } else if (dy > 0) { 17490e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int parentHeight = getHeight(); 175f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell while (scrolled < dy) { 17690e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final View bottomView = getChildAt(getChildCount() - 1); 177bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell final int hangingBottom = 178bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell Math.max(getDecoratedBottom(bottomView) - parentHeight, 0); 179f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int scrollBy = -Math.min(dy - scrolled, hangingBottom); 180f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell scrolled -= scrollBy; 18190e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell offsetChildrenVertical(scrollBy); 1828b38db9f287670f670f631a0ec4b95882cdd0705Yigit Boyar if (scrolled < dy && state.getItemCount() > mFirstPosition + getChildCount()) { 1832a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar View v = recycler.getViewForPosition(mFirstPosition + getChildCount()); 184bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell final int top = getDecoratedBottom(getChildAt(getChildCount() - 1)); 185f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell addView(v); 18663c8ab9435d707a23e2045af3be410ea7deed895Adam Powell measureChildWithMargins(v, 0, 0); 187bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell final int bottom = top + getDecoratedMeasuredHeight(v); 188bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell layoutDecorated(v, left, top, right, bottom); 189f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } else { 190f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell break; 191f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 192f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 193f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 19451edefe34ae8f6a1a1d08f9596360286a0f2d238Adam Powell recycleViewsOutOfBounds(recycler); 195f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return scrolled; 196f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 197f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 198f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 199f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public View onFocusSearchFailed(View focused, int direction, 2002a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar RecyclerView.Recycler recycler, RecyclerView.State state) { 20190e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int oldCount = getChildCount(); 202f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 203f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (oldCount == 0) { 204f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return null; 205f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 206f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 20790e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int left = getPaddingLeft(); 20890e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int right = getWidth() - getPaddingRight(); 209f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 210f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell View toFocus = null; 211f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell int newViewsHeight = 0; 212f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (direction == View.FOCUS_UP || direction == View.FOCUS_BACKWARD) { 213f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell while (mFirstPosition > 0 && newViewsHeight < mScrollDistance) { 214f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell mFirstPosition--; 2152a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar View v = recycler.getViewForPosition(mFirstPosition); 216bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell final int bottom = getDecoratedTop(getChildAt(0)); 217f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell addView(v, 0); 21863c8ab9435d707a23e2045af3be410ea7deed895Adam Powell measureChildWithMargins(v, 0, 0); 219bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell final int top = bottom - getDecoratedMeasuredHeight(v); 220bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell layoutDecorated(v, left, top, right, bottom); 221f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (v.isFocusable()) { 222f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell toFocus = v; 223f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell break; 224f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 225f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 226f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 227f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (direction == View.FOCUS_DOWN || direction == View.FOCUS_FORWARD) { 2288b38db9f287670f670f631a0ec4b95882cdd0705Yigit Boyar while (mFirstPosition + getChildCount() < state.getItemCount() && 229f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell newViewsHeight < mScrollDistance) { 2302a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar View v = recycler.getViewForPosition(mFirstPosition + getChildCount()); 231bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell final int top = getDecoratedBottom(getChildAt(getChildCount() - 1)); 232f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell addView(v); 23363c8ab9435d707a23e2045af3be410ea7deed895Adam Powell measureChildWithMargins(v, 0, 0); 234bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell final int bottom = top + getDecoratedMeasuredHeight(v); 235bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell layoutDecorated(v, left, top, right, bottom); 236f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (v.isFocusable()) { 237f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell toFocus = v; 238f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell break; 239f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 240f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 241f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 242f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 243f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return toFocus; 244f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 245f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 24651edefe34ae8f6a1a1d08f9596360286a0f2d238Adam Powell public void recycleViewsOutOfBounds(RecyclerView.Recycler recycler) { 24790e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int childCount = getChildCount(); 24890e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int parentWidth = getWidth(); 24990e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int parentHeight = getHeight(); 250f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell boolean foundFirst = false; 251f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell int first = 0; 252f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell int last = 0; 253f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell for (int i = 0; i < childCount; i++) { 25490e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final View v = getChildAt(i); 255bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell if (v.hasFocus() || (getDecoratedRight(v) >= 0 && 256bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell getDecoratedLeft(v) <= parentWidth && 257bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell getDecoratedBottom(v) >= 0 && 258bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell getDecoratedTop(v) <= parentHeight)) { 259f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (!foundFirst) { 260f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell first = i; 261f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell foundFirst = true; 262f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 263f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell last = i; 264f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 265f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 266f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell for (int i = childCount - 1; i > last; i--) { 26751edefe34ae8f6a1a1d08f9596360286a0f2d238Adam Powell removeAndRecycleViewAt(i, recycler); 268f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 26990e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell for (int i = first - 1; i >= 0; i--) { 27051edefe34ae8f6a1a1d08f9596360286a0f2d238Adam Powell removeAndRecycleViewAt(i, recycler); 271f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 27290e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell if (getChildCount() == 0) { 273f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell mFirstPosition = 0; 274f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } else { 275f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell mFirstPosition += first; 276f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 277f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 278f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 279f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell} 280