1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.car.ui.recyclerview;
18 
19 import static com.android.car.ui.core.CarUi.MIN_TARGET_API;
20 
21 import static java.lang.annotation.RetentionPolicy.SOURCE;
22 
23 import android.annotation.SuppressLint;
24 import android.annotation.TargetApi;
25 import android.content.Context;
26 import android.util.AttributeSet;
27 import android.view.View;
28 import android.view.View.OnLayoutChangeListener;
29 import android.view.View.OnTouchListener;
30 import android.view.ViewGroup;
31 import android.view.ViewParent;
32 import android.view.ViewTreeObserver;
33 
34 import androidx.annotation.IdRes;
35 import androidx.annotation.IntDef;
36 import androidx.annotation.NonNull;
37 import androidx.annotation.Nullable;
38 import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup;
39 import androidx.recyclerview.widget.LinearLayoutManager;
40 import androidx.recyclerview.widget.OrientationHelper;
41 import androidx.recyclerview.widget.RecyclerView;
42 import androidx.recyclerview.widget.RecyclerView.Adapter;
43 import androidx.recyclerview.widget.RecyclerView.ItemAnimator;
44 import androidx.recyclerview.widget.RecyclerView.ItemDecoration;
45 import androidx.recyclerview.widget.RecyclerView.LayoutManager;
46 import androidx.recyclerview.widget.RecyclerView.OnChildAttachStateChangeListener;
47 import androidx.recyclerview.widget.RecyclerView.OnFlingListener;
48 import androidx.recyclerview.widget.RecyclerView.OnScrollListener;
49 import androidx.recyclerview.widget.RecyclerView.ViewHolder;
50 
51 import com.android.car.ui.pluginsupport.PluginFactorySingleton;
52 
53 import java.lang.annotation.Retention;
54 
55 /**
56  * A class to access the {@link CarUiRecyclerView} methods. The appearance and layout is
57  * customizable by OEM.
58  * <p>
59  * This is the base class for CarUiRecyclerView implementation.
60  * <p>
61  * Rendered views will comply with
62  * <a href="https://source.android.com/devices/automotive/hmi/car_ui/appendix_b">customization guardrails</a>
63  */
64 @TargetApi(MIN_TARGET_API)
65 @SuppressLint("Instantiatable")
66 public interface CarUiRecyclerView {
67     int SIZE_SMALL = 0;
68     int SIZE_MEDIUM = 1;
69     int SIZE_LARGE = 2;
70 
71     /**
72      * Describes the expected relative size of the {@link CarUiRecyclerView}. The list may be
73      * rendered differently for each expected size.
74      */
75     @Retention(SOURCE)
76     @IntDef({SIZE_SMALL, SIZE_MEDIUM, SIZE_LARGE})
77     @interface Size {}
78 
79     /**
80      * The possible values for setScrollBarPosition. The default value is {@link
81      * CarUiRecyclerViewLayout#LINEAR}.
82      */
83     @IntDef({
84         CarUiRecyclerViewLayout.LINEAR,
85         CarUiRecyclerViewLayout.GRID,
86     })
87     @Retention(SOURCE)
88     @interface CarUiRecyclerViewLayout {
89         /**
90          * Arranges items either horizontally in a single row or vertically in a single column.
91          * This is the default value.
92          */
93         int LINEAR = 0;
94 
95         /**
96          * Arranges items in a Grid.
97          */
98         int GRID = 1;
99     }
100 
101     /**
102      * Interface for a {@link RecyclerView.Adapter} to cap the number of items.
103      *
104      * <p>NOTE: it is still up to the adapter to use maxItems in {@link
105      * RecyclerView.Adapter#getItemCount()}.
106      *
107      * <p>the recommended way would be with:
108      *
109      * <pre>{@code
110      * {@literal@}Override
111      * public int getItemCount() {
112      *   return Math.min(super.getItemCount(), mMaxItems);
113      * }
114      * }</pre>
115      */
116     interface ItemCap {
117         /**
118          * Sets the maximum number of items available in the adapter. A value less than '0' means
119          * the list should not be capped.
120          */
setMaxItems(int maxItems)121         void setMaxItems(int maxItems);
122         /**
123          * A value to pass to {@link #setMaxItems(int)} that indicates there should be no limit.
124          */
125         int UNLIMITED = -1;
126     }
127 
128     /**
129      * The RecyclerView is not currently scrolling.
130      *
131      * @see #getScrollState()
132      */
133     int SCROLL_STATE_IDLE = 0;
134 
135     /**
136      * The RecyclerView is currently being dragged by outside input such as user touch input.
137      *
138      * @see #getScrollState()
139      */
140     int SCROLL_STATE_DRAGGING = 1;
141 
142     /**
143      * The RecyclerView is currently animating to a final position while not under
144      * outside control.
145      *
146      * @see #getScrollState()
147      */
148     int SCROLL_STATE_SETTLING = 2;
149 
150     /**
151      * Equivalent of {@link RecyclerView.OnScrollListener}
152      */
153     interface OnScrollListener {
onScrolled(CarUiRecyclerView recyclerView, int dx, int dy)154         void onScrolled(CarUiRecyclerView recyclerView, int dx, int dy);
onScrollStateChanged(CarUiRecyclerView recyclerView, int newState)155         void onScrollStateChanged(CarUiRecyclerView recyclerView, int newState);
156     }
157 
158     /**
159      * Adapters that implement this interface will receive the calls
160      */
161     interface OnAttachListener {
onAttachedToCarUiRecyclerView(@onNull CarUiRecyclerView carUiRecyclerView)162         void onAttachedToCarUiRecyclerView(@NonNull CarUiRecyclerView carUiRecyclerView);
onDetachedFromCarUiRecyclerView(@onNull CarUiRecyclerView carUiRecyclerView)163         void onDetachedFromCarUiRecyclerView(@NonNull CarUiRecyclerView carUiRecyclerView);
164     }
165 
166     /**
167      * Use this method to create an instance of CarUiRecyclerView at runtime.
168      */
create(Context context)169     static CarUiRecyclerView create(Context context) {
170         return PluginFactorySingleton.get(context)
171             .createRecyclerView(context, null);
172     }
173 
174     /**
175      * Use this method to create an instance of CarUiRecyclerView at runtime.
176      */
create(Context context, AttributeSet attributeSet)177     static CarUiRecyclerView create(Context context, AttributeSet attributeSet) {
178         return PluginFactorySingleton.get(context)
179             .createRecyclerView(context, attributeSet);
180     }
181 
182     /**
183      * see {@link RecyclerView#addItemDecoration(ItemDecoration)}
184      * @deprecated this will fail when there is a oem implementation
185      */
186     @Deprecated
addItemDecoration(@onNull ItemDecoration decor)187     void addItemDecoration(@NonNull ItemDecoration decor);
188 
189     /**
190      * see {@link RecyclerView#addItemDecoration(ItemDecoration, int)}
191      * @deprecated this will fail when there is a oem implementation
192      */
193     @Deprecated
addItemDecoration(@onNull ItemDecoration decor, int index)194     void addItemDecoration(@NonNull ItemDecoration decor, int index);
195 
196     /** see {@link RecyclerView#addOnChildAttachStateChangeListener} */
addOnChildAttachStateChangeListener(OnChildAttachStateChangeListener listener)197     void addOnChildAttachStateChangeListener(OnChildAttachStateChangeListener listener);
198 
199     /** see {@link View#addOnLayoutChangeListener(OnLayoutChangeListener)} */
addOnLayoutChangeListener(OnLayoutChangeListener listener)200     void addOnLayoutChangeListener(OnLayoutChangeListener listener);
201 
202     /** see {@link RecyclerView#addOnScrollListener(RecyclerView.OnScrollListener)} */
addOnScrollListener(OnScrollListener scrollListener)203     void addOnScrollListener(OnScrollListener scrollListener);
204 
205     /** {@link RecyclerView#clearOnChildAttachStateChangeListeners()} */
clearOnChildAttachStateChangeListeners()206     void clearOnChildAttachStateChangeListeners();
207 
208     /** {@link RecyclerView#clearOnScrollListeners()} */
clearOnScrollListeners()209     void clearOnScrollListeners();
210 
211     /** see {@link LinearLayoutManager#findFirstCompletelyVisibleItemPosition()} */
findFirstCompletelyVisibleItemPosition()212     int findFirstCompletelyVisibleItemPosition();
213 
214     /** see {@link LinearLayoutManager#findFirstVisibleItemPosition()} */
findFirstVisibleItemPosition()215     int findFirstVisibleItemPosition();
216 
217     /** see {@link LinearLayoutManager#findLastCompletelyVisibleItemPosition()} */
findLastCompletelyVisibleItemPosition()218     int findLastCompletelyVisibleItemPosition();
219 
220     /** see {@link LinearLayoutManager#findLastVisibleItemPosition()} */
findLastVisibleItemPosition()221     int findLastVisibleItemPosition();
222 
223     /**
224      * see {@link View#findViewById(int)}
225      * @deprecated this will fail when there is a oem implementation
226      */
227     @Deprecated
findViewById(int id)228     <T extends View> T findViewById(int id);
229 
230     /** see {@link RecyclerView#findViewHolderForAdapterPosition(int)} */
findViewHolderForAdapterPosition(int position)231     ViewHolder findViewHolderForAdapterPosition(int position);
232 
233     /** see {@link RecyclerView#findViewHolderForAdapterPosition(int)} */
findViewHolderForLayoutPosition(int position)234     ViewHolder findViewHolderForLayoutPosition(int position);
235 
236     /** see {@link ViewGroup#focusableViewAvailable(View)} */
focusableViewAvailable(View v)237     void focusableViewAvailable(View v);
238 
239     /** see {@link RecyclerView#getAdapter()} */
getAdapter()240     Adapter<?> getAdapter();
241 
242     /** see {@link View#getAlpha()} */
getAlpha()243     float getAlpha();
244 
245     /**
246      * see {@link ViewGroup#getChildAt(int)}
247      * @deprecated this will fail when there is a oem implementation
248      */
249     @Deprecated
250     @Nullable
getChildAt(int index)251     View getChildAt(int index);
252 
253     /**
254      * see {@link ViewGroup#getChildCount()}
255      * @deprecated this will fail when there is a oem implementation
256      */
257     @Deprecated
getChildCount()258     int getChildCount();
259 
260     /**
261      * see {@link RecyclerView#getChildLayoutPosition(View)}
262      */
getChildLayoutPosition(View child)263     int getChildLayoutPosition(View child);
264 
265     /** see {@link View#getContentDescription()} */
getContentDescription()266     CharSequence getContentDescription();
267 
268     /** see {@link View#getContext()} */
getContext()269     Context getContext();
270 
271     /** see {@link OrientationHelper#getEndAfterPadding()} */
getEndAfterPadding()272     int getEndAfterPadding();
273 
274     /** see {@link View#getHeight()} */
getHeight()275     int getHeight();
276 
277     /**
278      * see {@link RecyclerView#getItemDecorationAt(int)}
279      * @deprecated this will fail when there is a oem implementation
280      */
281     @Deprecated
282     @Nullable
getItemDecorationAt(int index)283     ItemDecoration getItemDecorationAt(int index);
284 
285     /**
286      * see {@link RecyclerView#getItemDecorationCount()}
287      * @deprecated this will fail when there is a oem implementation
288      */
289     @Deprecated
getItemDecorationCount()290     int getItemDecorationCount();
291 
292     /**
293      * see {@link RecyclerView#getLayoutManager()}
294      * @deprecated this will fail when there is a oem implementation
295      */
296     @Deprecated
297     @Nullable
getLayoutManager()298     LayoutManager getLayoutManager();
299 
300     /** Use this instead of {@link #getLayoutManager} */
301     @Nullable
getLayoutStyle()302     CarUiLayoutStyle getLayoutStyle();
303 
304     /** {@link RecyclerView#hasFixedSize()} */
hasFixedSize()305     boolean hasFixedSize();
306 
307     /** see {@link View#getPaddingLeft()} */
getPaddingLeft()308     int getPaddingLeft();
309 
310     /** see {@link View#getPaddingRight()} */
getPaddingRight()311     int getPaddingRight();
312 
313     /** see {@link View#getPaddingBottom()} */
getPaddingBottom()314     int getPaddingBottom();
315 
316     /** see {@link View#getPaddingEnd()} */
getPaddingEnd()317     int getPaddingEnd();
318 
319     /** see {@link View#getPaddingStart()} */
getPaddingStart()320     int getPaddingStart();
321 
322     /** see {@link View#getPaddingTop()} */
getPaddingTop()323     int getPaddingTop();
324 
325     /**
326      * see {@link View#getParent()}
327      * @deprecated this will fail when there is a oem implementation
328      */
329     @Deprecated
getParent()330     ViewParent getParent();
331 
332     /**
333      * see {@link LayoutManager#getChildCount()}
334      * Prefer this method over {@link #getChildCount()}
335      */
getRecyclerViewChildCount()336     int getRecyclerViewChildCount();
337 
338     /**
339      * see {@link LayoutManager#getChildAt(int)}
340      * Prefer this method over {@link #getChildAt(int)}
341      */
342     @Nullable
getRecyclerViewChildAt(int index)343     View getRecyclerViewChildAt(int index);
344 
345     /** see {@link RecyclerView#getScrollState()} */
getScrollState()346     int getScrollState();
347 
348     /** see {@link OrientationHelper#getStartAfterPadding()} */
getStartAfterPadding()349     int getStartAfterPadding();
350 
351     /** see {@link View#getTag()} */
getTag()352     Object getTag();
353 
354     /** see {@link OrientationHelper#getTotalSpace()} */
getTotalSpace()355     int getTotalSpace();
356 
357     /**
358      * Returns a view that will be attached to the view hierarchy.
359      */
360     @NonNull
getView()361     View getView();
362 
363     /** see {@link View#getViewTreeObserver()} */
getViewTreeObserver()364     ViewTreeObserver getViewTreeObserver();
365 
366     /**
367      * see {@link RecyclerView#invalidateItemDecorations()}
368      * @deprecated this will fail value when there is a oem implementation
369      */
370     @Deprecated
invalidateItemDecorations()371     void invalidateItemDecorations();
372 
373     /** see {@link View#post(Runnable)} */
post(Runnable runnable)374     boolean post(Runnable runnable);
375 
376     /**
377      * see {@link RecyclerView#removeItemDecoration(ItemDecoration)}
378      * @deprecated this will fail value when there is a oem implementation
379      */
380     @Deprecated
removeItemDecoration(@onNull ItemDecoration decor)381     void removeItemDecoration(@NonNull ItemDecoration decor);
382 
383     /**
384      * see {@link RecyclerView#removeItemDecorationAt(int)}
385      * @deprecated this will fail value when there is a oem implementation
386      */
387     @Deprecated
removeItemDecorationAt(int index)388     void removeItemDecorationAt(int index);
389 
390     /** see {@link RecyclerView#removeOnChildAttachStateChangeListener} */
removeOnChildAttachStateChangeListener(OnChildAttachStateChangeListener listener)391     void removeOnChildAttachStateChangeListener(OnChildAttachStateChangeListener listener);
392 
393     /** see {@link View#removeOnLayoutChangeListener(OnLayoutChangeListener)} */
removeOnLayoutChangeListener(OnLayoutChangeListener listener)394     void removeOnLayoutChangeListener(OnLayoutChangeListener listener);
395 
396     /** see {@link View#requestLayout()} */
requestLayout()397     void requestLayout();
398 
399     /** see {@link RecyclerView#removeOnScrollListener(OnScrollListener)} */
removeOnScrollListener(OnScrollListener scrollListener)400     void removeOnScrollListener(OnScrollListener scrollListener);
401 
402     /** see {@link View#requireViewById(int)} */
requireViewById(int id)403     <T extends View> T requireViewById(int id);
404 
405     /** see {@link View#scrollBy(int, int)} */
scrollBy(int x, int y)406     void scrollBy(int x, int y);
407 
408     /** see {@link RecyclerView#scrollToPosition(int)} */
scrollToPosition(int position)409     void scrollToPosition(int position);
410 
411     /** see {@link RecyclerView#setAdapter(Adapter)} */
setAdapter(Adapter<?> adapter)412     void setAdapter(Adapter<?> adapter);
413 
414     /** see {@link View#setAlpha(float)} */
setAlpha(float alpha)415     void setAlpha(float alpha);
416 
417     /** see {@link RecyclerView#setClipToPadding(boolean)} */
setClipToPadding(boolean enabled)418     void setClipToPadding(boolean enabled);
419 
420     /** see {@link View#setContentDescription(CharSequence)} */
setContentDescription(CharSequence contentDescription)421     void setContentDescription(CharSequence contentDescription);
422 
423     /** see {@link RecyclerView#setHasFixedSize(boolean)} */
setHasFixedSize(boolean hasFixedSize)424     void setHasFixedSize(boolean hasFixedSize);
425 
426     /**
427      * see {@link View#setFadingEdgeLength(int)}
428      * @deprecated this will fail when there is a oem implementation
429      */
430     @Deprecated
setFadingEdgeLength(int length)431     void setFadingEdgeLength(int length);
432 
433     /** see {@link RecyclerView#setOnFlingListener(OnFlingListener)} */
setOnFlingListener(OnFlingListener listener)434     void setOnFlingListener(OnFlingListener listener);
435 
436     /** see {@link View#setId(int)}  */
setId(@dRes int id)437     void setId(@IdRes int id);
438 
439     /**
440      * see {@link RecyclerView#setItemAnimator(ItemAnimator)}
441      * @deprecated this will fail when there is a oem implementation
442      */
443     @Deprecated
setItemAnimator(ItemAnimator itemAnimator)444     void setItemAnimator(ItemAnimator itemAnimator);
445 
446     /**
447      * see {@link RecyclerView#setLayoutManager(LayoutManager)}
448      * @deprecated this will fail when there is a oem implementation
449      */
450     @Deprecated
setLayoutManager(@ullable LayoutManager layoutManager)451     default void setLayoutManager(@Nullable LayoutManager layoutManager) {}
452 
453     /** Use this instead of {@link #setLayoutManager} */
setLayoutStyle(@ullable CarUiLayoutStyle layoutStyle)454     void setLayoutStyle(@Nullable CarUiLayoutStyle layoutStyle);
455 
456     /** see {@link View#setOnTouchListener(OnTouchListener)} */
setOnTouchListener(OnTouchListener listener)457     void setOnTouchListener(OnTouchListener listener);
458 
459     /** see {@link View#setPadding(int, int, int, int)} */
setPadding(int left, int top, int right, int bottom)460     void setPadding(int left, int top, int right, int bottom);
461 
462     /** see {@link View#setPaddingRelative(int, int, int, int)} */
setPaddingRelative(int start, int top, int end, int bottom)463     void setPaddingRelative(int start, int top, int end, int bottom);
464 
465     /** Will get called when {@link SpanSizeLookup} changes at runtime. */
setSpanSizeLookup(@onNull SpanSizeLookup spanSizeLookup)466     void setSpanSizeLookup(@NonNull SpanSizeLookup spanSizeLookup);
467 
468     /** see {@link View#setTag(Object)} */
setTag(Object tag)469     void setTag(Object tag);
470 
471     /**
472      * see {@link View#setVerticalFadingEdgeEnabled(boolean)}
473      * @deprecated this will fail when there is a oem implementation
474      */
475     @Deprecated
setVerticalFadingEdgeEnabled(boolean enabled)476     void setVerticalFadingEdgeEnabled(boolean enabled);
477 
478     /**
479      * see {@link View#setVerticalScrollBarEnabled(boolean)}
480      * @deprecated this will fail when there is a oem implementation
481      */
482     @Deprecated
setVerticalScrollBarEnabled(boolean enabled)483     void setVerticalScrollBarEnabled(boolean enabled);
484 
485     /**
486      * see {@link View#setVerticalScrollbarPosition(int)}
487      * @deprecated this will fail when there is a oem implementation
488      */
489     @Deprecated
setVerticalScrollbarPosition(int position)490     void setVerticalScrollbarPosition(int position);
491 
492     /** see {@link View#setVisibility(int)} */
setVisibility(int visible)493     void setVisibility(int visible);
494 
495     /** see {@link RecyclerView#smoothScrollBy(int, int)} */
smoothScrollBy(int dx, int dy)496     void smoothScrollBy(int dx, int dy);
497 
498     /** see {@link RecyclerView#smoothScrollToPosition(int) */
smoothScrollToPosition(int position)499     void smoothScrollToPosition(int position);
500 }
501