ListRowPresenter.java revision 3173fdc69a928880a271036570c235f874b86f65
147520b68e50572a9775a662410c5aff8300c8784Craig Stout/*
247520b68e50572a9775a662410c5aff8300c8784Craig Stout * Copyright (C) 2014 The Android Open Source Project
347520b68e50572a9775a662410c5aff8300c8784Craig Stout *
447520b68e50572a9775a662410c5aff8300c8784Craig Stout * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
547520b68e50572a9775a662410c5aff8300c8784Craig Stout * in compliance with the License. You may obtain a copy of the License at
647520b68e50572a9775a662410c5aff8300c8784Craig Stout *
747520b68e50572a9775a662410c5aff8300c8784Craig Stout * http://www.apache.org/licenses/LICENSE-2.0
847520b68e50572a9775a662410c5aff8300c8784Craig Stout *
947520b68e50572a9775a662410c5aff8300c8784Craig Stout * Unless required by applicable law or agreed to in writing, software distributed under the License
1047520b68e50572a9775a662410c5aff8300c8784Craig Stout * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
1147520b68e50572a9775a662410c5aff8300c8784Craig Stout * or implied. See the License for the specific language governing permissions and limitations under
1247520b68e50572a9775a662410c5aff8300c8784Craig Stout * the License.
1347520b68e50572a9775a662410c5aff8300c8784Craig Stout */
1447520b68e50572a9775a662410c5aff8300c8784Craig Stoutpackage android.support.v17.leanback.widget;
1547520b68e50572a9775a662410c5aff8300c8784Craig Stout
16892181367d658f347d00ea5e091aa31f086b2a20Dake Guimport android.content.Context;
179240e796bc63422c28f2707840bd99c48573279bDake Guimport android.content.res.TypedArray;
18892181367d658f347d00ea5e091aa31f086b2a20Dake Guimport android.support.v17.leanback.R;
19cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Guimport android.support.v17.leanback.graphics.ColorOverlayDimmer;
204cd4cce277571385f4d1a56d5348578c38368cbeCraig Stoutimport android.util.Log;
2147520b68e50572a9775a662410c5aff8300c8784Craig Stoutimport android.view.View;
2247520b68e50572a9775a662410c5aff8300c8784Craig Stoutimport android.view.ViewGroup;
23892181367d658f347d00ea5e091aa31f086b2a20Dake Guimport android.view.ViewGroup.LayoutParams;
2447520b68e50572a9775a662410c5aff8300c8784Craig Stout
25bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stoutimport java.util.HashMap;
26bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout
2747520b68e50572a9775a662410c5aff8300c8784Craig Stout/**
287aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * ListRowPresenter renders {@link ListRow} using a
29cb13a318e577e14461eb008071dddf762847de42Dake Gu * {@link HorizontalGridView} hosted in a {@link ListRowView}.
307aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu *
317aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * <h3>Hover card</h3>
3247520b68e50572a9775a662410c5aff8300c8784Craig Stout * Optionally, {@link #setHoverCardPresenterSelector(PresenterSelector)} can be used to
3347520b68e50572a9775a662410c5aff8300c8784Craig Stout * display a view for the currently focused list item below the rendered
3447520b68e50572a9775a662410c5aff8300c8784Craig Stout * list. This view is known as a hover card.
357aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu *
367aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * <h3>Selection animation</h3>
377aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * ListRowPresenter disables {@link RowPresenter}'s default dimming effect and draw
387aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * a dim overlay on top of each individual child items.  Subclass may override and disable
397aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * {@link #isUsingDefaultListSelectEffect()} and write its own dim effect in
407aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * {@link #onSelectLevelChanged(RowPresenter.ViewHolder)}.
41dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu *
42dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu * <h3>Shadow</h3>
43dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu * ListRowPresenter applies a default shadow to child of each view.  Call
44dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu * {@link #setShadowEnabled(boolean)} to disable shadow.  Subclass may override and return
45dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu * false in {@link #isUsingDefaultShadow()} and replace with its own shadow implementation.
4647520b68e50572a9775a662410c5aff8300c8784Craig Stout */
4747520b68e50572a9775a662410c5aff8300c8784Craig Stoutpublic class ListRowPresenter extends RowPresenter {
4847520b68e50572a9775a662410c5aff8300c8784Craig Stout
4947520b68e50572a9775a662410c5aff8300c8784Craig Stout    private static final String TAG = "ListRowPresenter";
5047520b68e50572a9775a662410c5aff8300c8784Craig Stout    private static final boolean DEBUG = false;
5147520b68e50572a9775a662410c5aff8300c8784Craig Stout
52bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout    private static final int DEFAULT_RECYCLED_POOL_SIZE = 24;
53bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout
5447520b68e50572a9775a662410c5aff8300c8784Craig Stout    public static class ViewHolder extends RowPresenter.ViewHolder {
5547520b68e50572a9775a662410c5aff8300c8784Craig Stout        final ListRowPresenter mListRowPresenter;
5647520b68e50572a9775a662410c5aff8300c8784Craig Stout        final HorizontalGridView mGridView;
5771fddded48048acfa744ac352166770c91a1c2b1Dake Gu        ItemBridgeAdapter mItemBridgeAdapter;
5847520b68e50572a9775a662410c5aff8300c8784Craig Stout        final HorizontalHoverCardSwitcher mHoverCardViewSwitcher = new HorizontalHoverCardSwitcher();
59e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu        final int mPaddingTop;
60e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu        final int mPaddingBottom;
61e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu        final int mPaddingLeft;
62e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu        final int mPaddingRight;
6347520b68e50572a9775a662410c5aff8300c8784Craig Stout
6447520b68e50572a9775a662410c5aff8300c8784Craig Stout        public ViewHolder(View rootView, HorizontalGridView gridView, ListRowPresenter p) {
6547520b68e50572a9775a662410c5aff8300c8784Craig Stout            super(rootView);
6647520b68e50572a9775a662410c5aff8300c8784Craig Stout            mGridView = gridView;
6747520b68e50572a9775a662410c5aff8300c8784Craig Stout            mListRowPresenter = p;
68e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu            mPaddingTop = mGridView.getPaddingTop();
69e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu            mPaddingBottom = mGridView.getPaddingBottom();
70e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu            mPaddingLeft = mGridView.getPaddingLeft();
71e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu            mPaddingRight = mGridView.getPaddingRight();
7247520b68e50572a9775a662410c5aff8300c8784Craig Stout        }
7347520b68e50572a9775a662410c5aff8300c8784Craig Stout
7447520b68e50572a9775a662410c5aff8300c8784Craig Stout        public final ListRowPresenter getListRowPresenter() {
7547520b68e50572a9775a662410c5aff8300c8784Craig Stout            return mListRowPresenter;
7647520b68e50572a9775a662410c5aff8300c8784Craig Stout        }
7747520b68e50572a9775a662410c5aff8300c8784Craig Stout
7847520b68e50572a9775a662410c5aff8300c8784Craig Stout        public final HorizontalGridView getGridView() {
7947520b68e50572a9775a662410c5aff8300c8784Craig Stout            return mGridView;
8047520b68e50572a9775a662410c5aff8300c8784Craig Stout        }
819de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout
829de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout        public final ItemBridgeAdapter getBridgeAdapter() {
839de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout            return mItemBridgeAdapter;
849de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout        }
8547520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
8647520b68e50572a9775a662410c5aff8300c8784Craig Stout
8771fddded48048acfa744ac352166770c91a1c2b1Dake Gu    class ListRowPresenterItemBridgeAdapter extends ItemBridgeAdapter {
8871fddded48048acfa744ac352166770c91a1c2b1Dake Gu        ListRowPresenter.ViewHolder mRowViewHolder;
8971fddded48048acfa744ac352166770c91a1c2b1Dake Gu
9071fddded48048acfa744ac352166770c91a1c2b1Dake Gu        ListRowPresenterItemBridgeAdapter(ListRowPresenter.ViewHolder rowViewHolder) {
9171fddded48048acfa744ac352166770c91a1c2b1Dake Gu            mRowViewHolder = rowViewHolder;
9271fddded48048acfa744ac352166770c91a1c2b1Dake Gu        }
9371fddded48048acfa744ac352166770c91a1c2b1Dake Gu
9471fddded48048acfa744ac352166770c91a1c2b1Dake Gu        @Override
9571fddded48048acfa744ac352166770c91a1c2b1Dake Gu        public void onBind(final ItemBridgeAdapter.ViewHolder viewHolder) {
9671fddded48048acfa744ac352166770c91a1c2b1Dake Gu            // Only when having an OnItemClickListner, we will attach the OnClickListener.
9771fddded48048acfa744ac352166770c91a1c2b1Dake Gu            if (getOnItemClickedListener() != null || getOnItemViewClickedListener() != null) {
9871fddded48048acfa744ac352166770c91a1c2b1Dake Gu                viewHolder.mHolder.view.setOnClickListener(new View.OnClickListener() {
9971fddded48048acfa744ac352166770c91a1c2b1Dake Gu                    @Override
10071fddded48048acfa744ac352166770c91a1c2b1Dake Gu                    public void onClick(View v) {
10171fddded48048acfa744ac352166770c91a1c2b1Dake Gu                        ItemBridgeAdapter.ViewHolder ibh = (ItemBridgeAdapter.ViewHolder)
10271fddded48048acfa744ac352166770c91a1c2b1Dake Gu                                mRowViewHolder.mGridView.getChildViewHolder(viewHolder.itemView);
10371fddded48048acfa744ac352166770c91a1c2b1Dake Gu                        if (getOnItemClickedListener() != null) {
10471fddded48048acfa744ac352166770c91a1c2b1Dake Gu                            getOnItemClickedListener().onItemClicked(ibh.mItem,
10571fddded48048acfa744ac352166770c91a1c2b1Dake Gu                                    (ListRow) mRowViewHolder.mRow);
10671fddded48048acfa744ac352166770c91a1c2b1Dake Gu                        }
10771fddded48048acfa744ac352166770c91a1c2b1Dake Gu                        if (getOnItemViewClickedListener() != null) {
10871fddded48048acfa744ac352166770c91a1c2b1Dake Gu                            getOnItemViewClickedListener().onItemClicked(viewHolder.mHolder,
10971fddded48048acfa744ac352166770c91a1c2b1Dake Gu                                    ibh.mItem, mRowViewHolder, (ListRow) mRowViewHolder.mRow);
11071fddded48048acfa744ac352166770c91a1c2b1Dake Gu                        }
11171fddded48048acfa744ac352166770c91a1c2b1Dake Gu                    }
11271fddded48048acfa744ac352166770c91a1c2b1Dake Gu                });
11371fddded48048acfa744ac352166770c91a1c2b1Dake Gu            }
11471fddded48048acfa744ac352166770c91a1c2b1Dake Gu        }
11571fddded48048acfa744ac352166770c91a1c2b1Dake Gu
11671fddded48048acfa744ac352166770c91a1c2b1Dake Gu        @Override
11771fddded48048acfa744ac352166770c91a1c2b1Dake Gu        public void onUnbind(ItemBridgeAdapter.ViewHolder viewHolder) {
11871fddded48048acfa744ac352166770c91a1c2b1Dake Gu            if (getOnItemClickedListener() != null || getOnItemViewClickedListener() != null) {
11971fddded48048acfa744ac352166770c91a1c2b1Dake Gu                viewHolder.mHolder.view.setOnClickListener(null);
12071fddded48048acfa744ac352166770c91a1c2b1Dake Gu            }
12171fddded48048acfa744ac352166770c91a1c2b1Dake Gu        }
12271fddded48048acfa744ac352166770c91a1c2b1Dake Gu
12371fddded48048acfa744ac352166770c91a1c2b1Dake Gu        @Override
12471fddded48048acfa744ac352166770c91a1c2b1Dake Gu        public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder viewHolder) {
12571fddded48048acfa744ac352166770c91a1c2b1Dake Gu            if (viewHolder.itemView instanceof ShadowOverlayContainer) {
12671fddded48048acfa744ac352166770c91a1c2b1Dake Gu                int dimmedColor = mRowViewHolder.mColorDimmer.getPaint().getColor();
12771fddded48048acfa744ac352166770c91a1c2b1Dake Gu                ((ShadowOverlayContainer) viewHolder.itemView).setOverlayColor(dimmedColor);
12871fddded48048acfa744ac352166770c91a1c2b1Dake Gu            }
12971fddded48048acfa744ac352166770c91a1c2b1Dake Gu            mRowViewHolder.syncActivatedStatus(viewHolder.itemView);
13071fddded48048acfa744ac352166770c91a1c2b1Dake Gu        }
13171fddded48048acfa744ac352166770c91a1c2b1Dake Gu
13271fddded48048acfa744ac352166770c91a1c2b1Dake Gu        @Override
13371fddded48048acfa744ac352166770c91a1c2b1Dake Gu        public void onAddPresenter(Presenter presenter, int type) {
13471fddded48048acfa744ac352166770c91a1c2b1Dake Gu            mRowViewHolder.getGridView().getRecycledViewPool().setMaxRecycledViews(
13571fddded48048acfa744ac352166770c91a1c2b1Dake Gu                    type, getRecycledPoolSize(presenter));
13671fddded48048acfa744ac352166770c91a1c2b1Dake Gu        }
13771fddded48048acfa744ac352166770c91a1c2b1Dake Gu    }
13871fddded48048acfa744ac352166770c91a1c2b1Dake Gu
139a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    private int mRowHeight;
140a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    private int mExpandedRowHeight;
14147520b68e50572a9775a662410c5aff8300c8784Craig Stout    private PresenterSelector mHoverCardPresenterSelector;
142b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    private int mZoomFactor;
143892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    private boolean mShadowEnabled = true;
1449240e796bc63422c28f2707840bd99c48573279bDake Gu    private int mBrowseRowsFadingEdgeLength = -1;
1454f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout    private boolean mRoundedCornersEnabled = true;
146bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout    private HashMap<Presenter, Integer> mRecycledPoolSize = new HashMap<Presenter, Integer>();
147b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout
1484cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    private static int sSelectedRowTopPadding;
1494cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    private static int sExpandedSelectedRowTopPadding;
1504cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    private static int sExpandedRowNoHovercardBottomPadding;
1514cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout
152b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    /**
153b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     * Constructs a ListRowPresenter with defaults.
154739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Uses {@link FocusHighlight#ZOOM_FACTOR_MEDIUM} for focus zooming.
155b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     */
156b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    public ListRowPresenter() {
157739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        this(FocusHighlight.ZOOM_FACTOR_MEDIUM);
158b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    }
159b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout
160b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    /**
161b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     * Constructs a ListRowPresenter with the given parameters.
162b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     *
163b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     * @param zoomFactor Controls the zoom factor used when an item view is focused. One of
164739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     *         {@link FocusHighlight#ZOOM_FACTOR_NONE},
165739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     *         {@link FocusHighlight#ZOOM_FACTOR_SMALL},
166575dc8a5a5c023aee0c0ec297a7d357685cf49e9Craig Stout     *         {@link FocusHighlight#ZOOM_FACTOR_XSMALL},
167739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     *         {@link FocusHighlight#ZOOM_FACTOR_MEDIUM},
168739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     *         {@link FocusHighlight#ZOOM_FACTOR_LARGE}
169b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     */
170b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    public ListRowPresenter(int zoomFactor) {
171575dc8a5a5c023aee0c0ec297a7d357685cf49e9Craig Stout        if (!FocusHighlightHelper.isValidZoomIndex(zoomFactor)) {
172575dc8a5a5c023aee0c0ec297a7d357685cf49e9Craig Stout            throw new IllegalArgumentException("Unhandled zoom factor");
173575dc8a5a5c023aee0c0ec297a7d357685cf49e9Craig Stout        }
174b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout        mZoomFactor = zoomFactor;
175b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    }
176b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout
177b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    /**
178f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * Sets the row height for rows created by this Presenter. Rows
179a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     * created before calling this method will not be updated.
180a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     *
181f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * @param rowHeight Row height in pixels, or WRAP_CONTENT, or 0
182f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * to use the default height.
183a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     */
184a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    public void setRowHeight(int rowHeight) {
185a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn        mRowHeight = rowHeight;
186a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    }
187a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn
188a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    /**
189f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * Returns the row height for list rows created by this Presenter.
190a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     */
191a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    public int getRowHeight() {
192a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn        return mRowHeight;
193a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    }
194a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn
195a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    /**
196f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * Sets the expanded row height for rows created by this Presenter.
197f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * If not set, expanded rows have the same height as unexpanded
198a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     * rows.
199a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     *
200f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * @param rowHeight The row height in to use when the row is expanded,
201f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     *        in pixels, or WRAP_CONTENT, or 0 to use the default.
202a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     */
203a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    public void setExpandedRowHeight(int rowHeight) {
204a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn        mExpandedRowHeight = rowHeight;
205a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    }
206a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn
207a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    /**
208f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * Returns the expanded row height for rows created by this Presenter.
209a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     */
210a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    public int getExpandedRowHeight() {
211f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout        return mExpandedRowHeight != 0 ? mExpandedRowHeight : mRowHeight;
212a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    }
213a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn
214a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    /**
215b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     * Returns the zoom factor used for focus highlighting.
216b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     */
217b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    public final int getZoomFactor() {
218b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout        return mZoomFactor;
219b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    }
22047520b68e50572a9775a662410c5aff8300c8784Craig Stout
221892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    private ItemBridgeAdapter.Wrapper mCardWrapper = new ItemBridgeAdapter.Wrapper() {
222892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        @Override
223892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        public View createWrapper(View root) {
224dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu            ShadowOverlayContainer wrapper = new ShadowOverlayContainer(root.getContext());
225892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            wrapper.setLayoutParams(
226892181367d658f347d00ea5e091aa31f086b2a20Dake Gu                    new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
2274f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout            wrapper.initialize(needsDefaultShadow(),
2284f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout                    needsDefaultListSelectEffect(),
2294f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout                    areChildRoundedCornersEnabled());
230892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            return wrapper;
231892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        }
232892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        @Override
233892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        public void wrap(View wrapper, View wrapped) {
234dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu            ((ShadowOverlayContainer) wrapper).wrap(wrapped);
235892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        }
236892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    };
237892181367d658f347d00ea5e091aa31f086b2a20Dake Gu
23847520b68e50572a9775a662410c5aff8300c8784Craig Stout    @Override
23947520b68e50572a9775a662410c5aff8300c8784Craig Stout    protected void initializeRowViewHolder(RowPresenter.ViewHolder holder) {
24047520b68e50572a9775a662410c5aff8300c8784Craig Stout        super.initializeRowViewHolder(holder);
24147520b68e50572a9775a662410c5aff8300c8784Craig Stout        final ViewHolder rowViewHolder = (ViewHolder) holder;
24271fddded48048acfa744ac352166770c91a1c2b1Dake Gu        rowViewHolder.mItemBridgeAdapter = new ListRowPresenterItemBridgeAdapter(rowViewHolder);
2434f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout        if (needsDefaultListSelectEffect() || needsDefaultShadow()
2444f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout                || areChildRoundedCornersEnabled()) {
245892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            rowViewHolder.mItemBridgeAdapter.setWrapper(mCardWrapper);
246892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        }
247cb13a318e577e14461eb008071dddf762847de42Dake Gu        if (needsDefaultListSelectEffect()) {
248dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu            ShadowOverlayContainer.prepareParentForShadow(rowViewHolder.mGridView);
249cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu        }
25046e7de54775fc37dc51041629c79249e6dae3242Dake Gu        FocusHighlightHelper.setupBrowseItemFocusHighlight(rowViewHolder.mItemBridgeAdapter,
25146e7de54775fc37dc51041629c79249e6dae3242Dake Gu                mZoomFactor, false);
2520fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu        rowViewHolder.mGridView.setFocusDrawingOrderEnabled(!isUsingZOrder());
25347520b68e50572a9775a662410c5aff8300c8784Craig Stout        rowViewHolder.mGridView.setOnChildSelectedListener(
25447520b68e50572a9775a662410c5aff8300c8784Craig Stout                new OnChildSelectedListener() {
25547520b68e50572a9775a662410c5aff8300c8784Craig Stout            @Override
25647520b68e50572a9775a662410c5aff8300c8784Craig Stout            public void onChildSelected(ViewGroup parent, View view, int position, long id) {
25747520b68e50572a9775a662410c5aff8300c8784Craig Stout                selectChildView(rowViewHolder, view);
25847520b68e50572a9775a662410c5aff8300c8784Craig Stout            }
25947520b68e50572a9775a662410c5aff8300c8784Craig Stout        });
26047520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
26147520b68e50572a9775a662410c5aff8300c8784Craig Stout
262cb13a318e577e14461eb008071dddf762847de42Dake Gu    final boolean needsDefaultListSelectEffect() {
263cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu        return isUsingDefaultListSelectEffect() && getSelectEffectEnabled();
264cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    }
265cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu
26647520b68e50572a9775a662410c5aff8300c8784Craig Stout    /**
267bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout     * Sets the recycled pool size for the given presenter.
268bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout     */
269bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout    public void setRecycledPoolSize(Presenter presenter, int size) {
270bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout        mRecycledPoolSize.put(presenter, size);
271bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout    }
272bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout
273bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout    /**
274bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout     * Returns the recycled pool size for the given presenter.
275bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout     */
276bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout    public int getRecycledPoolSize(Presenter presenter) {
277bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout        return mRecycledPoolSize.containsKey(presenter) ? mRecycledPoolSize.get(presenter) :
278bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout                DEFAULT_RECYCLED_POOL_SIZE;
279bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout    }
280bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout
281bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout    /**
28247520b68e50572a9775a662410c5aff8300c8784Craig Stout     * Set {@link PresenterSelector} used for showing a select object in a hover card.
28347520b68e50572a9775a662410c5aff8300c8784Craig Stout     */
28447520b68e50572a9775a662410c5aff8300c8784Craig Stout    public final void setHoverCardPresenterSelector(PresenterSelector selector) {
28547520b68e50572a9775a662410c5aff8300c8784Craig Stout        mHoverCardPresenterSelector = selector;
28647520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
28747520b68e50572a9775a662410c5aff8300c8784Craig Stout
28847520b68e50572a9775a662410c5aff8300c8784Craig Stout    /**
28947520b68e50572a9775a662410c5aff8300c8784Craig Stout     * Get {@link PresenterSelector} used for showing a select object in a hover card.
29047520b68e50572a9775a662410c5aff8300c8784Craig Stout     */
29147520b68e50572a9775a662410c5aff8300c8784Craig Stout    public final PresenterSelector getHoverCardPresenterSelector() {
29247520b68e50572a9775a662410c5aff8300c8784Craig Stout        return mHoverCardPresenterSelector;
29347520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
29447520b68e50572a9775a662410c5aff8300c8784Craig Stout
29547520b68e50572a9775a662410c5aff8300c8784Craig Stout    /*
29647520b68e50572a9775a662410c5aff8300c8784Craig Stout     * Perform operations when a child of horizontal grid view is selected.
29747520b68e50572a9775a662410c5aff8300c8784Craig Stout     */
29847520b68e50572a9775a662410c5aff8300c8784Craig Stout    private void selectChildView(ViewHolder rowViewHolder, View view) {
29947520b68e50572a9775a662410c5aff8300c8784Craig Stout        if (view != null) {
3003173fdc69a928880a271036570c235f874b86f65butterfield@google.com            if (rowViewHolder.mExpanded && rowViewHolder.mSelected) {
3013173fdc69a928880a271036570c235f874b86f65butterfield@google.com                ItemBridgeAdapter.ViewHolder ibh = (ItemBridgeAdapter.ViewHolder)
3023173fdc69a928880a271036570c235f874b86f65butterfield@google.com                        rowViewHolder.mGridView.getChildViewHolder(view);
3033173fdc69a928880a271036570c235f874b86f65butterfield@google.com
3043173fdc69a928880a271036570c235f874b86f65butterfield@google.com                if (mHoverCardPresenterSelector != null) {
3053173fdc69a928880a271036570c235f874b86f65butterfield@google.com                    rowViewHolder.mHoverCardViewSwitcher.select(rowViewHolder.mGridView, view,
3063173fdc69a928880a271036570c235f874b86f65butterfield@google.com                            ibh.mItem);
3073173fdc69a928880a271036570c235f874b86f65butterfield@google.com                }
3083173fdc69a928880a271036570c235f874b86f65butterfield@google.com                if (getOnItemViewSelectedListener() != null) {
3093173fdc69a928880a271036570c235f874b86f65butterfield@google.com                    getOnItemViewSelectedListener().onItemSelected(ibh.mHolder, ibh.mItem,
3103173fdc69a928880a271036570c235f874b86f65butterfield@google.com                            rowViewHolder, rowViewHolder.mRow);
3113173fdc69a928880a271036570c235f874b86f65butterfield@google.com                }
3123173fdc69a928880a271036570c235f874b86f65butterfield@google.com                if (getOnItemSelectedListener() != null) {
3133173fdc69a928880a271036570c235f874b86f65butterfield@google.com                    getOnItemSelectedListener().onItemSelected(ibh.mItem, rowViewHolder.mRow);
3143173fdc69a928880a271036570c235f874b86f65butterfield@google.com                }
3153173fdc69a928880a271036570c235f874b86f65butterfield@google.com            }
3163173fdc69a928880a271036570c235f874b86f65butterfield@google.com        } else {
31747520b68e50572a9775a662410c5aff8300c8784Craig Stout            if (mHoverCardPresenterSelector != null) {
31847520b68e50572a9775a662410c5aff8300c8784Craig Stout                rowViewHolder.mHoverCardViewSwitcher.unselect();
31947520b68e50572a9775a662410c5aff8300c8784Craig Stout            }
3209de363b8db05106b03d115c266859fe200d41db7Dake Gu            if (getOnItemViewSelectedListener() != null) {
3219de363b8db05106b03d115c266859fe200d41db7Dake Gu                getOnItemViewSelectedListener().onItemSelected(null, null,
3229de363b8db05106b03d115c266859fe200d41db7Dake Gu                        rowViewHolder, rowViewHolder.mRow);
3239de363b8db05106b03d115c266859fe200d41db7Dake Gu            }
32447520b68e50572a9775a662410c5aff8300c8784Craig Stout            if (getOnItemSelectedListener() != null) {
32547520b68e50572a9775a662410c5aff8300c8784Craig Stout                getOnItemSelectedListener().onItemSelected(null, rowViewHolder.mRow);
32647520b68e50572a9775a662410c5aff8300c8784Craig Stout            }
32747520b68e50572a9775a662410c5aff8300c8784Craig Stout        }
32847520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
32947520b68e50572a9775a662410c5aff8300c8784Craig Stout
3304cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    private static void initStatics(Context context) {
3314cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        if (sSelectedRowTopPadding == 0) {
3324cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            sSelectedRowTopPadding = context.getResources().getDimensionPixelSize(
3334cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout                    R.dimen.lb_browse_selected_row_top_padding);
3344cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            sExpandedSelectedRowTopPadding = context.getResources().getDimensionPixelSize(
3354cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout                    R.dimen.lb_browse_expanded_selected_row_top_padding);
3364cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            sExpandedRowNoHovercardBottomPadding = context.getResources().getDimensionPixelSize(
3374cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout                    R.dimen.lb_browse_expanded_row_no_hovercard_bottom_padding);
3384cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        }
3394cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    }
3404cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout
3414cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    private int getSpaceUnderBaseline(ListRowPresenter.ViewHolder vh) {
3424cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        RowHeaderPresenter.ViewHolder headerViewHolder = vh.getHeaderViewHolder();
3434cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        if (headerViewHolder != null) {
3444cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            if (getHeaderPresenter() != null) {
3454cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout                return getHeaderPresenter().getSpaceUnderBaseline(headerViewHolder);
3464cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            }
3474cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            return headerViewHolder.view.getPaddingBottom();
3484cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        }
3494cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        return 0;
3504cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    }
3514cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout
3524cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    private void setVerticalPadding(ListRowPresenter.ViewHolder vh) {
3534cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        int paddingTop, paddingBottom;
3543146269a82645438b55a41c679047e3be36e65dfCraig Stout        // Note: sufficient bottom padding needed for card shadows.
3554cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        if (vh.isExpanded()) {
3564cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            int headerSpaceUnderBaseline = getSpaceUnderBaseline(vh);
3574cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            if (DEBUG) Log.v(TAG, "headerSpaceUnderBaseline " + headerSpaceUnderBaseline);
3584cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            paddingTop = (vh.isSelected() ? sExpandedSelectedRowTopPadding : vh.mPaddingTop) -
3594cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout                    headerSpaceUnderBaseline;
3604cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            paddingBottom = mHoverCardPresenterSelector == null ?
3614cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout                    sExpandedRowNoHovercardBottomPadding : vh.mPaddingBottom;
3624cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        } else if (vh.isSelected()) {
3633146269a82645438b55a41c679047e3be36e65dfCraig Stout            paddingTop = sSelectedRowTopPadding - vh.mPaddingBottom;
3643146269a82645438b55a41c679047e3be36e65dfCraig Stout            paddingBottom = sSelectedRowTopPadding;
3654cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        } else {
3663146269a82645438b55a41c679047e3be36e65dfCraig Stout            paddingTop = 0;
3673146269a82645438b55a41c679047e3be36e65dfCraig Stout            paddingBottom = vh.mPaddingBottom;
3684cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        }
3694cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        vh.getGridView().setPadding(vh.mPaddingLeft, paddingTop, vh.mPaddingRight,
3704cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout                paddingBottom);
3714cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    }
3724cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout
37347520b68e50572a9775a662410c5aff8300c8784Craig Stout    @Override
37447520b68e50572a9775a662410c5aff8300c8784Craig Stout    protected RowPresenter.ViewHolder createRowViewHolder(ViewGroup parent) {
3754cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        initStatics(parent.getContext());
376cb13a318e577e14461eb008071dddf762847de42Dake Gu        ListRowView rowView = new ListRowView(parent.getContext());
3779240e796bc63422c28f2707840bd99c48573279bDake Gu        setupFadingEffect(rowView);
378f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout        if (mRowHeight != 0) {
379a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn            rowView.getGridView().setRowHeight(mRowHeight);
380a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn        }
38147520b68e50572a9775a662410c5aff8300c8784Craig Stout        return new ViewHolder(rowView, rowView.getGridView(), this);
38247520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
38347520b68e50572a9775a662410c5aff8300c8784Craig Stout
38447520b68e50572a9775a662410c5aff8300c8784Craig Stout    @Override
38547520b68e50572a9775a662410c5aff8300c8784Craig Stout    protected void onRowViewSelected(RowPresenter.ViewHolder holder, boolean selected) {
3862f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu        super.onRowViewSelected(holder, selected);
3874cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        ViewHolder vh = (ViewHolder) holder;
3884cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        setVerticalPadding(vh);
3894cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        updateFooterViewSwitcher(vh);
39047520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
39147520b68e50572a9775a662410c5aff8300c8784Craig Stout
39247520b68e50572a9775a662410c5aff8300c8784Craig Stout    /*
39347520b68e50572a9775a662410c5aff8300c8784Craig Stout     * Show or hide hover card when row selection or expanded state is changed.
39447520b68e50572a9775a662410c5aff8300c8784Craig Stout     */
39547520b68e50572a9775a662410c5aff8300c8784Craig Stout    private void updateFooterViewSwitcher(ViewHolder vh) {
39647520b68e50572a9775a662410c5aff8300c8784Craig Stout        if (vh.mExpanded && vh.mSelected) {
39747520b68e50572a9775a662410c5aff8300c8784Craig Stout            if (mHoverCardPresenterSelector != null) {
39847520b68e50572a9775a662410c5aff8300c8784Craig Stout                vh.mHoverCardViewSwitcher.init((ViewGroup) vh.view,
39947520b68e50572a9775a662410c5aff8300c8784Craig Stout                        mHoverCardPresenterSelector);
40047520b68e50572a9775a662410c5aff8300c8784Craig Stout            }
40102e411c2c69d20aab138f1a162a24ea650eff7a1Dake Gu            ItemBridgeAdapter.ViewHolder ibh = (ItemBridgeAdapter.ViewHolder)
40202e411c2c69d20aab138f1a162a24ea650eff7a1Dake Gu                    vh.mGridView.findViewHolderForPosition(
40302e411c2c69d20aab138f1a162a24ea650eff7a1Dake Gu                            vh.mGridView.getSelectedPosition());
40402e411c2c69d20aab138f1a162a24ea650eff7a1Dake Gu            selectChildView(vh, ibh == null ? null : ibh.itemView);
40547520b68e50572a9775a662410c5aff8300c8784Craig Stout        } else {
40647520b68e50572a9775a662410c5aff8300c8784Craig Stout            if (mHoverCardPresenterSelector != null) {
4072f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu                vh.mHoverCardViewSwitcher.unselect();
40847520b68e50572a9775a662410c5aff8300c8784Craig Stout            }
40947520b68e50572a9775a662410c5aff8300c8784Craig Stout        }
41047520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
41147520b68e50572a9775a662410c5aff8300c8784Craig Stout
4129240e796bc63422c28f2707840bd99c48573279bDake Gu    private void setupFadingEffect(ListRowView rowView) {
4139240e796bc63422c28f2707840bd99c48573279bDake Gu        // content is completely faded at 1/2 padding of left, fading length is 1/2 of padding.
4149240e796bc63422c28f2707840bd99c48573279bDake Gu        HorizontalGridView gridView = rowView.getGridView();
4159240e796bc63422c28f2707840bd99c48573279bDake Gu        if (mBrowseRowsFadingEdgeLength < 0) {
4169240e796bc63422c28f2707840bd99c48573279bDake Gu            TypedArray ta = gridView.getContext()
4179240e796bc63422c28f2707840bd99c48573279bDake Gu                    .obtainStyledAttributes(R.styleable.LeanbackTheme);
4189240e796bc63422c28f2707840bd99c48573279bDake Gu            mBrowseRowsFadingEdgeLength = (int) ta.getDimension(
4199240e796bc63422c28f2707840bd99c48573279bDake Gu                    R.styleable.LeanbackTheme_browseRowsFadingEdgeLength, 0);
4209240e796bc63422c28f2707840bd99c48573279bDake Gu            ta.recycle();
42147520b68e50572a9775a662410c5aff8300c8784Craig Stout        }
4229240e796bc63422c28f2707840bd99c48573279bDake Gu        gridView.setFadingLeftEdgeLength(mBrowseRowsFadingEdgeLength);
42347520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
42447520b68e50572a9775a662410c5aff8300c8784Craig Stout
42547520b68e50572a9775a662410c5aff8300c8784Craig Stout    @Override
42647520b68e50572a9775a662410c5aff8300c8784Craig Stout    protected void onRowViewExpanded(RowPresenter.ViewHolder holder, boolean expanded) {
42747520b68e50572a9775a662410c5aff8300c8784Craig Stout        super.onRowViewExpanded(holder, expanded);
42847520b68e50572a9775a662410c5aff8300c8784Craig Stout        ViewHolder vh = (ViewHolder) holder;
429a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn        if (getRowHeight() != getExpandedRowHeight()) {
430a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn            int newHeight = expanded ? getExpandedRowHeight() : getRowHeight();
431a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn            vh.getGridView().setRowHeight(newHeight);
432a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn        }
4334cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        setVerticalPadding(vh);
43447520b68e50572a9775a662410c5aff8300c8784Craig Stout        updateFooterViewSwitcher(vh);
43547520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
43647520b68e50572a9775a662410c5aff8300c8784Craig Stout
43747520b68e50572a9775a662410c5aff8300c8784Craig Stout    @Override
438cb13a318e577e14461eb008071dddf762847de42Dake Gu    protected void onBindRowViewHolder(RowPresenter.ViewHolder holder, Object item) {
439cb13a318e577e14461eb008071dddf762847de42Dake Gu        super.onBindRowViewHolder(holder, item);
440cb13a318e577e14461eb008071dddf762847de42Dake Gu        ViewHolder vh = (ViewHolder) holder;
44147520b68e50572a9775a662410c5aff8300c8784Craig Stout        ListRow rowItem = (ListRow) item;
44247520b68e50572a9775a662410c5aff8300c8784Craig Stout        vh.mItemBridgeAdapter.setAdapter(rowItem.getAdapter());
44347520b68e50572a9775a662410c5aff8300c8784Craig Stout        vh.mGridView.setAdapter(vh.mItemBridgeAdapter);
44447520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
44547520b68e50572a9775a662410c5aff8300c8784Craig Stout
44647520b68e50572a9775a662410c5aff8300c8784Craig Stout    @Override
447cb13a318e577e14461eb008071dddf762847de42Dake Gu    protected void onUnbindRowViewHolder(RowPresenter.ViewHolder holder) {
4485358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout        ViewHolder vh = (ViewHolder) holder;
4495358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout        vh.mGridView.setAdapter(null);
4505358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout        vh.mItemBridgeAdapter.clear();
451cb13a318e577e14461eb008071dddf762847de42Dake Gu        super.onUnbindRowViewHolder(holder);
45247520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
45347520b68e50572a9775a662410c5aff8300c8784Craig Stout
454cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    /**
455cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * ListRowPresenter overrides the default select effect of {@link RowPresenter}
456cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * and return false.
457cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     */
458cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    @Override
459cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    public final boolean isUsingDefaultSelectEffect() {
460cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu        return false;
461cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    }
462cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu
463cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    /**
464cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * Returns true so that default select effect is applied to each individual
465cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * child of {@link HorizontalGridView}.  Subclass may return false to disable
466cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * the default implementation.
467cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * @see #onSelectLevelChanged(RowPresenter.ViewHolder)
468cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     */
469cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    public boolean isUsingDefaultListSelectEffect() {
470cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu        return true;
471cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    }
472cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu
473cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    /**
474dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu     * Returns true if SDK >= 18, where default shadow
475892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * is applied to each individual child of {@link HorizontalGridView}.
476892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * Subclass may return false to disable.
477892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     */
478892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    public boolean isUsingDefaultShadow() {
479dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu        return ShadowOverlayContainer.supportsShadow();
480892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    }
481892181367d658f347d00ea5e091aa31f086b2a20Dake Gu
482892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    /**
4830fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu     * Returns true if SDK >= L, where Z shadow is enabled so that Z order is enabled
4840fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu     * on each child of horizontal list.   If subclass returns false in isUsingDefaultShadow()
4850fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu     * and does not use Z-shadow on SDK >= L, it should override isUsingZOrder() return false.
4860fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu     */
4870fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu    public boolean isUsingZOrder() {
4880fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu        return ShadowHelper.getInstance().usesZShadow();
4890fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu    }
4900fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu
4910fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu    /**
492892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * Enable or disable child shadow.
493892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * This is not only for enable/disable default shadow implementation but also subclass must
494892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * respect this flag.
495892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     */
496892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    public final void setShadowEnabled(boolean enabled) {
497892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        mShadowEnabled = enabled;
498892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    }
499892181367d658f347d00ea5e091aa31f086b2a20Dake Gu
500892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    /**
501892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * Returns true if child shadow is enabled.
502892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * This is not only for enable/disable default shadow implementation but also subclass must
503892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * respect this flag.
504892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     */
505892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    public final boolean getShadowEnabled() {
506892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        return mShadowEnabled;
507892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    }
508892181367d658f347d00ea5e091aa31f086b2a20Dake Gu
5094f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout    /**
5104f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout     * Enables or disabled rounded corners on children of this row.
5114f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout     * Supported on Android SDK >= L.
5124f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout     */
5134f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout    public final void enableChildRoundedCorners(boolean enable) {
5144f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout        mRoundedCornersEnabled = enable;
5154f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout    }
5164f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout
5174f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout    /**
5184f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout     * Returns true if rounded corners are enabled for children of this row.
5194f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout     */
5204f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout    public final boolean areChildRoundedCornersEnabled() {
5214f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout        return mRoundedCornersEnabled;
5224f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout    }
5234f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout
524892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    final boolean needsDefaultShadow() {
525892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        return isUsingDefaultShadow() && getShadowEnabled();
526892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    }
527892181367d658f347d00ea5e091aa31f086b2a20Dake Gu
528892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    @Override
529892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    public boolean canDrawOutOfBounds() {
530892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        return needsDefaultShadow();
531892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    }
532892181367d658f347d00ea5e091aa31f086b2a20Dake Gu
533892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    /**
534cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * Applies select level to header and draw a default color dim over each child
535cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * of {@link HorizontalGridView}.
536cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * <p>
537cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * Subclass may override this method.  A subclass
538cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * needs to call super.onSelectLevelChanged() for applying header select level
539cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * and optionally applying a default select level to each child view of
540cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * {@link HorizontalGridView} if {@link #isUsingDefaultListSelectEffect()}
541cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * is true.  Subclass may override {@link #isUsingDefaultListSelectEffect()} to return
542cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * false and deal with the individual item select level by itself.
543cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * </p>
544cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     */
545cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    @Override
546cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    protected void onSelectLevelChanged(RowPresenter.ViewHolder holder) {
547cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu        super.onSelectLevelChanged(holder);
548cb13a318e577e14461eb008071dddf762847de42Dake Gu        if (needsDefaultListSelectEffect()) {
549cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu            ViewHolder vh = (ViewHolder) holder;
550892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            int dimmedColor = vh.mColorDimmer.getPaint().getColor();
551892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            for (int i = 0, count = vh.mGridView.getChildCount(); i < count; i++) {
552dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu                ShadowOverlayContainer wrapper = (ShadowOverlayContainer) vh.mGridView.getChildAt(i);
553dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu                wrapper.setOverlayColor(dimmedColor);
554cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu            }
5559240e796bc63422c28f2707840bd99c48573279bDake Gu            if (vh.mGridView.getFadingLeftEdge()) {
5569240e796bc63422c28f2707840bd99c48573279bDake Gu                vh.mGridView.invalidate();
5579240e796bc63422c28f2707840bd99c48573279bDake Gu            }
558cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu        }
559cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    }
560cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu
561709bb7083a089e788d84ffa81f2c4f60a1bc8cf2Dake Gu    @Override
562709bb7083a089e788d84ffa81f2c4f60a1bc8cf2Dake Gu    public void freeze(RowPresenter.ViewHolder holder, boolean freeze) {
563709bb7083a089e788d84ffa81f2c4f60a1bc8cf2Dake Gu        ViewHolder vh = (ViewHolder) holder;
564709bb7083a089e788d84ffa81f2c4f60a1bc8cf2Dake Gu        vh.mGridView.setScrollEnabled(!freeze);
565709bb7083a089e788d84ffa81f2c4f60a1bc8cf2Dake Gu    }
566709bb7083a089e788d84ffa81f2c4f60a1bc8cf2Dake Gu
567c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    @Override
5683f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu    public void setEntranceTransitionState(RowPresenter.ViewHolder holder,
5693f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu            boolean afterEntrance) {
5703f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu        super.setEntranceTransitionState(holder, afterEntrance);
571c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu        ((ViewHolder) holder).mGridView.setChildrenVisibility(
5723f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu                afterEntrance? View.VISIBLE : View.INVISIBLE);
573c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu    }
57447520b68e50572a9775a662410c5aff8300c8784Craig Stout}
575