1e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing/*
2e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing * Copyright 2017 The Android Open Source Project
3e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing *
4e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing * Licensed under the Apache License, Version 2.0 (the "License");
5e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing * you may not use this file except in compliance with the License.
6e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing * You may obtain a copy of the License at
7e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing *
8e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing *      http://www.apache.org/licenses/LICENSE-2.0
9e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing *
10e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing * Unless required by applicable law or agreed to in writing, software
11e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing * distributed under the License is distributed on an "AS IS" BASIS,
12e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing * See the License for the specific language governing permissions and
14e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing * limitations under the License.
15e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing */
16e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing
17e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxingpackage androidx.car.widget;
18e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing
193737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxingimport android.app.Activity;
203737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxingimport android.car.drivingstate.CarUxRestrictions;
21e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxingimport android.content.Context;
2215c4392796f5bb261c632412953db3fe753f9ddaAnthony Chenimport android.content.res.TypedArray;
233737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxingimport android.os.Bundle;
244e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxingimport android.util.SparseArray;
254e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxingimport android.util.SparseIntArray;
26e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxingimport android.view.LayoutInflater;
27e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxingimport android.view.View;
28e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxingimport android.view.ViewGroup;
29d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxingimport android.widget.FrameLayout;
304e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing
31b6ad1766427df3f2fad967dfd1a6e969a7bc216bYao, Yuxingimport androidx.annotation.ColorInt;
32073deef03c0761697ac418e78b49062baaa2cfe5Yao, Yuxingimport androidx.annotation.IntDef;
33073deef03c0761697ac418e78b49062baaa2cfe5Yao, Yuxingimport androidx.annotation.LayoutRes;
34073deef03c0761697ac418e78b49062baaa2cfe5Yao, Yuxingimport androidx.annotation.StyleRes;
35e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxingimport androidx.car.R;
36073deef03c0761697ac418e78b49062baaa2cfe5Yao, Yuxingimport androidx.car.utils.CarUxRestrictionsHelper;
37d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxingimport androidx.car.utils.ListItemBackgroundResolver;
38073deef03c0761697ac418e78b49062baaa2cfe5Yao, Yuxingimport androidx.cardview.widget.CardView;
39073deef03c0761697ac418e78b49062baaa2cfe5Yao, Yuxingimport androidx.recyclerview.widget.RecyclerView;
40e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing
4118dbdd24a8d64a2d21b1cdd98ddcb7938ff7be37Yao, Yuxingimport java.lang.annotation.Retention;
4218dbdd24a8d64a2d21b1cdd98ddcb7938ff7be37Yao, Yuxingimport java.lang.annotation.RetentionPolicy;
4318dbdd24a8d64a2d21b1cdd98ddcb7938ff7be37Yao, Yuxingimport java.util.function.Function;
4418dbdd24a8d64a2d21b1cdd98ddcb7938ff7be37Yao, Yuxing
45e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing/**
46e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing * Adapter for {@link PagedListView} to display {@link ListItem}.
47e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing *
489b0ebd7c98d4c0d73c101851014ecc5f4b70471aJovana * <ul>
499b0ebd7c98d4c0d73c101851014ecc5f4b70471aJovana *     <li> Implements {@link PagedListView.ItemCap} - defaults to unlimited item count.
509b0ebd7c98d4c0d73c101851014ecc5f4b70471aJovana *     <li> Implements {@link PagedListView.DividerVisibilityManager} - to control dividers after
519b0ebd7c98d4c0d73c101851014ecc5f4b70471aJovana *     individual {@link ListItem}.
529b0ebd7c98d4c0d73c101851014ecc5f4b70471aJovana * </ul>
539b0ebd7c98d4c0d73c101851014ecc5f4b70471aJovana *
543737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing * <p>To enable support for {@link CarUxRestrictions}, call {@link #start()} in your
553737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing * {@code Activity}'s {@link android.app.Activity#onCreate(Bundle)}, and {@link #stop()} in
563737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing * {@link Activity#onStop()}.
57e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing */
58e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxingpublic class ListItemAdapter extends
5920e9f85df9325d7dc79750be2527bd8dd1c38fcbYao, Yuxing        RecyclerView.Adapter<ListItem.ViewHolder> implements PagedListView.ItemCap,
609b0ebd7c98d4c0d73c101851014ecc5f4b70471aJovana        PagedListView.DividerVisibilityManager {
61d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing
62d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing    /**
63d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing     * Constant class for background style of items.
64d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing     */
65d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing    public static final class BackgroundStyle {
66d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing        private BackgroundStyle() {}
67d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing
68d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing        /**
69d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing         * Sets the background color of each item.
70534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing         * Background can be configured by {@link R.styleable#ListItem_listItemBackgroundColor}.
71d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing         */
72534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing        public static final int SOLID = 0;
73534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing        /**
74534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing         * Sets the background color of each item to none (transparent).
75534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing         */
76534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing        public static final int NONE = 1;
77d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing        /**
78d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing         * Sets each item in {@link CardView} with a rounded corner background and shadow.
79d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing         */
80534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing        public static final int CARD = 2;
81d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing        /**
82d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing         * Sets background of each item so the combined list looks like one elongated card, namely
83d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing         * top and bottom item will have rounded corner at only top/bottom side respectively. If
84d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing         * only one item exists, it will have both top and bottom rounded corner.
85d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing         */
86534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing        public static final int PANEL = 3;
87d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing    }
88d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing
8915c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen    @Retention(RetentionPolicy.SOURCE)
9015c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen    @IntDef({
91534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing        BackgroundStyle.SOLID,
9215c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen        BackgroundStyle.NONE,
9315c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen        BackgroundStyle.CARD,
94534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing        BackgroundStyle.PANEL
95534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing    })
9615c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen    private @interface ListBackgroundStyle {}
97e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing
984e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing    static final int LIST_ITEM_TYPE_TEXT = 1;
994e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing    static final int LIST_ITEM_TYPE_SEEKBAR = 2;
100b8f226941fcb44b40d4ebe860f86e43f0afed9fcYao, Yuxing    static final int LIST_ITEM_TYPE_SUBHEADER = 3;
1014e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing
1024e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing    private final SparseIntArray mViewHolderLayoutResIds = new SparseIntArray();
10320e9f85df9325d7dc79750be2527bd8dd1c38fcbYao, Yuxing    private final SparseArray<Function<View, ListItem.ViewHolder>> mViewHolderCreator =
1044e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing            new SparseArray<>();
1054e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing
10615c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen    @ListBackgroundStyle private int mBackgroundStyle;
107b6ad1766427df3f2fad967dfd1a6e969a7bc216bYao, Yuxing
108b6ad1766427df3f2fad967dfd1a6e969a7bc216bYao, Yuxing    @ColorInt private int mListItemBackgroundColor;
10915c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen    @StyleRes private int mListItemTitleTextAppearance;
11015c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen    @StyleRes private int mListItemBodyTextAppearance;
11115c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen
112073deef03c0761697ac418e78b49062baaa2cfe5Yao, Yuxing    private final CarUxRestrictionsHelper mUxRestrictionsHelper;
1133737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing    private CarUxRestrictions mCurrentUxRestrictions;
1143737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing
11515c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen    private Context mContext;
11615c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen    private final ListItemProvider mItemProvider;
11715c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen
11815c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen    private int mMaxItems = PagedListView.ItemCap.UNLIMITED;
11915c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen
120534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing    /**
121534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing     * Defaults {@link BackgroundStyle} to {@link BackgroundStyle#SOLID}.
122534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing     */
12315c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen    public ListItemAdapter(Context context, ListItemProvider itemProvider) {
124534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing        this(context, itemProvider, BackgroundStyle.SOLID);
12515c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen    }
12615c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen
12715c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen    public ListItemAdapter(Context context, ListItemProvider itemProvider,
12815c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen            @ListBackgroundStyle int backgroundStyle) {
12915c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen        mContext = context;
13015c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen        mItemProvider = itemProvider;
13115c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen        mBackgroundStyle = backgroundStyle;
13215c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen
13315c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen        registerListItemViewType(LIST_ITEM_TYPE_TEXT,
13415c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen                R.layout.car_list_item_text_content, TextListItem::createViewHolder);
13515c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen        registerListItemViewType(LIST_ITEM_TYPE_SEEKBAR,
13615c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen                R.layout.car_list_item_seekbar_content, SeekbarListItem::createViewHolder);
137b8f226941fcb44b40d4ebe860f86e43f0afed9fcYao, Yuxing        registerListItemViewType(LIST_ITEM_TYPE_SUBHEADER,
138b8f226941fcb44b40d4ebe860f86e43f0afed9fcYao, Yuxing                R.layout.car_list_item_subheader_content, SubheaderListItem::createViewHolder);
13915c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen
140073deef03c0761697ac418e78b49062baaa2cfe5Yao, Yuxing        mUxRestrictionsHelper =
141073deef03c0761697ac418e78b49062baaa2cfe5Yao, Yuxing                new CarUxRestrictionsHelper(context, carUxRestrictions -> {
142073deef03c0761697ac418e78b49062baaa2cfe5Yao, Yuxing                    mCurrentUxRestrictions = carUxRestrictions;
143073deef03c0761697ac418e78b49062baaa2cfe5Yao, Yuxing                    notifyDataSetChanged();
144073deef03c0761697ac418e78b49062baaa2cfe5Yao, Yuxing                });
14515c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen    }
1463737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing
1473737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing    /**
1483737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing     * Enables support for {@link CarUxRestrictions}.
1493737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing     *
1503737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing     * <p>This method can be called from {@code Activity}'s {@link Activity#onStart()}, or at the
1513737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing     * time of construction.
1523737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing     *
1533737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing     * <p>This method must be accompanied with a matching {@link #stop()} to avoid leak.
1543737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing     */
1553737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing    public void start() {
156073deef03c0761697ac418e78b49062baaa2cfe5Yao, Yuxing        mUxRestrictionsHelper.start();
1573737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing    }
1583737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing
1593737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing    /**
1603737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing     * Disables support for {@link CarUxRestrictions}, and frees up resources.
1613737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing     *
1623737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing     * <p>This method should be called from {@code Activity}'s {@link Activity#onStop()}, or at the
1633737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing     * time of this adapter being discarded.
1643737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing     */
1653737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing    public void stop() {
166073deef03c0761697ac418e78b49062baaa2cfe5Yao, Yuxing        mUxRestrictionsHelper.stop();
1673737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing    }
1683737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing
1694e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing    /**
170ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * Registers a function that returns {@link RecyclerView.ViewHolder}
1714e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing     * for its matching view type returned by {@link ListItem#getViewType()}.
1724e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing     *
1734e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing     * <p>The function will receive a view as {@link RecyclerView.ViewHolder#itemView}. This view
1744e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing     * uses background defined by {@link BackgroundStyle}.
1754e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing     *
1764e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing     * <p>Subclasses of {@link ListItem} in package androidx.car.widget are already registered.
1774e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing     *
1784e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing     * @param viewType use negative value for custom view type.
1794e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing     * @param function function to create ViewHolder for {@code viewType}.
1804e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing     */
1814e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing    public void registerListItemViewType(int viewType, @LayoutRes int layoutResId,
18220e9f85df9325d7dc79750be2527bd8dd1c38fcbYao, Yuxing            Function<View, ListItem.ViewHolder> function) {
1834e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing        if (mViewHolderLayoutResIds.get(viewType) != 0
1844e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing                || mViewHolderCreator.get(viewType) != null) {
1854e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing            throw new IllegalArgumentException("View type is already registered.");
1864e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing        }
1874e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing        mViewHolderCreator.put(viewType, function);
1884e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing        mViewHolderLayoutResIds.put(viewType, layoutResId);
1894e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing    }
1904e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing
19115c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen    @Override
19215c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
19315c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen        super.onAttachedToRecyclerView(recyclerView);
19415c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen        // When attached to the RecyclerView, update the Context so that this ListItemAdapter can
19515c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen        // retrieve theme information off that view.
19615c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen        mContext = recyclerView.getContext();
19715c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen
198b6ad1766427df3f2fad967dfd1a6e969a7bc216bYao, Yuxing        TypedArray a = mContext.getTheme().obtainStyledAttributes(R.styleable.ListItem);
199b6ad1766427df3f2fad967dfd1a6e969a7bc216bYao, Yuxing
200b6ad1766427df3f2fad967dfd1a6e969a7bc216bYao, Yuxing        mListItemBackgroundColor = a.getColor(R.styleable.ListItem_listItemBackgroundColor,
201b6ad1766427df3f2fad967dfd1a6e969a7bc216bYao, Yuxing                mContext.getColor(R.color.car_card));
20215c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen        mListItemTitleTextAppearance = a.getResourceId(
20315c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen                R.styleable.ListItem_listItemTitleTextAppearance,
20415c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen                R.style.TextAppearance_Car_Body1);
20515c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen        mListItemBodyTextAppearance = a.getResourceId(
20615c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen                R.styleable.ListItem_listItemBodyTextAppearance,
20715c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen                R.style.TextAppearance_Car_Body2);
20815c4392796f5bb261c632412953db3fe753f9ddaAnthony Chen        a.recycle();
209e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing    }
210e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing
211e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing    @Override
21220e9f85df9325d7dc79750be2527bd8dd1c38fcbYao, Yuxing    public ListItem.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
2134e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing        if (mViewHolderLayoutResIds.get(viewType) == 0
2144e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing                || mViewHolderCreator.get(viewType) == null) {
2154e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing            throw new IllegalArgumentException("Unregistered view type.");
2164e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing        }
2174e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing
218d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing        LayoutInflater inflater = LayoutInflater.from(mContext);
2194e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing        View itemView = inflater.inflate(mViewHolderLayoutResIds.get(viewType), parent, false);
220d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing
221d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing        ViewGroup container = createListItemContainer();
222d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing        container.addView(itemView);
2234e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing        return mViewHolderCreator.get(viewType).apply(container);
224e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing    }
225e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing
2264e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing    /**
2274e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing     * Creates a view with background set by {@link BackgroundStyle}.
2284e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing     */
229d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing    private ViewGroup createListItemContainer() {
230d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing        ViewGroup container;
231534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing        if (mBackgroundStyle == BackgroundStyle.CARD) {
232534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing            CardView card = new CardView(mContext);
233534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing            RecyclerView.LayoutParams cardLayoutParams = new RecyclerView.LayoutParams(
234534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing                    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
235534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing            cardLayoutParams.bottomMargin = mContext.getResources().getDimensionPixelSize(
23618dbdd24a8d64a2d21b1cdd98ddcb7938ff7be37Yao, Yuxing                    R.dimen.car_padding_1);
237534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing            card.setLayoutParams(cardLayoutParams);
238534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing            card.setRadius(mContext.getResources().getDimensionPixelSize(R.dimen.car_radius_1));
239534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing            card.setCardBackgroundColor(mListItemBackgroundColor);
240534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing
241534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing            container = card;
242534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing        } else {
243534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing            FrameLayout frameLayout = new FrameLayout(mContext);
244534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing            frameLayout.setLayoutParams(new RecyclerView.LayoutParams(
245534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing                    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
246534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing            // Skip setting background color for NONE.
247534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing            if (mBackgroundStyle != BackgroundStyle.NONE) {
248b6ad1766427df3f2fad967dfd1a6e969a7bc216bYao, Yuxing                frameLayout.setBackgroundColor(mListItemBackgroundColor);
249534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing            }
250d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing
251534cd0259e56f0b4b12ff9fa697b2f4d19e011e1Yao, Yuxing            container = frameLayout;
252e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing        }
253d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing        return container;
254e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing    }
255e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing
256e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing    @Override
2574e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing    public int getItemViewType(int position) {
2584e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing        return mItemProvider.get(position).getViewType();
2594e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing    }
2604e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing
2614e832ea4269fff1780e0726c16bc37584957ba10Yao, Yuxing    @Override
26220e9f85df9325d7dc79750be2527bd8dd1c38fcbYao, Yuxing    public void onBindViewHolder(ListItem.ViewHolder holder, int position) {
263d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing        if (mBackgroundStyle == BackgroundStyle.PANEL) {
264d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing            ListItemBackgroundResolver.setBackground(
265d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing                    holder.itemView, position, mItemProvider.size());
266d0e9e80e8d49a82d43cda017f10df9a609cd6102Yao, Yuxing        }
2673737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing
2683737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing        // Car may not be initialized thus current UXR will not be available.
2693737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing        if (mCurrentUxRestrictions != null) {
2703737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing            holder.complyWithUxRestrictions(mCurrentUxRestrictions);
2713737d1dff953969c27652b49b010ea9902b3da4fYao, Yuxing        }
2722524380fff7e003a2949947561f5ac2fa9591391Yao, Yuxing
2732524380fff7e003a2949947561f5ac2fa9591391Yao, Yuxing        ListItem item = mItemProvider.get(position);
2742524380fff7e003a2949947561f5ac2fa9591391Yao, Yuxing        item.setTitleTextAppearance(mListItemTitleTextAppearance);
2752524380fff7e003a2949947561f5ac2fa9591391Yao, Yuxing        item.setBodyTextAppearance(mListItemBodyTextAppearance);
2762524380fff7e003a2949947561f5ac2fa9591391Yao, Yuxing
2772524380fff7e003a2949947561f5ac2fa9591391Yao, Yuxing        item.bind(holder);
278e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing    }
279e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing
280e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing    @Override
281e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing    public int getItemCount() {
282e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing        return mMaxItems == PagedListView.ItemCap.UNLIMITED
283e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing                ? mItemProvider.size()
284e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing                : Math.min(mItemProvider.size(), mMaxItems);
285e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing    }
286e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing
287e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing    @Override
288e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing    public void setMaxItems(int maxItems) {
289e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing        mMaxItems = maxItems;
290e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing    }
291e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing
2929b0ebd7c98d4c0d73c101851014ecc5f4b70471aJovana    @Override
2939b0ebd7c98d4c0d73c101851014ecc5f4b70471aJovana    public boolean shouldHideDivider(int position) {
29424c300d7e994f91de777099dece727710a1ec018Anthony Chen        // By default we should show the divider i.e. return false.
2959b0ebd7c98d4c0d73c101851014ecc5f4b70471aJovana
29624c300d7e994f91de777099dece727710a1ec018Anthony Chen        // Check if position is within range, and then check the item flag.
29724c300d7e994f91de777099dece727710a1ec018Anthony Chen        return position >= 0 && position < getItemCount()
29824c300d7e994f91de777099dece727710a1ec018Anthony Chen                && mItemProvider.get(position).shouldHideDivider();
2999b0ebd7c98d4c0d73c101851014ecc5f4b70471aJovana    }
300e048d0d3137fbee6430d3481aaa7269d221a7d45Yao, Yuxing}
301