RecyclerViewActivity.java revision 549b58504ef397f4c1524ec370bbd0569027e315
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) { 88f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final RecyclerView parent = getRecyclerView(); 89f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int parentBottom = parent.getHeight() - parent.getPaddingBottom(); 90f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 91549b58504ef397f4c1524ec370bbd0569027e315Adam Powell final View oldTopView = parent.getChildCount() > 0 ? parent.getChildAt(0) : null; 92549b58504ef397f4c1524ec370bbd0569027e315Adam Powell int oldTop = parent.getPaddingTop(); 93549b58504ef397f4c1524ec370bbd0569027e315Adam Powell if (oldTopView != null) { 94549b58504ef397f4c1524ec370bbd0569027e315Adam Powell oldTop = oldTopView.getTop(); 95549b58504ef397f4c1524ec370bbd0569027e315Adam Powell } 96549b58504ef397f4c1524ec370bbd0569027e315Adam Powell 97f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell recycler.scrapAllViewsAttached(); 98f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 99549b58504ef397f4c1524ec370bbd0569027e315Adam Powell int top = oldTop; 100f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell int bottom; 101f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int left = parent.getPaddingLeft(); 102f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int right = parent.getWidth() - parent.getPaddingRight(); 103f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 104f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int count = adapter.getItemCount(); 105f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell for (int i = 0; mFirstPosition + i < count && top < parentBottom; i++, top = bottom) { 106f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell View v = recycler.getViewForPosition(mFirstPosition + i); 107f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell addView(v, i); 108f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell v.measure(MeasureSpec.makeMeasureSpec(right - left, MeasureSpec.EXACTLY), 109f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 110f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell bottom = top + v.getMeasuredHeight(); 111f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell v.layout(left, top, right, bottom); 112f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 113f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 114f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell recycler.detachDirtyScrapViews(); 115f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 116f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 117f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 118f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public RecyclerView.LayoutParams generateDefaultLayoutParams() { 119f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 120f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell ViewGroup.LayoutParams.WRAP_CONTENT); 121f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 122f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 123f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 124f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public boolean canScrollVertically() { 125f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return true; 126f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 127f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 128f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 129f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler) { 130f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final RecyclerView parent = getRecyclerView(); 131f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (parent.getChildCount() == 0) { 132f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return 0; 133f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 134f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 135f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell int scrolled = 0; 136f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int left = parent.getPaddingLeft(); 137f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int right = parent.getWidth() - parent.getPaddingRight(); 138f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (dy < 0) { 139f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell while (scrolled > dy) { 140f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final View topView = parent.getChildAt(0); 141f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int hangingTop = Math.max(-topView.getTop(), 0); 142f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int scrollBy = Math.min(scrolled - dy, hangingTop); 143f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell scrolled -= scrollBy; 144f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell parent.offsetChildrenVertical(scrollBy); 145f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (mFirstPosition > 0 && scrolled > dy) { 146f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell mFirstPosition--; 147f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell View v = recycler.getViewForPosition(mFirstPosition); 148f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell addView(v, 0); 149f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell v.measure(MeasureSpec.makeMeasureSpec(right - left, MeasureSpec.EXACTLY), 150f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 151f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int bottom = topView.getTop(); // TODO decorated top? 152f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int top = bottom - v.getMeasuredHeight(); 153f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell v.layout(left, top, right, bottom); 154f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } else { 155f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell break; 156f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 157f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 158f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } else if (dy > 0) { 159f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int parentHeight = parent.getHeight(); 160f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell while (scrolled < dy) { 161f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final View bottomView = parent.getChildAt(parent.getChildCount() - 1); 162f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int hangingBottom = Math.max(bottomView.getBottom() - parentHeight, 0); 163f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int scrollBy = -Math.min(dy - scrolled, hangingBottom); 164f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell scrolled -= scrollBy; 165f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell parent.offsetChildrenVertical(scrollBy); 166f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (scrolled < dy && 167f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell parent.getAdapter().getItemCount() > mFirstPosition + parent.getChildCount()) { 168f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell View v = recycler.getViewForPosition( 169f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell mFirstPosition + parent.getChildCount()); 170f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int top = parent.getChildAt(parent.getChildCount() - 1).getBottom(); 171f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell addView(v); 172f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell v.measure(MeasureSpec.makeMeasureSpec(right - left, MeasureSpec.EXACTLY), 173f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 174f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int bottom = top + v.getMeasuredHeight(); 175f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell v.layout(left, top, right, bottom); 176f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } else { 177f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell break; 178f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 179f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 180f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 181f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell detachAndScrapViewsOutOfBounds(recycler); 182f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return scrolled; 183f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 184f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 185f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 186f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public View onFocusSearchFailed(View focused, int direction, 187f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell RecyclerView.Recycler recycler) { 188f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final RecyclerView rv = getRecyclerView(); 189f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int oldFirstPosition = mFirstPosition; 190f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int oldCount = rv.getChildCount(); 191f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 192f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (oldCount == 0) { 193f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return null; 194f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 195f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 196f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int left = rv.getPaddingLeft(); 197f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int right = rv.getWidth() - rv.getPaddingRight(); 198f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 199f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell View toFocus = null; 200f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell int newViewsHeight = 0; 201f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (direction == View.FOCUS_UP || direction == View.FOCUS_BACKWARD) { 202f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell while (mFirstPosition > 0 && newViewsHeight < mScrollDistance) { 203f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell mFirstPosition--; 204f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell View v = recycler.getViewForPosition(mFirstPosition); 205f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int bottom = rv.getChildAt(0).getTop(); // TODO decorated top? 206f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell addView(v, 0); 207f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell v.measure(MeasureSpec.makeMeasureSpec(right - left, MeasureSpec.EXACTLY), 208f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 209f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int top = bottom - v.getMeasuredHeight(); 210f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell v.layout(left, top, right, bottom); 211f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (v.isFocusable()) { 212f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell toFocus = v; 213f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell break; 214f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 215f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 216f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 217f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (direction == View.FOCUS_DOWN || direction == View.FOCUS_FORWARD) { 218f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell while (mFirstPosition + rv.getChildCount() < rv.getAdapter().getItemCount() && 219f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell newViewsHeight < mScrollDistance) { 220f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell View v = recycler.getViewForPosition(mFirstPosition + rv.getChildCount()); 221f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int top = rv.getChildAt(rv.getChildCount() - 1).getBottom(); 222f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell addView(v); 223f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell v.measure(MeasureSpec.makeMeasureSpec(right - left, MeasureSpec.EXACTLY), 224f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 225f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int bottom = top + v.getMeasuredHeight(); 226f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell v.layout(left, top, right, bottom); 227f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (v.isFocusable()) { 228f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell toFocus = v; 229f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell break; 230f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 231f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 232f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 233f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 234f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return toFocus; 235f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 236f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 237f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public void detachAndScrapViewsOutOfBounds(RecyclerView.Recycler recycler) { 238f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final RecyclerView parent = getRecyclerView(); 239f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int childCount = parent.getChildCount(); 240f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int parentWidth = parent.getWidth(); 241f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final int parentHeight = parent.getHeight(); 242f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell boolean foundFirst = false; 243f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell int first = 0; 244f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell int last = 0; 245f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell for (int i = 0; i < childCount; i++) { 246f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell final View v = parent.getChildAt(i); 247f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (v.hasFocus() || (v.getRight() >= 0 && v.getLeft() <= parentWidth && 248f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell v.getBottom() >= 0 && v.getTop() <= parentHeight)) { 249f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (!foundFirst) { 250f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell first = i; 251f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell foundFirst = true; 252f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 253f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell last = i; 254f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 255f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 256f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell for (int i = childCount - 1; i > last; i--) { 257f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell recycler.detachAndScrapView(parent.getChildAt(i)); 258f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 259f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell for (int i = 0; i < first; i++) { 260f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell recycler.detachAndScrapView(parent.getChildAt(i)); 261f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 262f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell if (parent.getChildCount() == 0) { 263f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell mFirstPosition = 0; 264f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } else { 265f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell mFirstPosition += first; 266f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 267f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 268f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 269f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 270f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell class MyAdapter extends RecyclerView.Adapter { 271f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell private int mBackground; 272549b58504ef397f4c1524ec370bbd0569027e315Adam Powell private ArrayList<String> mValues; 273f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 274549b58504ef397f4c1524ec370bbd0569027e315Adam Powell public MyAdapter(String[] strings) { 275f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell TypedValue val = new TypedValue(); 276f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell RecyclerViewActivity.this.getTheme().resolveAttribute( 277f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell R.attr.selectableItemBackground, val, true); 278f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell mBackground = val.resourceId; 279549b58504ef397f4c1524ec370bbd0569027e315Adam Powell mValues = new ArrayList(); 280549b58504ef397f4c1524ec370bbd0569027e315Adam Powell Collections.addAll(mValues, strings); 281f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 282f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 283f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 284f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public RecyclerView.ViewHolder createViewHolder(ViewGroup parent, int viewType) { 285549b58504ef397f4c1524ec370bbd0569027e315Adam Powell final ViewHolder h = new ViewHolder(new TextView(RecyclerViewActivity.this)); 286f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell h.textView.setMinimumHeight(128); 287f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell h.textView.setFocusable(true); 288f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell h.textView.setBackgroundResource(mBackground); 289549b58504ef397f4c1524ec370bbd0569027e315Adam Powell h.textView.setOnClickListener(new View.OnClickListener() { 290549b58504ef397f4c1524ec370bbd0569027e315Adam Powell @Override 291549b58504ef397f4c1524ec370bbd0569027e315Adam Powell public void onClick(View v) { 292549b58504ef397f4c1524ec370bbd0569027e315Adam Powell final int pos = h.getPosition(); 293549b58504ef397f4c1524ec370bbd0569027e315Adam Powell if (mValues.size() > pos + 1) { 294549b58504ef397f4c1524ec370bbd0569027e315Adam Powell final String t = mValues.get(pos); 295549b58504ef397f4c1524ec370bbd0569027e315Adam Powell mValues.set(pos, mValues.get(pos + 1)); 296549b58504ef397f4c1524ec370bbd0569027e315Adam Powell mValues.set(pos + 1, t); 297549b58504ef397f4c1524ec370bbd0569027e315Adam Powell notifyDataSetChanged(); 298549b58504ef397f4c1524ec370bbd0569027e315Adam Powell } 299549b58504ef397f4c1524ec370bbd0569027e315Adam Powell } 300549b58504ef397f4c1524ec370bbd0569027e315Adam Powell }); 301f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell return h; 302f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 303f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 304f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 305f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public void bindViewHolder(RecyclerView.ViewHolder holder, int position) { 306549b58504ef397f4c1524ec370bbd0569027e315Adam Powell ((ViewHolder) holder).textView.setText(mValues.get(position)); 307f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 308f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 309f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell @Override 310f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public int getItemCount() { 311549b58504ef397f4c1524ec370bbd0569027e315Adam Powell return mValues.size(); 312f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 313f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 314f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 315f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell static class ViewHolder extends RecyclerView.ViewHolder { 316f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public TextView textView; 317f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell 318f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell public ViewHolder(TextView v) { 319f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell super(v); 320f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell textView = v; 321f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 322f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell } 323f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell} 324