1f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell/*
2f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * Copyright (C) 2013 The Android Open Source Project
3f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell *
4f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * Licensed under the Apache License, Version 2.0 (the "License");
5f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * you may not use this file except in compliance with the License.
6f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * You may obtain a copy of the License at
7f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell *
8f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell *      http://www.apache.org/licenses/LICENSE-2.0
9f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell *
10f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * Unless required by applicable law or agreed to in writing, software
11f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * distributed under the License is distributed on an "AS IS" BASIS,
12f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * See the License for the specific language governing permissions and
14f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell * limitations under the License.
15f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell */
16f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
17f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
18f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellpackage com.example.android.supportv7.widget;
19f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
20f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.app.Activity;
21f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.content.Context;
22f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.os.Bundle;
237febb12feeade9937fc0bd1a8e5967251c4aad24Aurimas Liutikasimport android.support.v7.widget.DividerItemDecoration;
24f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.support.v7.widget.RecyclerView;
25f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.util.DisplayMetrics;
26f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.view.Menu;
27f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.view.MenuItem;
28f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.view.View;
29f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.view.ViewGroup;
30f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
317febb12feeade9937fc0bd1a8e5967251c4aad24Aurimas Liutikasimport com.example.android.supportv7.Cheeses;
327febb12feeade9937fc0bd1a8e5967251c4aad24Aurimas Liutikasimport com.example.android.supportv7.widget.adapter.SimpleStringAdapter;
337febb12feeade9937fc0bd1a8e5967251c4aad24Aurimas Liutikas
34f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellpublic class RecyclerViewActivity extends Activity {
35e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar
36bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell    private static final String TAG = "RecyclerViewActivity";
37bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell
38f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    private RecyclerView mRecyclerView;
39f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
40f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    @Override
41f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    protected void onCreate(Bundle savedInstanceState) {
42f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        super.onCreate(savedInstanceState);
43f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
44f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        final RecyclerView rv = new RecyclerView(this);
45f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        rv.setLayoutManager(new MyLayoutManager(this));
46f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        rv.setHasFixedSize(true);
47f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        rv.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
48f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                ViewGroup.LayoutParams.MATCH_PARENT));
49e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar        rv.setAdapter(new SimpleStringAdapter(this, Cheeses.sCheeseStrings) {
50e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar            @Override
51e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar            public SimpleStringAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
52e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                    int viewType) {
53e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                final SimpleStringAdapter.ViewHolder vh = super
54e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                        .onCreateViewHolder(parent, viewType);
55e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                vh.itemView.setOnClickListener(new View.OnClickListener() {
56e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                    @Override
57e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                    public void onClick(View v) {
584fa1fe35a2e2f6aa8973bbb698f5191b7acc8d95Yigit Boyar                        final int pos = vh.getAdapterPosition();
594fa1fe35a2e2f6aa8973bbb698f5191b7acc8d95Yigit Boyar                        if (pos == RecyclerView.NO_POSITION) {
604fa1fe35a2e2f6aa8973bbb698f5191b7acc8d95Yigit Boyar                            return;
614fa1fe35a2e2f6aa8973bbb698f5191b7acc8d95Yigit Boyar                        }
62e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                        if (pos + 1 < getItemCount()) {
63e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                            swap(pos, pos + 1);
64e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                        }
65e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                    }
66e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                });
67e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                return vh;
68e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar            }
69e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar        });
707febb12feeade9937fc0bd1a8e5967251c4aad24Aurimas Liutikas        rv.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
71f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        setContentView(rv);
72f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        mRecyclerView = rv;
73f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    }
74f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
75f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    @Override
76f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    public boolean onCreateOptionsMenu(Menu menu) {
77f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        super.onCreateOptionsMenu(menu);
78458543f38db49fdcb1764f007ded33820964c3feAurimas Liutikas        menu.add("Layout").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
79f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        return true;
80f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    }
81f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
82f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    @Override
83f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    public boolean onOptionsItemSelected(MenuItem item) {
84f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        mRecyclerView.requestLayout();
85f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        return super.onOptionsItemSelected(item);
86f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    }
87f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
88f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    private static final int SCROLL_DISTANCE = 80; // dp
89f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
90f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    /**
91f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell     * A basic ListView-style LayoutManager.
92f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell     */
93f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    class MyLayoutManager extends RecyclerView.LayoutManager {
94e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar
95f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        private static final String TAG = "MyLayoutManager";
96e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar
97f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        private int mFirstPosition;
98e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar
99f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        private final int mScrollDistance;
100f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
101f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        public MyLayoutManager(Context c) {
102f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            final DisplayMetrics dm = c.getResources().getDisplayMetrics();
103f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            mScrollDistance = (int) (SCROLL_DISTANCE * dm.density + 0.5f);
104f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        }
105f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
106f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        @Override
1072a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar        public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
10890e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int parentBottom = getHeight() - getPaddingBottom();
10990e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final View oldTopView = getChildCount() > 0 ? getChildAt(0) : null;
11090e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            int oldTop = getPaddingTop();
111549b58504ef397f4c1524ec370bbd0569027e315Adam Powell            if (oldTopView != null) {
112549b58504ef397f4c1524ec370bbd0569027e315Adam Powell                oldTop = oldTopView.getTop();
113549b58504ef397f4c1524ec370bbd0569027e315Adam Powell            }
114549b58504ef397f4c1524ec370bbd0569027e315Adam Powell
11551edefe34ae8f6a1a1d08f9596360286a0f2d238Adam Powell            detachAndScrapAttachedViews(recycler);
116f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
117549b58504ef397f4c1524ec370bbd0569027e315Adam Powell            int top = oldTop;
118f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            int bottom;
11990e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int left = getPaddingLeft();
12090e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int right = getWidth() - getPaddingRight();
121f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
1222a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar            final int count = state.getItemCount();
123f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            for (int i = 0; mFirstPosition + i < count && top < parentBottom; i++, top = bottom) {
1242a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar                View v = recycler.getViewForPosition(mFirstPosition + i);
125f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                addView(v, i);
12663c8ab9435d707a23e2045af3be410ea7deed895Adam Powell                measureChildWithMargins(v, 0, 0);
127bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                bottom = top + getDecoratedMeasuredHeight(v);
128bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                layoutDecorated(v, left, top, right, bottom);
129f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
130f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        }
131f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
132f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        @Override
133f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        public RecyclerView.LayoutParams generateDefaultLayoutParams() {
134f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
135f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    ViewGroup.LayoutParams.WRAP_CONTENT);
136f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        }
137f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
138f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        @Override
139f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        public boolean canScrollVertically() {
140f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            return true;
141f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        }
142f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
143f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        @Override
1442a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar        public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler,
1452a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar                RecyclerView.State state) {
14690e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            if (getChildCount() == 0) {
147f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                return 0;
148f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
149f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
150f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            int scrolled = 0;
15190e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int left = getPaddingLeft();
15290e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int right = getWidth() - getPaddingRight();
153f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            if (dy < 0) {
154f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                while (scrolled > dy) {
15590e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell                    final View topView = getChildAt(0);
156bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    final int hangingTop = Math.max(-getDecoratedTop(topView), 0);
157f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    final int scrollBy = Math.min(scrolled - dy, hangingTop);
158f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    scrolled -= scrollBy;
15990e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell                    offsetChildrenVertical(scrollBy);
160f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    if (mFirstPosition > 0 && scrolled > dy) {
161f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        mFirstPosition--;
1622a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar                        View v = recycler.getViewForPosition(mFirstPosition);
163f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        addView(v, 0);
16463c8ab9435d707a23e2045af3be410ea7deed895Adam Powell                        measureChildWithMargins(v, 0, 0);
165bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        final int bottom = getDecoratedTop(topView);
166bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        final int top = bottom - getDecoratedMeasuredHeight(v);
167bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        layoutDecorated(v, left, top, right, bottom);
168f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    } else {
169f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        break;
170f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    }
171f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                }
172f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            } else if (dy > 0) {
17390e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell                final int parentHeight = getHeight();
174f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                while (scrolled < dy) {
17590e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell                    final View bottomView = getChildAt(getChildCount() - 1);
176bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    final int hangingBottom =
177bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                            Math.max(getDecoratedBottom(bottomView) - parentHeight, 0);
178f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    final int scrollBy = -Math.min(dy - scrolled, hangingBottom);
179f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    scrolled -= scrollBy;
18090e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell                    offsetChildrenVertical(scrollBy);
1818b38db9f287670f670f631a0ec4b95882cdd0705Yigit Boyar                    if (scrolled < dy && state.getItemCount() > mFirstPosition + getChildCount()) {
1822a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar                        View v = recycler.getViewForPosition(mFirstPosition + getChildCount());
183bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        final int top = getDecoratedBottom(getChildAt(getChildCount() - 1));
184f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        addView(v);
18563c8ab9435d707a23e2045af3be410ea7deed895Adam Powell                        measureChildWithMargins(v, 0, 0);
186bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        final int bottom = top + getDecoratedMeasuredHeight(v);
187bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        layoutDecorated(v, left, top, right, bottom);
188f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    } else {
189f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        break;
190f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    }
191f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                }
192f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
19351edefe34ae8f6a1a1d08f9596360286a0f2d238Adam Powell            recycleViewsOutOfBounds(recycler);
194f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            return scrolled;
195f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        }
196f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
197f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        @Override
198f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        public View onFocusSearchFailed(View focused, int direction,
1992a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar                RecyclerView.Recycler recycler, RecyclerView.State state) {
20090e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int oldCount = getChildCount();
201f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
202f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            if (oldCount == 0) {
203f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                return null;
204f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
205f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
20690e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int left = getPaddingLeft();
20790e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int right = getWidth() - getPaddingRight();
208f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
209f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            View toFocus = null;
210f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            int newViewsHeight = 0;
211f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            if (direction == View.FOCUS_UP || direction == View.FOCUS_BACKWARD) {
212f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                while (mFirstPosition > 0 && newViewsHeight < mScrollDistance) {
213f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    mFirstPosition--;
2142a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar                    View v = recycler.getViewForPosition(mFirstPosition);
215bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    final int bottom = getDecoratedTop(getChildAt(0));
216f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    addView(v, 0);
21763c8ab9435d707a23e2045af3be410ea7deed895Adam Powell                    measureChildWithMargins(v, 0, 0);
218bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    final int top = bottom - getDecoratedMeasuredHeight(v);
219bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    layoutDecorated(v, left, top, right, bottom);
220f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    if (v.isFocusable()) {
221f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        toFocus = v;
222f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        break;
223f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    }
224f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                }
225f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
226f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            if (direction == View.FOCUS_DOWN || direction == View.FOCUS_FORWARD) {
2278b38db9f287670f670f631a0ec4b95882cdd0705Yigit Boyar                while (mFirstPosition + getChildCount() < state.getItemCount() &&
228f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        newViewsHeight < mScrollDistance) {
2292a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar                    View v = recycler.getViewForPosition(mFirstPosition + getChildCount());
230bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    final int top = getDecoratedBottom(getChildAt(getChildCount() - 1));
231f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    addView(v);
23263c8ab9435d707a23e2045af3be410ea7deed895Adam Powell                    measureChildWithMargins(v, 0, 0);
233bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    final int bottom = top + getDecoratedMeasuredHeight(v);
234bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    layoutDecorated(v, left, top, right, bottom);
235f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    if (v.isFocusable()) {
236f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        toFocus = v;
237f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        break;
238f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    }
239f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                }
240f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
241f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
242f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            return toFocus;
243f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        }
244f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
24551edefe34ae8f6a1a1d08f9596360286a0f2d238Adam Powell        public void recycleViewsOutOfBounds(RecyclerView.Recycler recycler) {
24690e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int childCount = getChildCount();
24790e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int parentWidth = getWidth();
24890e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int parentHeight = getHeight();
249f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            boolean foundFirst = false;
250f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            int first = 0;
251f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            int last = 0;
252f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            for (int i = 0; i < childCount; i++) {
25390e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell                final View v = getChildAt(i);
254bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                if (v.hasFocus() || (getDecoratedRight(v) >= 0 &&
255bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        getDecoratedLeft(v) <= parentWidth &&
256bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        getDecoratedBottom(v) >= 0 &&
257bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        getDecoratedTop(v) <= parentHeight)) {
258f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    if (!foundFirst) {
259f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        first = i;
260f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        foundFirst = true;
261f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    }
262f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    last = i;
263f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                }
264f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
265f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            for (int i = childCount - 1; i > last; i--) {
26651edefe34ae8f6a1a1d08f9596360286a0f2d238Adam Powell                removeAndRecycleViewAt(i, recycler);
267f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
26890e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            for (int i = first - 1; i >= 0; i--) {
26951edefe34ae8f6a1a1d08f9596360286a0f2d238Adam Powell                removeAndRecycleViewAt(i, recycler);
270f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
27190e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            if (getChildCount() == 0) {
272f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                mFirstPosition = 0;
273f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            } else {
274f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                mFirstPosition += first;
275f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
276f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        }
277f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    }
278f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell}
279