163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay/* 263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * Copyright 2017 The Android Open Source Project 363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * 463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * Licensed under the Apache License, Version 2.0 (the "License"); 563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * you may not use this file except in compliance with the License. 663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * You may obtain a copy of the License at 763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * 863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * http://www.apache.org/licenses/LICENSE-2.0 963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * 1063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * Unless required by applicable law or agreed to in writing, software 1163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * distributed under the License is distributed on an "AS IS" BASIS, 1263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * See the License for the specific language governing permissions and 1463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * limitations under the License. 1563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay */ 1663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 172a32c7e1264b14a20ed900abadea828b804a46ceAurimas Liutikaspackage androidx.recyclerview.selection; 1863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 19ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.core.util.Preconditions.checkArgument; 2063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 2163d2846409d84487d4856d3b8d18cc4684352e29Steve McKayimport android.graphics.Canvas; 2263d2846409d84487d4856d3b8d18cc4684352e29Steve McKayimport android.graphics.Point; 2363d2846409d84487d4856d3b8d18cc4684352e29Steve McKayimport android.graphics.Rect; 2463d2846409d84487d4856d3b8d18cc4684352e29Steve McKayimport android.graphics.drawable.Drawable; 2560dadaeed4f5cee272b575dfde6c02e3506a2fa0Aurimas Liutikasimport android.view.View; 2660dadaeed4f5cee272b575dfde6c02e3506a2fa0Aurimas Liutikas 27ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.DrawableRes; 28ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.NonNull; 2960dadaeed4f5cee272b575dfde6c02e3506a2fa0Aurimas Liutikasimport androidx.recyclerview.selection.SelectionTracker.SelectionPredicate; 30ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.recyclerview.widget.GridLayoutManager; 31ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.recyclerview.widget.RecyclerView; 32ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.recyclerview.widget.RecyclerView.ItemDecoration; 33ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.recyclerview.widget.RecyclerView.OnScrollListener; 3463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 3563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay/** 3663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * RecyclerView backed {@link BandSelectionHelper.BandHost}. 3763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay */ 3863d2846409d84487d4856d3b8d18cc4684352e29Steve McKayfinal class DefaultBandHost<K> extends GridModel.GridHost<K> { 3963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 4063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay private static final Rect NILL_RECT = new Rect(0, 0, 0, 0); 4163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 427fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay private final RecyclerView mRecyclerView; 4363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay private final Drawable mBand; 4463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay private final ItemKeyProvider<K> mKeyProvider; 4563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay private final SelectionPredicate<K> mSelectionPredicate; 4663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 4763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay DefaultBandHost( 487fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay @NonNull RecyclerView recyclerView, 4963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay @DrawableRes int bandOverlayId, 507fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay @NonNull ItemKeyProvider<K> keyProvider, 517fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay @NonNull SelectionPredicate<K> selectionPredicate) { 5263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 537fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay checkArgument(recyclerView != null); 5463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 557fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay mRecyclerView = recyclerView; 567fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay mBand = mRecyclerView.getContext().getResources().getDrawable(bandOverlayId); 5763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 5863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay checkArgument(mBand != null); 5963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay checkArgument(keyProvider != null); 6063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay checkArgument(selectionPredicate != null); 6163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 6263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay mKeyProvider = keyProvider; 6363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay mSelectionPredicate = selectionPredicate; 6463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 657fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay mRecyclerView.addItemDecoration( 6663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay new ItemDecoration() { 6763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay @Override 6863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay public void onDrawOver( 6963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay Canvas canvas, 7063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay RecyclerView unusedParent, 7163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay RecyclerView.State unusedState) { 7263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay DefaultBandHost.this.onDrawBand(canvas); 7363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay } 7463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay }); 7563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay } 7663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 7763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay @Override 7863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay GridModel<K> createGridModel() { 7963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay return new GridModel<>(this, mKeyProvider, mSelectionPredicate); 8063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay } 8163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 8263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay @Override 8363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay int getAdapterPositionAt(int index) { 847fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay return mRecyclerView.getChildAdapterPosition(mRecyclerView.getChildAt(index)); 8563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay } 8663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 8763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay @Override 887fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay void addOnScrollListener(@NonNull OnScrollListener listener) { 897fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay mRecyclerView.addOnScrollListener(listener); 9063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay } 9163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 9263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay @Override 937fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay void removeOnScrollListener(@NonNull OnScrollListener listener) { 947fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay mRecyclerView.removeOnScrollListener(listener); 9563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay } 9663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 9763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay @Override 987fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay Point createAbsolutePoint(@NonNull Point relativePoint) { 997fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay return new Point(relativePoint.x + mRecyclerView.computeHorizontalScrollOffset(), 1007fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay relativePoint.y + mRecyclerView.computeVerticalScrollOffset()); 10163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay } 10263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 10363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay @Override 10463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay Rect getAbsoluteRectForChildViewAt(int index) { 1057fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay final View child = mRecyclerView.getChildAt(index); 10663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay final Rect childRect = new Rect(); 10763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay child.getHitRect(childRect); 1087fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay childRect.left += mRecyclerView.computeHorizontalScrollOffset(); 1097fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay childRect.right += mRecyclerView.computeHorizontalScrollOffset(); 1107fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay childRect.top += mRecyclerView.computeVerticalScrollOffset(); 1117fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay childRect.bottom += mRecyclerView.computeVerticalScrollOffset(); 11263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay return childRect; 11363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay } 11463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 11563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay @Override 11663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay int getVisibleChildCount() { 1177fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay return mRecyclerView.getChildCount(); 11863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay } 11963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 12063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay @Override 12163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay int getColumnCount() { 1227fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager(); 12363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay if (layoutManager instanceof GridLayoutManager) { 12463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay return ((GridLayoutManager) layoutManager).getSpanCount(); 12563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay } 12663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 12763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay // Otherwise, it is a list with 1 column. 12863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay return 1; 12963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay } 13063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 13163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay @Override 1327fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay void showBand(@NonNull Rect rect) { 13363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay mBand.setBounds(rect); 1347fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay // TODO: mRecyclerView.invalidateItemDecorations() should work, but it isn't currently. 13563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay // NOTE: That without invalidating rv, the band only gets updated 13663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay // when the pointer moves off a the item view into "NO_POSITION" territory. 1377fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay mRecyclerView.invalidate(); 13863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay } 13963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 14063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay @Override 14163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay void hideBand() { 14263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay mBand.setBounds(NILL_RECT); 1437fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay // TODO: mRecyclerView.invalidateItemDecorations() should work, but it isn't currently. 1447fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay mRecyclerView.invalidate(); 14563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay } 14663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 1477fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay private void onDrawBand(@NonNull Canvas c) { 14863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay mBand.draw(c); 14963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay } 15063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 15163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay @Override 15263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay boolean hasView(int pos) { 1537fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay return mRecyclerView.findViewHolderForAdapterPosition(pos) != null; 15463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay } 15563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay} 156