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