RecyclerViewActivity.java revision 90e0922d7d57ad748b919dfe21c63f03987227e7
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.R; 21f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.app.Activity; 22f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.content.Context; 23f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.graphics.Rect; 24f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.os.Bundle; 25f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.support.v4.view.MenuItemCompat; 26f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.support.v7.widget.RecyclerView; 27f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.util.DisplayMetrics; 28f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.util.TypedValue; 29f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.view.Menu; 30f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.view.MenuItem; 31f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.view.View; 32f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.view.ViewGroup; 33f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.view.View.MeasureSpec; 34f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.widget.TextView; 35549b58504ef397f4c1524ec370bbd0569027e315Adam Powellimport com.example.android.supportv7.Cheeses; 36549b58504ef397f4c1524ec370bbd0569027e315Adam Powell 37549b58504ef397f4c1524ec370bbd0569027e315Adam Powellimport java.util.ArrayList; 38549b58504ef397f4c1524ec370bbd0569027e315Adam Powellimport java.util.Collections; 39f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 40f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellpublic class RecyclerViewActivity extends Activity { 41f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell private RecyclerView mRecyclerView; 42f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 43f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 44f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell protected void onCreate(Bundle savedInstanceState) { 45f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell super.onCreate(savedInstanceState); 46f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 47f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final RecyclerView rv = new RecyclerView(this); 48f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell rv.setLayoutManager(new MyLayoutManager(this)); 49f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell rv.setHasFixedSize(true); 50f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell rv.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 51f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell ViewGroup.LayoutParams.MATCH_PARENT)); 52549b58504ef397f4c1524ec370bbd0569027e315Adam Powell rv.setAdapter(new MyAdapter(Cheeses.sCheeseStrings)); 53f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell setContentView(rv); 54f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 55f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell mRecyclerView = rv; 56f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 57f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 58f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 59f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public boolean onCreateOptionsMenu(Menu menu) { 60f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell super.onCreateOptionsMenu(menu); 61f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell MenuItemCompat.setShowAsAction(menu.add("Layout"), MenuItemCompat.SHOW_AS_ACTION_IF_ROOM); 62f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return true; 63f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 64f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 65f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 66f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public boolean onOptionsItemSelected(MenuItem item) { 67f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell mRecyclerView.requestLayout(); 68f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return super.onOptionsItemSelected(item); 69f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 70f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 71f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell private static final int SCROLL_DISTANCE = 80; // dp 72f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 73f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell /** 74f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * A basic ListView-style LayoutManager. 75f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell */ 76f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell class MyLayoutManager extends RecyclerView.LayoutManager { 77f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell private static final String TAG = "MyLayoutManager"; 78f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell private int mFirstPosition; 79f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell private final int mScrollDistance; 80f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 81f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public MyLayoutManager(Context c) { 82f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final DisplayMetrics dm = c.getResources().getDisplayMetrics(); 83f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell mScrollDistance = (int) (SCROLL_DISTANCE * dm.density + 0.5f); 84f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 85f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 86f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 87f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public void layoutChildren(RecyclerView.Adapter adapter, RecyclerView.Recycler recycler) { 8890e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int parentBottom = getHeight() - getPaddingBottom(); 89f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 9090e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final View oldTopView = getChildCount() > 0 ? getChildAt(0) : null; 9190e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell int oldTop = getPaddingTop(); 92549b58504ef397f4c1524ec370bbd0569027e315Adam Powell if (oldTopView != null) { 93549b58504ef397f4c1524ec370bbd0569027e315Adam Powell oldTop = oldTopView.getTop(); 94549b58504ef397f4c1524ec370bbd0569027e315Adam Powell } 95549b58504ef397f4c1524ec370bbd0569027e315Adam Powell 96f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell recycler.scrapAllViewsAttached(); 97f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 98549b58504ef397f4c1524ec370bbd0569027e315Adam Powell int top = oldTop; 99f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell int bottom; 10090e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int left = getPaddingLeft(); 10190e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int right = getWidth() - getPaddingRight(); 102f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 103f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int count = adapter.getItemCount(); 104f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell for (int i = 0; mFirstPosition + i < count && top < parentBottom; i++, top = bottom) { 10590e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell View v = recycler.getViewForPosition(adapter, mFirstPosition + i); 106f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell addView(v, i); 107f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell v.measure(MeasureSpec.makeMeasureSpec(right - left, MeasureSpec.EXACTLY), 108f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 109f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell bottom = top + v.getMeasuredHeight(); 110f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell v.layout(left, top, right, bottom); 111f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 112f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 113f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell recycler.detachDirtyScrapViews(); 114f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 115f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 116f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 117f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public RecyclerView.LayoutParams generateDefaultLayoutParams() { 118f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 119f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell ViewGroup.LayoutParams.WRAP_CONTENT); 120f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 121f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 122f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 123f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public boolean canScrollVertically() { 124f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return true; 125f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 126f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 127f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 12890e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell public int scrollVerticallyBy(int dy, RecyclerView.Adapter adapter, 12990e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell RecyclerView.Recycler recycler) { 13090e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell if (getChildCount() == 0) { 131f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return 0; 132f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 133f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 134f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell int scrolled = 0; 13590e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int left = getPaddingLeft(); 13690e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int right = getWidth() - getPaddingRight(); 137f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (dy < 0) { 138f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell while (scrolled > dy) { 13990e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final View topView = getChildAt(0); 140f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int hangingTop = Math.max(-topView.getTop(), 0); 141f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int scrollBy = Math.min(scrolled - dy, hangingTop); 142f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell scrolled -= scrollBy; 14390e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell offsetChildrenVertical(scrollBy); 144f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (mFirstPosition > 0 && scrolled > dy) { 145f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell mFirstPosition--; 14690e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell View v = recycler.getViewForPosition(adapter, mFirstPosition); 147f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell addView(v, 0); 148f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell v.measure(MeasureSpec.makeMeasureSpec(right - left, MeasureSpec.EXACTLY), 149f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 150f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int bottom = topView.getTop(); // TODO decorated top? 151f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int top = bottom - v.getMeasuredHeight(); 152f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell v.layout(left, top, right, bottom); 153f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } else { 154f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell break; 155f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 156f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 157f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } else if (dy > 0) { 15890e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int parentHeight = getHeight(); 159f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell while (scrolled < dy) { 16090e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final View bottomView = getChildAt(getChildCount() - 1); 161f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int hangingBottom = Math.max(bottomView.getBottom() - parentHeight, 0); 162f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int scrollBy = -Math.min(dy - scrolled, hangingBottom); 163f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell scrolled -= scrollBy; 16490e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell offsetChildrenVertical(scrollBy); 16590e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell if (scrolled < dy && getItemCount() > mFirstPosition + getChildCount()) { 16690e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell View v = recycler.getViewForPosition(adapter, 16790e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell mFirstPosition + getChildCount()); 16890e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int top = getChildAt(getChildCount() - 1).getBottom(); 169f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell addView(v); 170f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell v.measure(MeasureSpec.makeMeasureSpec(right - left, MeasureSpec.EXACTLY), 171f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 172f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int bottom = top + v.getMeasuredHeight(); 173f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell v.layout(left, top, right, bottom); 174f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } else { 175f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell break; 176f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 177f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 178f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 179f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell detachAndScrapViewsOutOfBounds(recycler); 180f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return scrolled; 181f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 182f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 183f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 184f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public View onFocusSearchFailed(View focused, int direction, 18590e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell RecyclerView.Adapter adapter, RecyclerView.Recycler recycler) { 18690e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int oldCount = getChildCount(); 187f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 188f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (oldCount == 0) { 189f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return null; 190f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 191f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 19290e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int left = getPaddingLeft(); 19390e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int right = getWidth() - getPaddingRight(); 194f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 195f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell View toFocus = null; 196f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell int newViewsHeight = 0; 197f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (direction == View.FOCUS_UP || direction == View.FOCUS_BACKWARD) { 198f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell while (mFirstPosition > 0 && newViewsHeight < mScrollDistance) { 199f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell mFirstPosition--; 20090e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell View v = recycler.getViewForPosition(adapter, mFirstPosition); 20190e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int bottom = getChildAt(0).getTop(); // TODO decorated top? 202f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell addView(v, 0); 203f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell v.measure(MeasureSpec.makeMeasureSpec(right - left, MeasureSpec.EXACTLY), 204f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 205f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int top = bottom - v.getMeasuredHeight(); 206f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell v.layout(left, top, right, bottom); 207f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (v.isFocusable()) { 208f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell toFocus = v; 209f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell break; 210f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 211f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 212f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 213f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (direction == View.FOCUS_DOWN || direction == View.FOCUS_FORWARD) { 21490e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell while (mFirstPosition + getChildCount() < getItemCount() && 215f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell newViewsHeight < mScrollDistance) { 21690e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell View v = recycler.getViewForPosition(adapter, mFirstPosition + getChildCount()); 21790e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int top = getChildAt(getChildCount() - 1).getBottom(); 218f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell addView(v); 219f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell v.measure(MeasureSpec.makeMeasureSpec(right - left, MeasureSpec.EXACTLY), 220f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 221f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int bottom = top + v.getMeasuredHeight(); 222f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell v.layout(left, top, right, bottom); 223f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (v.isFocusable()) { 224f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell toFocus = v; 225f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell break; 226f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 227f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 228f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 229f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 230f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return toFocus; 231f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 232f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 233f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public void detachAndScrapViewsOutOfBounds(RecyclerView.Recycler recycler) { 23490e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int childCount = getChildCount(); 23590e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int parentWidth = getWidth(); 23690e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final int parentHeight = getHeight(); 237f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell boolean foundFirst = false; 238f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell int first = 0; 239f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell int last = 0; 240f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell for (int i = 0; i < childCount; i++) { 24190e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell final View v = getChildAt(i); 242f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (v.hasFocus() || (v.getRight() >= 0 && v.getLeft() <= parentWidth && 243f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell v.getBottom() >= 0 && v.getTop() <= parentHeight)) { 244f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (!foundFirst) { 245f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell first = i; 246f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell foundFirst = true; 247f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 248f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell last = i; 249f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 250f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 251f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell for (int i = childCount - 1; i > last; i--) { 25290e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell recycler.detachAndScrapView(getChildAt(i)); 253f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 25490e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell for (int i = first - 1; i >= 0; i--) { 25590e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell recycler.detachAndScrapView(getChildAt(i)); 256f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 25790e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell if (getChildCount() == 0) { 258f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell mFirstPosition = 0; 259f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } else { 260f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell mFirstPosition += first; 261f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 262f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 263f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 264f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 265f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell class MyAdapter extends RecyclerView.Adapter { 266f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell private int mBackground; 267549b58504ef397f4c1524ec370bbd0569027e315Adam Powell private ArrayList<String> mValues; 268f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 269549b58504ef397f4c1524ec370bbd0569027e315Adam Powell public MyAdapter(String[] strings) { 270f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell TypedValue val = new TypedValue(); 271f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell RecyclerViewActivity.this.getTheme().resolveAttribute( 272f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell R.attr.selectableItemBackground, val, true); 273f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell mBackground = val.resourceId; 27490e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell mValues = new ArrayList<String>(); 275549b58504ef397f4c1524ec370bbd0569027e315Adam Powell Collections.addAll(mValues, strings); 276f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 277f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 278f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 279f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public RecyclerView.ViewHolder createViewHolder(ViewGroup parent, int viewType) { 280549b58504ef397f4c1524ec370bbd0569027e315Adam Powell final ViewHolder h = new ViewHolder(new TextView(RecyclerViewActivity.this)); 281f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell h.textView.setMinimumHeight(128); 282f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell h.textView.setFocusable(true); 283f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell h.textView.setBackgroundResource(mBackground); 284549b58504ef397f4c1524ec370bbd0569027e315Adam Powell h.textView.setOnClickListener(new View.OnClickListener() { 285549b58504ef397f4c1524ec370bbd0569027e315Adam Powell @Override 286549b58504ef397f4c1524ec370bbd0569027e315Adam Powell public void onClick(View v) { 287549b58504ef397f4c1524ec370bbd0569027e315Adam Powell final int pos = h.getPosition(); 288549b58504ef397f4c1524ec370bbd0569027e315Adam Powell if (mValues.size() > pos + 1) { 289549b58504ef397f4c1524ec370bbd0569027e315Adam Powell final String t = mValues.get(pos); 290549b58504ef397f4c1524ec370bbd0569027e315Adam Powell mValues.set(pos, mValues.get(pos + 1)); 291549b58504ef397f4c1524ec370bbd0569027e315Adam Powell mValues.set(pos + 1, t); 292549b58504ef397f4c1524ec370bbd0569027e315Adam Powell notifyDataSetChanged(); 293549b58504ef397f4c1524ec370bbd0569027e315Adam Powell } 294549b58504ef397f4c1524ec370bbd0569027e315Adam Powell } 295549b58504ef397f4c1524ec370bbd0569027e315Adam Powell }); 296f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return h; 297f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 298f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 299f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 300f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public void bindViewHolder(RecyclerView.ViewHolder holder, int position) { 301549b58504ef397f4c1524ec370bbd0569027e315Adam Powell ((ViewHolder) holder).textView.setText(mValues.get(position)); 302f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 303f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 304f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 305f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public int getItemCount() { 306549b58504ef397f4c1524ec370bbd0569027e315Adam Powell return mValues.size(); 307f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 308f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 309f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 310f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell static class ViewHolder extends RecyclerView.ViewHolder { 311f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public TextView textView; 312f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 313f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public ViewHolder(TextView v) { 314f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell super(v); 315f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell textView = v; 316f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 317f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 318f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell} 319