RecyclerViewActivity.java revision 2a1ade8a82653e53f3d5b16c7e9d0ed9cb734101
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
20e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyarimport com.example.android.supportv7.Cheeses;
21e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyarimport com.example.android.supportv7.widget.adapter.SimpleStringAdapter;
22e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyarimport com.example.android.supportv7.widget.decorator.DividerItemDecoration;
23e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar
24f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.app.Activity;
25f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.content.Context;
26f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.os.Bundle;
27f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.support.v4.view.MenuItemCompat;
28f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.support.v7.widget.RecyclerView;
29f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.util.DisplayMetrics;
30f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.view.Menu;
31f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.view.MenuItem;
32f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.view.View;
33f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.view.ViewGroup;
34f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
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) {
59e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                        final int pos = vh.getPosition();
60e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                        if (pos + 1 < getItemCount()) {
61e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                            swap(pos, pos + 1);
62e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                        }
63e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                    }
64e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                });
65e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                return vh;
66e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar            }
67e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar        });
68e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar        rv.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));
69f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        setContentView(rv);
70f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        mRecyclerView = rv;
71f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    }
72f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
73f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    @Override
74f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    public boolean onCreateOptionsMenu(Menu menu) {
75f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        super.onCreateOptionsMenu(menu);
76f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        MenuItemCompat.setShowAsAction(menu.add("Layout"), MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
77f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        return true;
78f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    }
79f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
80f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    @Override
81f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    public boolean onOptionsItemSelected(MenuItem item) {
82f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        mRecyclerView.requestLayout();
83f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        return super.onOptionsItemSelected(item);
84f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    }
85f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
86f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    private static final int SCROLL_DISTANCE = 80; // dp
87f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
88f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    /**
89f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell     * A basic ListView-style LayoutManager.
90f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell     */
91f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    class MyLayoutManager extends RecyclerView.LayoutManager {
92e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar
93f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        private static final String TAG = "MyLayoutManager";
94e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar
95f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        private int mFirstPosition;
96e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar
97f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        private final int mScrollDistance;
98f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
99f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        public MyLayoutManager(Context c) {
100f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            final DisplayMetrics dm = c.getResources().getDisplayMetrics();
101f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            mScrollDistance = (int) (SCROLL_DISTANCE * dm.density + 0.5f);
102f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        }
103f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
104f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        @Override
1052a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar        public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
10690e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int parentBottom = getHeight() - getPaddingBottom();
10790e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final View oldTopView = getChildCount() > 0 ? getChildAt(0) : null;
10890e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            int oldTop = getPaddingTop();
109549b58504ef397f4c1524ec370bbd0569027e315Adam Powell            if (oldTopView != null) {
110549b58504ef397f4c1524ec370bbd0569027e315Adam Powell                oldTop = oldTopView.getTop();
111549b58504ef397f4c1524ec370bbd0569027e315Adam Powell            }
112549b58504ef397f4c1524ec370bbd0569027e315Adam Powell
11351edefe34ae8f6a1a1d08f9596360286a0f2d238Adam Powell            detachAndScrapAttachedViews(recycler);
114f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
115549b58504ef397f4c1524ec370bbd0569027e315Adam Powell            int top = oldTop;
116f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            int bottom;
11790e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int left = getPaddingLeft();
11890e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int right = getWidth() - getPaddingRight();
119f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
1202a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar            final int count = state.getItemCount();
121f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            for (int i = 0; mFirstPosition + i < count && top < parentBottom; i++, top = bottom) {
1222a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar                View v = recycler.getViewForPosition(mFirstPosition + i);
123f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                addView(v, i);
12463c8ab9435d707a23e2045af3be410ea7deed895Adam Powell                measureChildWithMargins(v, 0, 0);
125bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                bottom = top + getDecoratedMeasuredHeight(v);
126bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                layoutDecorated(v, left, top, right, bottom);
127f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
128f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        }
129f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
130f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        @Override
131f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        public RecyclerView.LayoutParams generateDefaultLayoutParams() {
132f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
133f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    ViewGroup.LayoutParams.WRAP_CONTENT);
134f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        }
135f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
136f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        @Override
137f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        public boolean canScrollVertically() {
138f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            return true;
139f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        }
140f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
141f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        @Override
1422a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar        public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler,
1432a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar                RecyclerView.State state) {
14490e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            if (getChildCount() == 0) {
145f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                return 0;
146f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
147f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
148f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            int scrolled = 0;
14990e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int left = getPaddingLeft();
15090e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int right = getWidth() - getPaddingRight();
151f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            if (dy < 0) {
152f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                while (scrolled > dy) {
15390e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell                    final View topView = getChildAt(0);
154bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    final int hangingTop = Math.max(-getDecoratedTop(topView), 0);
155f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    final int scrollBy = Math.min(scrolled - dy, hangingTop);
156f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    scrolled -= scrollBy;
15790e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell                    offsetChildrenVertical(scrollBy);
158f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    if (mFirstPosition > 0 && scrolled > dy) {
159f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        mFirstPosition--;
1602a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar                        View v = recycler.getViewForPosition(mFirstPosition);
161f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        addView(v, 0);
16263c8ab9435d707a23e2045af3be410ea7deed895Adam Powell                        measureChildWithMargins(v, 0, 0);
163bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        final int bottom = getDecoratedTop(topView);
164bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        final int top = bottom - getDecoratedMeasuredHeight(v);
165bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        layoutDecorated(v, left, top, right, bottom);
166f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    } else {
167f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        break;
168f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    }
169f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                }
170f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            } else if (dy > 0) {
17190e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell                final int parentHeight = getHeight();
172f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                while (scrolled < dy) {
17390e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell                    final View bottomView = getChildAt(getChildCount() - 1);
174bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    final int hangingBottom =
175bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                            Math.max(getDecoratedBottom(bottomView) - parentHeight, 0);
176f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    final int scrollBy = -Math.min(dy - scrolled, hangingBottom);
177f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    scrolled -= scrollBy;
17890e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell                    offsetChildrenVertical(scrollBy);
17990e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell                    if (scrolled < dy && getItemCount() > mFirstPosition + getChildCount()) {
1802a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar                        View v = recycler.getViewForPosition(mFirstPosition + getChildCount());
181bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        final int top = getDecoratedBottom(getChildAt(getChildCount() - 1));
182f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        addView(v);
18363c8ab9435d707a23e2045af3be410ea7deed895Adam Powell                        measureChildWithMargins(v, 0, 0);
184bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        final int bottom = top + getDecoratedMeasuredHeight(v);
185bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        layoutDecorated(v, left, top, right, bottom);
186f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    } else {
187f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        break;
188f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    }
189f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                }
190f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
19151edefe34ae8f6a1a1d08f9596360286a0f2d238Adam Powell            recycleViewsOutOfBounds(recycler);
192f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            return scrolled;
193f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        }
194f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
195f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        @Override
196f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        public View onFocusSearchFailed(View focused, int direction,
1972a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar                RecyclerView.Recycler recycler, RecyclerView.State state) {
19890e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int oldCount = getChildCount();
199f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
200f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            if (oldCount == 0) {
201f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                return null;
202f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
203f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
20490e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int left = getPaddingLeft();
20590e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int right = getWidth() - getPaddingRight();
206f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
207f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            View toFocus = null;
208f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            int newViewsHeight = 0;
209f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            if (direction == View.FOCUS_UP || direction == View.FOCUS_BACKWARD) {
210f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                while (mFirstPosition > 0 && newViewsHeight < mScrollDistance) {
211f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    mFirstPosition--;
2122a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar                    View v = recycler.getViewForPosition(mFirstPosition);
213bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    final int bottom = getDecoratedTop(getChildAt(0));
214f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    addView(v, 0);
21563c8ab9435d707a23e2045af3be410ea7deed895Adam Powell                    measureChildWithMargins(v, 0, 0);
216bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    final int top = bottom - getDecoratedMeasuredHeight(v);
217bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    layoutDecorated(v, left, top, right, bottom);
218f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    if (v.isFocusable()) {
219f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        toFocus = v;
220f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        break;
221f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    }
222f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                }
223f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
224f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            if (direction == View.FOCUS_DOWN || direction == View.FOCUS_FORWARD) {
22590e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell                while (mFirstPosition + getChildCount() < getItemCount() &&
226f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        newViewsHeight < mScrollDistance) {
2272a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar                    View v = recycler.getViewForPosition(mFirstPosition + getChildCount());
228bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    final int top = getDecoratedBottom(getChildAt(getChildCount() - 1));
229f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    addView(v);
23063c8ab9435d707a23e2045af3be410ea7deed895Adam Powell                    measureChildWithMargins(v, 0, 0);
231bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    final int bottom = top + getDecoratedMeasuredHeight(v);
232bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    layoutDecorated(v, left, top, right, bottom);
233f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    if (v.isFocusable()) {
234f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        toFocus = v;
235f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        break;
236f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    }
237f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                }
238f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
239f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
240f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            return toFocus;
241f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        }
242f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
24351edefe34ae8f6a1a1d08f9596360286a0f2d238Adam Powell        public void recycleViewsOutOfBounds(RecyclerView.Recycler recycler) {
24490e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int childCount = getChildCount();
24590e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int parentWidth = getWidth();
24690e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int parentHeight = getHeight();
247f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            boolean foundFirst = false;
248f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            int first = 0;
249f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            int last = 0;
250f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            for (int i = 0; i < childCount; i++) {
25190e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell                final View v = getChildAt(i);
252bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                if (v.hasFocus() || (getDecoratedRight(v) >= 0 &&
253bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        getDecoratedLeft(v) <= parentWidth &&
254bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        getDecoratedBottom(v) >= 0 &&
255bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        getDecoratedTop(v) <= parentHeight)) {
256f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    if (!foundFirst) {
257f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        first = i;
258f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        foundFirst = true;
259f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    }
260f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    last = i;
261f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                }
262f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
263f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            for (int i = childCount - 1; i > last; i--) {
26451edefe34ae8f6a1a1d08f9596360286a0f2d238Adam Powell                removeAndRecycleViewAt(i, recycler);
265f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
26690e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            for (int i = first - 1; i >= 0; i--) {
26751edefe34ae8f6a1a1d08f9596360286a0f2d238Adam Powell                removeAndRecycleViewAt(i, recycler);
268f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
26990e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            if (getChildCount() == 0) {
270f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                mFirstPosition = 0;
271f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            } else {
272f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                mFirstPosition += first;
273f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
274f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        }
275f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    }
276f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell}
277