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;
23f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.util.DisplayMetrics;
24f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.view.Menu;
25f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.view.MenuItem;
26f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.view.View;
27f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powellimport android.view.ViewGroup;
28f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
29def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.recyclerview.widget.DividerItemDecoration;
30def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.recyclerview.widget.RecyclerView;
31def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikas
327febb12feeade9937fc0bd1a8e5967251c4aad24Aurimas Liutikasimport com.example.android.supportv7.Cheeses;
337febb12feeade9937fc0bd1a8e5967251c4aad24Aurimas Liutikasimport com.example.android.supportv7.widget.adapter.SimpleStringAdapter;
347febb12feeade9937fc0bd1a8e5967251c4aad24Aurimas Liutikas
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) {
594fa1fe35a2e2f6aa8973bbb698f5191b7acc8d95Yigit Boyar                        final int pos = vh.getAdapterPosition();
604fa1fe35a2e2f6aa8973bbb698f5191b7acc8d95Yigit Boyar                        if (pos == RecyclerView.NO_POSITION) {
614fa1fe35a2e2f6aa8973bbb698f5191b7acc8d95Yigit Boyar                            return;
624fa1fe35a2e2f6aa8973bbb698f5191b7acc8d95Yigit Boyar                        }
63e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                        if (pos + 1 < getItemCount()) {
64e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                            swap(pos, pos + 1);
65e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                        }
66e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                    }
67e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                });
68e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar                return vh;
69e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar            }
70e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar        });
717febb12feeade9937fc0bd1a8e5967251c4aad24Aurimas Liutikas        rv.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
72f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        setContentView(rv);
73f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        mRecyclerView = rv;
74f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    }
75f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
76f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    @Override
77f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    public boolean onCreateOptionsMenu(Menu menu) {
78f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        super.onCreateOptionsMenu(menu);
79458543f38db49fdcb1764f007ded33820964c3feAurimas Liutikas        menu.add("Layout").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
80f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        return true;
81f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    }
82f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
83f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    @Override
84f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    public boolean onOptionsItemSelected(MenuItem item) {
85f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        mRecyclerView.requestLayout();
86f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        return super.onOptionsItemSelected(item);
87f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    }
88f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
89f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    private static final int SCROLL_DISTANCE = 80; // dp
90f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
91f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    /**
92f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell     * A basic ListView-style LayoutManager.
93f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell     */
94f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    class MyLayoutManager extends RecyclerView.LayoutManager {
95e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar
96f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        private static final String TAG = "MyLayoutManager";
97e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar
98f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        private int mFirstPosition;
99e9f9a04c426e7423db0cd58ec8d2dc3ff2238a30Yigit Boyar
100f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        private final int mScrollDistance;
101f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
102f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        public MyLayoutManager(Context c) {
103f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            final DisplayMetrics dm = c.getResources().getDisplayMetrics();
104f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            mScrollDistance = (int) (SCROLL_DISTANCE * dm.density + 0.5f);
105f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        }
106f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
107f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        @Override
1082a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar        public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
10990e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int parentBottom = getHeight() - getPaddingBottom();
11090e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final View oldTopView = getChildCount() > 0 ? getChildAt(0) : null;
11190e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            int oldTop = getPaddingTop();
112549b58504ef397f4c1524ec370bbd0569027e315Adam Powell            if (oldTopView != null) {
113549b58504ef397f4c1524ec370bbd0569027e315Adam Powell                oldTop = oldTopView.getTop();
114549b58504ef397f4c1524ec370bbd0569027e315Adam Powell            }
115549b58504ef397f4c1524ec370bbd0569027e315Adam Powell
11651edefe34ae8f6a1a1d08f9596360286a0f2d238Adam Powell            detachAndScrapAttachedViews(recycler);
117f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
118549b58504ef397f4c1524ec370bbd0569027e315Adam Powell            int top = oldTop;
119f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            int bottom;
12090e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int left = getPaddingLeft();
12190e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int right = getWidth() - getPaddingRight();
122f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
1232a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar            final int count = state.getItemCount();
124f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            for (int i = 0; mFirstPosition + i < count && top < parentBottom; i++, top = bottom) {
1252a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar                View v = recycler.getViewForPosition(mFirstPosition + i);
126f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                addView(v, i);
12763c8ab9435d707a23e2045af3be410ea7deed895Adam Powell                measureChildWithMargins(v, 0, 0);
128bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                bottom = top + getDecoratedMeasuredHeight(v);
129bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                layoutDecorated(v, left, top, right, bottom);
130f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
131f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        }
132f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
133f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        @Override
134f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        public RecyclerView.LayoutParams generateDefaultLayoutParams() {
135f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
136f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    ViewGroup.LayoutParams.WRAP_CONTENT);
137f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        }
138f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
139f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        @Override
140f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        public boolean canScrollVertically() {
141f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            return true;
142f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        }
143f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
144f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        @Override
1452a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar        public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler,
1462a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar                RecyclerView.State state) {
14790e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            if (getChildCount() == 0) {
148f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                return 0;
149f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
150f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
151f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            int scrolled = 0;
15290e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int left = getPaddingLeft();
15390e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int right = getWidth() - getPaddingRight();
154f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            if (dy < 0) {
155f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                while (scrolled > dy) {
15690e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell                    final View topView = getChildAt(0);
157bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    final int hangingTop = Math.max(-getDecoratedTop(topView), 0);
158f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    final int scrollBy = Math.min(scrolled - dy, hangingTop);
159f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    scrolled -= scrollBy;
16090e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell                    offsetChildrenVertical(scrollBy);
161f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    if (mFirstPosition > 0 && scrolled > dy) {
162f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        mFirstPosition--;
1632a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar                        View v = recycler.getViewForPosition(mFirstPosition);
164f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        addView(v, 0);
16563c8ab9435d707a23e2045af3be410ea7deed895Adam Powell                        measureChildWithMargins(v, 0, 0);
166bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        final int bottom = getDecoratedTop(topView);
167bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        final int top = bottom - getDecoratedMeasuredHeight(v);
168bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        layoutDecorated(v, left, top, right, bottom);
169f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    } else {
170f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        break;
171f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    }
172f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                }
173f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            } else if (dy > 0) {
17490e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell                final int parentHeight = getHeight();
175f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                while (scrolled < dy) {
17690e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell                    final View bottomView = getChildAt(getChildCount() - 1);
177bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    final int hangingBottom =
178bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                            Math.max(getDecoratedBottom(bottomView) - parentHeight, 0);
179f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    final int scrollBy = -Math.min(dy - scrolled, hangingBottom);
180f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    scrolled -= scrollBy;
18190e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell                    offsetChildrenVertical(scrollBy);
1828b38db9f287670f670f631a0ec4b95882cdd0705Yigit Boyar                    if (scrolled < dy && state.getItemCount() > mFirstPosition + getChildCount()) {
1832a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar                        View v = recycler.getViewForPosition(mFirstPosition + getChildCount());
184bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        final int top = getDecoratedBottom(getChildAt(getChildCount() - 1));
185f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        addView(v);
18663c8ab9435d707a23e2045af3be410ea7deed895Adam Powell                        measureChildWithMargins(v, 0, 0);
187bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        final int bottom = top + getDecoratedMeasuredHeight(v);
188bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        layoutDecorated(v, left, top, right, bottom);
189f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    } else {
190f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        break;
191f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    }
192f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                }
193f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
19451edefe34ae8f6a1a1d08f9596360286a0f2d238Adam Powell            recycleViewsOutOfBounds(recycler);
195f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            return scrolled;
196f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        }
197f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
198f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        @Override
199f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        public View onFocusSearchFailed(View focused, int direction,
2002a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar                RecyclerView.Recycler recycler, RecyclerView.State state) {
20190e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int oldCount = getChildCount();
202f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
203f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            if (oldCount == 0) {
204f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                return null;
205f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
206f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
20790e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int left = getPaddingLeft();
20890e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int right = getWidth() - getPaddingRight();
209f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
210f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            View toFocus = null;
211f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            int newViewsHeight = 0;
212f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            if (direction == View.FOCUS_UP || direction == View.FOCUS_BACKWARD) {
213f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                while (mFirstPosition > 0 && newViewsHeight < mScrollDistance) {
214f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    mFirstPosition--;
2152a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar                    View v = recycler.getViewForPosition(mFirstPosition);
216bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    final int bottom = getDecoratedTop(getChildAt(0));
217f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    addView(v, 0);
21863c8ab9435d707a23e2045af3be410ea7deed895Adam Powell                    measureChildWithMargins(v, 0, 0);
219bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    final int top = bottom - getDecoratedMeasuredHeight(v);
220bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    layoutDecorated(v, left, top, right, bottom);
221f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    if (v.isFocusable()) {
222f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        toFocus = v;
223f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        break;
224f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    }
225f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                }
226f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
227f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            if (direction == View.FOCUS_DOWN || direction == View.FOCUS_FORWARD) {
2288b38db9f287670f670f631a0ec4b95882cdd0705Yigit Boyar                while (mFirstPosition + getChildCount() < state.getItemCount() &&
229f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        newViewsHeight < mScrollDistance) {
2302a1ade8a82653e53f3d5b16c7e9d0ed9cb734101Yigit Boyar                    View v = recycler.getViewForPosition(mFirstPosition + getChildCount());
231bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    final int top = getDecoratedBottom(getChildAt(getChildCount() - 1));
232f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    addView(v);
23363c8ab9435d707a23e2045af3be410ea7deed895Adam Powell                    measureChildWithMargins(v, 0, 0);
234bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    final int bottom = top + getDecoratedMeasuredHeight(v);
235bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                    layoutDecorated(v, left, top, right, bottom);
236f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    if (v.isFocusable()) {
237f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        toFocus = v;
238f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        break;
239f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    }
240f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                }
241f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
242f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
243f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            return toFocus;
244f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        }
245f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell
24651edefe34ae8f6a1a1d08f9596360286a0f2d238Adam Powell        public void recycleViewsOutOfBounds(RecyclerView.Recycler recycler) {
24790e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int childCount = getChildCount();
24890e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int parentWidth = getWidth();
24990e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            final int parentHeight = getHeight();
250f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            boolean foundFirst = false;
251f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            int first = 0;
252f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            int last = 0;
253f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            for (int i = 0; i < childCount; i++) {
25490e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell                final View v = getChildAt(i);
255bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                if (v.hasFocus() || (getDecoratedRight(v) >= 0 &&
256bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        getDecoratedLeft(v) <= parentWidth &&
257bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        getDecoratedBottom(v) >= 0 &&
258bfda82df45c6f37f5773917d6f7c918fa3530d49Adam Powell                        getDecoratedTop(v) <= parentHeight)) {
259f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    if (!foundFirst) {
260f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        first = i;
261f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                        foundFirst = true;
262f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    }
263f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                    last = i;
264f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                }
265f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
266f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            for (int i = childCount - 1; i > last; i--) {
26751edefe34ae8f6a1a1d08f9596360286a0f2d238Adam Powell                removeAndRecycleViewAt(i, recycler);
268f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
26990e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            for (int i = first - 1; i >= 0; i--) {
27051edefe34ae8f6a1a1d08f9596360286a0f2d238Adam Powell                removeAndRecycleViewAt(i, recycler);
271f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
27290e0922d7d57ad748b919dfe21c63f03987227e7Adam Powell            if (getChildCount() == 0) {
273f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                mFirstPosition = 0;
274f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            } else {
275f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell                mFirstPosition += first;
276f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell            }
277f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell        }
278f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell    }
279f6c36bb9b61083b25397a6cff82ddbb102cacfbdAdam Powell}
280