ListRowPresenter.java revision 4cd4cce277571385f4d1a56d5348578c38368cbe
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
1647520b68e50572a9775a662410c5aff8300c8784Craig Stoutimport java.util.ArrayList;
1747520b68e50572a9775a662410c5aff8300c8784Craig Stout
18892181367d658f347d00ea5e091aa31f086b2a20Dake Guimport android.content.Context;
199240e796bc63422c28f2707840bd99c48573279bDake Guimport android.content.res.TypedArray;
20cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Guimport android.graphics.Canvas;
21892181367d658f347d00ea5e091aa31f086b2a20Dake Guimport android.support.v17.leanback.R;
22cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Guimport android.support.v17.leanback.graphics.ColorOverlayDimmer;
2347520b68e50572a9775a662410c5aff8300c8784Craig Stoutimport android.support.v17.leanback.widget.Presenter.ViewHolder;
24cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Guimport android.support.v7.widget.RecyclerView;
25892181367d658f347d00ea5e091aa31f086b2a20Dake Guimport android.util.AttributeSet;
264cd4cce277571385f4d1a56d5348578c38368cbeCraig Stoutimport android.util.Log;
2747520b68e50572a9775a662410c5aff8300c8784Craig Stoutimport android.view.View;
2847520b68e50572a9775a662410c5aff8300c8784Craig Stoutimport android.view.ViewGroup;
29892181367d658f347d00ea5e091aa31f086b2a20Dake Guimport android.view.ViewGroup.LayoutParams;
30892181367d658f347d00ea5e091aa31f086b2a20Dake Guimport android.widget.FrameLayout;
3147520b68e50572a9775a662410c5aff8300c8784Craig Stout
3247520b68e50572a9775a662410c5aff8300c8784Craig Stout/**
337aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * ListRowPresenter renders {@link ListRow} using a
34cb13a318e577e14461eb008071dddf762847de42Dake Gu * {@link HorizontalGridView} hosted in a {@link ListRowView}.
357aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu *
367aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * <h3>Hover card</h3>
3747520b68e50572a9775a662410c5aff8300c8784Craig Stout * Optionally, {@link #setHoverCardPresenterSelector(PresenterSelector)} can be used to
3847520b68e50572a9775a662410c5aff8300c8784Craig Stout * display a view for the currently focused list item below the rendered
3947520b68e50572a9775a662410c5aff8300c8784Craig Stout * list. This view is known as a hover card.
407aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu *
417aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * <h3>Selection animation</h3>
427aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * ListRowPresenter disables {@link RowPresenter}'s default dimming effect and draw
437aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * a dim overlay on top of each individual child items.  Subclass may override and disable
447aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * {@link #isUsingDefaultListSelectEffect()} and write its own dim effect in
457aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * {@link #onSelectLevelChanged(RowPresenter.ViewHolder)}.
46dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu *
47dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu * <h3>Shadow</h3>
48dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu * ListRowPresenter applies a default shadow to child of each view.  Call
49dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu * {@link #setShadowEnabled(boolean)} to disable shadow.  Subclass may override and return
50dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu * false in {@link #isUsingDefaultShadow()} and replace with its own shadow implementation.
5147520b68e50572a9775a662410c5aff8300c8784Craig Stout */
5247520b68e50572a9775a662410c5aff8300c8784Craig Stoutpublic class ListRowPresenter extends RowPresenter {
5347520b68e50572a9775a662410c5aff8300c8784Craig Stout
5447520b68e50572a9775a662410c5aff8300c8784Craig Stout    private static final String TAG = "ListRowPresenter";
5547520b68e50572a9775a662410c5aff8300c8784Craig Stout    private static final boolean DEBUG = false;
5647520b68e50572a9775a662410c5aff8300c8784Craig Stout
5747520b68e50572a9775a662410c5aff8300c8784Craig Stout    public static class ViewHolder extends RowPresenter.ViewHolder {
5847520b68e50572a9775a662410c5aff8300c8784Craig Stout        final ListRowPresenter mListRowPresenter;
5947520b68e50572a9775a662410c5aff8300c8784Craig Stout        final HorizontalGridView mGridView;
6047520b68e50572a9775a662410c5aff8300c8784Craig Stout        final ItemBridgeAdapter mItemBridgeAdapter = new ItemBridgeAdapter();
6147520b68e50572a9775a662410c5aff8300c8784Craig Stout        final HorizontalHoverCardSwitcher mHoverCardViewSwitcher = new HorizontalHoverCardSwitcher();
62cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu        final ColorOverlayDimmer mColorDimmer;
63e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu        final int mPaddingTop;
64e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu        final int mPaddingBottom;
65e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu        final int mPaddingLeft;
66e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu        final int mPaddingRight;
6747520b68e50572a9775a662410c5aff8300c8784Craig Stout
6847520b68e50572a9775a662410c5aff8300c8784Craig Stout        public ViewHolder(View rootView, HorizontalGridView gridView, ListRowPresenter p) {
6947520b68e50572a9775a662410c5aff8300c8784Craig Stout            super(rootView);
7047520b68e50572a9775a662410c5aff8300c8784Craig Stout            mGridView = gridView;
7147520b68e50572a9775a662410c5aff8300c8784Craig Stout            mListRowPresenter = p;
72cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu            mColorDimmer = ColorOverlayDimmer.createDefault(rootView.getContext());
73e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu            mPaddingTop = mGridView.getPaddingTop();
74e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu            mPaddingBottom = mGridView.getPaddingBottom();
75e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu            mPaddingLeft = mGridView.getPaddingLeft();
76e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu            mPaddingRight = mGridView.getPaddingRight();
7747520b68e50572a9775a662410c5aff8300c8784Craig Stout        }
7847520b68e50572a9775a662410c5aff8300c8784Craig Stout
7947520b68e50572a9775a662410c5aff8300c8784Craig Stout        public final ListRowPresenter getListRowPresenter() {
8047520b68e50572a9775a662410c5aff8300c8784Craig Stout            return mListRowPresenter;
8147520b68e50572a9775a662410c5aff8300c8784Craig Stout        }
8247520b68e50572a9775a662410c5aff8300c8784Craig Stout
8347520b68e50572a9775a662410c5aff8300c8784Craig Stout        public final HorizontalGridView getGridView() {
8447520b68e50572a9775a662410c5aff8300c8784Craig Stout            return mGridView;
8547520b68e50572a9775a662410c5aff8300c8784Craig Stout        }
869de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout
879de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout        public final ItemBridgeAdapter getBridgeAdapter() {
889de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout            return mItemBridgeAdapter;
899de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout        }
9047520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
9147520b68e50572a9775a662410c5aff8300c8784Craig Stout
92a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    private int mRowHeight;
93a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    private int mExpandedRowHeight;
9447520b68e50572a9775a662410c5aff8300c8784Craig Stout    private PresenterSelector mHoverCardPresenterSelector;
95b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    private int mZoomFactor;
96892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    private boolean mShadowEnabled = true;
979240e796bc63422c28f2707840bd99c48573279bDake Gu    private int mBrowseRowsFadingEdgeLength = -1;
98b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout
994cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    private static int sSelectedRowTopPadding;
1004cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    private static int sExpandedSelectedRowTopPadding;
1014cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    private static int sExpandedRowNoHovercardBottomPadding;
1024cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout
103b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    /**
104b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     * Constructs a ListRowPresenter with defaults.
105739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Uses {@link FocusHighlight#ZOOM_FACTOR_MEDIUM} for focus zooming.
106b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     */
107b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    public ListRowPresenter() {
108739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        this(FocusHighlight.ZOOM_FACTOR_MEDIUM);
109b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    }
110b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout
111b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    /**
112b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     * Constructs a ListRowPresenter with the given parameters.
113b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     *
114b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     * @param zoomFactor Controls the zoom factor used when an item view is focused. One of
115739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     *         {@link FocusHighlight#ZOOM_FACTOR_NONE},
116739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     *         {@link FocusHighlight#ZOOM_FACTOR_SMALL},
117739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     *         {@link FocusHighlight#ZOOM_FACTOR_MEDIUM},
118739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     *         {@link FocusHighlight#ZOOM_FACTOR_LARGE}
119b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     */
120b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    public ListRowPresenter(int zoomFactor) {
121b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout        mZoomFactor = zoomFactor;
122b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    }
123b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout
124b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    /**
125f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * Sets the row height for rows created by this Presenter. Rows
126a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     * created before calling this method will not be updated.
127a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     *
128f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * @param rowHeight Row height in pixels, or WRAP_CONTENT, or 0
129f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * to use the default height.
130a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     */
131a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    public void setRowHeight(int rowHeight) {
132a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn        mRowHeight = rowHeight;
133a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    }
134a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn
135a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    /**
136f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * Returns the row height for list rows created by this Presenter.
137a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     */
138a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    public int getRowHeight() {
139a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn        return mRowHeight;
140a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    }
141a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn
142a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    /**
143f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * Sets the expanded row height for rows created by this Presenter.
144f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * If not set, expanded rows have the same height as unexpanded
145a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     * rows.
146a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     *
147f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * @param rowHeight The row height in to use when the row is expanded,
148f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     *        in pixels, or WRAP_CONTENT, or 0 to use the default.
149a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     */
150a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    public void setExpandedRowHeight(int rowHeight) {
151a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn        mExpandedRowHeight = rowHeight;
152a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    }
153a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn
154a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    /**
155f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * Returns the expanded row height for rows created by this Presenter.
156a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     */
157a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    public int getExpandedRowHeight() {
158f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout        return mExpandedRowHeight != 0 ? mExpandedRowHeight : mRowHeight;
159a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    }
160a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn
161a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    /**
162b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     * Returns the zoom factor used for focus highlighting.
163b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     */
164b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    public final int getZoomFactor() {
165b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout        return mZoomFactor;
166b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    }
16747520b68e50572a9775a662410c5aff8300c8784Craig Stout
168892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    private ItemBridgeAdapter.Wrapper mCardWrapper = new ItemBridgeAdapter.Wrapper() {
169892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        @Override
170892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        public View createWrapper(View root) {
171dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu            ShadowOverlayContainer wrapper = new ShadowOverlayContainer(root.getContext());
172892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            wrapper.setLayoutParams(
173892181367d658f347d00ea5e091aa31f086b2a20Dake Gu                    new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
174cb13a318e577e14461eb008071dddf762847de42Dake Gu            wrapper.initialize(needsDefaultShadow(), needsDefaultListSelectEffect());
175892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            return wrapper;
176892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        }
177892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        @Override
178892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        public void wrap(View wrapper, View wrapped) {
179dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu            ((ShadowOverlayContainer) wrapper).wrap(wrapped);
180892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        }
181892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    };
182892181367d658f347d00ea5e091aa31f086b2a20Dake Gu
18347520b68e50572a9775a662410c5aff8300c8784Craig Stout    @Override
18447520b68e50572a9775a662410c5aff8300c8784Craig Stout    protected void initializeRowViewHolder(RowPresenter.ViewHolder holder) {
18547520b68e50572a9775a662410c5aff8300c8784Craig Stout        super.initializeRowViewHolder(holder);
18647520b68e50572a9775a662410c5aff8300c8784Craig Stout        final ViewHolder rowViewHolder = (ViewHolder) holder;
187c4b1a043ab39a881b2a05d50e93c35e6f6ebfffbDake Gu        if (needsDefaultListSelectEffect() || needsDefaultShadow()) {
188892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            rowViewHolder.mItemBridgeAdapter.setWrapper(mCardWrapper);
189892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        }
190cb13a318e577e14461eb008071dddf762847de42Dake Gu        if (needsDefaultListSelectEffect()) {
191dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu            ShadowOverlayContainer.prepareParentForShadow(rowViewHolder.mGridView);
192892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            ((ViewGroup) rowViewHolder.view).setClipChildren(false);
193cb13a318e577e14461eb008071dddf762847de42Dake Gu            if (rowViewHolder.mContainerViewHolder != null) {
194cb13a318e577e14461eb008071dddf762847de42Dake Gu                ((ViewGroup) rowViewHolder.mContainerViewHolder.view).setClipChildren(false);
195cb13a318e577e14461eb008071dddf762847de42Dake Gu            }
196cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu        }
197b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout        FocusHighlightHelper.setupBrowseItemFocusHighlight(rowViewHolder.mItemBridgeAdapter, mZoomFactor);
19847520b68e50572a9775a662410c5aff8300c8784Craig Stout        rowViewHolder.mGridView.setOnChildSelectedListener(
19947520b68e50572a9775a662410c5aff8300c8784Craig Stout                new OnChildSelectedListener() {
20047520b68e50572a9775a662410c5aff8300c8784Craig Stout            @Override
20147520b68e50572a9775a662410c5aff8300c8784Craig Stout            public void onChildSelected(ViewGroup parent, View view, int position, long id) {
20247520b68e50572a9775a662410c5aff8300c8784Craig Stout                selectChildView(rowViewHolder, view);
20347520b68e50572a9775a662410c5aff8300c8784Craig Stout            }
20447520b68e50572a9775a662410c5aff8300c8784Craig Stout        });
205892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        rowViewHolder.mItemBridgeAdapter.setAdapterListener(
206892181367d658f347d00ea5e091aa31f086b2a20Dake Gu                new ItemBridgeAdapter.AdapterListener() {
207892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            @Override
208892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            public void onCreate(final ItemBridgeAdapter.ViewHolder viewHolder) {
209892181367d658f347d00ea5e091aa31f086b2a20Dake Gu                // Only when having an OnItemClickListner, we will attach the OnClickListener.
210892181367d658f347d00ea5e091aa31f086b2a20Dake Gu                if (getOnItemClickedListener() != null) {
21147520b68e50572a9775a662410c5aff8300c8784Craig Stout                    viewHolder.mHolder.view.setOnClickListener(new View.OnClickListener() {
21247520b68e50572a9775a662410c5aff8300c8784Craig Stout                        @Override
21347520b68e50572a9775a662410c5aff8300c8784Craig Stout                        public void onClick(View v) {
21447520b68e50572a9775a662410c5aff8300c8784Craig Stout                            ItemBridgeAdapter.ViewHolder ibh = (ItemBridgeAdapter.ViewHolder)
215892181367d658f347d00ea5e091aa31f086b2a20Dake Gu                                    rowViewHolder.mGridView.getChildViewHolder(viewHolder.itemView);
21647520b68e50572a9775a662410c5aff8300c8784Craig Stout                            if (getOnItemClickedListener() != null) {
21747520b68e50572a9775a662410c5aff8300c8784Craig Stout                                getOnItemClickedListener().onItemClicked(ibh.mItem,
21847520b68e50572a9775a662410c5aff8300c8784Craig Stout                                        (ListRow) rowViewHolder.mRow);
21947520b68e50572a9775a662410c5aff8300c8784Craig Stout                            }
22047520b68e50572a9775a662410c5aff8300c8784Craig Stout                        }
22147520b68e50572a9775a662410c5aff8300c8784Craig Stout                    });
22247520b68e50572a9775a662410c5aff8300c8784Craig Stout                }
223892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            }
224892181367d658f347d00ea5e091aa31f086b2a20Dake Gu
225892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            @Override
22629246e5ca814f17dcf368eeacd1b44a329592ae0Dake Gu            public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder viewHolder) {
227dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu                if (viewHolder.itemView instanceof ShadowOverlayContainer) {
228892181367d658f347d00ea5e091aa31f086b2a20Dake Gu                    int dimmedColor = rowViewHolder.mColorDimmer.getPaint().getColor();
229dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu                    ((ShadowOverlayContainer) viewHolder.itemView).setOverlayColor(dimmedColor);
230892181367d658f347d00ea5e091aa31f086b2a20Dake Gu                }
2314df06cbe8f6dd087fc8f1068faa77923cb297365Tim Kilbourn                viewHolder.itemView.setActivated(rowViewHolder.mExpanded);
232892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            }
2339de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout
2349de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout            @Override
2359de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout            public void onAddPresenter(Presenter presenter, int type) {
2369de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout                rowViewHolder.getGridView().getRecycledViewPool().setMaxRecycledViews(type, 24);
2379de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout            }
238892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        });
23947520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
24047520b68e50572a9775a662410c5aff8300c8784Craig Stout
241cb13a318e577e14461eb008071dddf762847de42Dake Gu    final boolean needsDefaultListSelectEffect() {
242cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu        return isUsingDefaultListSelectEffect() && getSelectEffectEnabled();
243cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    }
244cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu
24547520b68e50572a9775a662410c5aff8300c8784Craig Stout    /**
24647520b68e50572a9775a662410c5aff8300c8784Craig Stout     * Set {@link PresenterSelector} used for showing a select object in a hover card.
24747520b68e50572a9775a662410c5aff8300c8784Craig Stout     */
24847520b68e50572a9775a662410c5aff8300c8784Craig Stout    public final void setHoverCardPresenterSelector(PresenterSelector selector) {
24947520b68e50572a9775a662410c5aff8300c8784Craig Stout        mHoverCardPresenterSelector = selector;
25047520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
25147520b68e50572a9775a662410c5aff8300c8784Craig Stout
25247520b68e50572a9775a662410c5aff8300c8784Craig Stout    /**
25347520b68e50572a9775a662410c5aff8300c8784Craig Stout     * Get {@link PresenterSelector} used for showing a select object in a hover card.
25447520b68e50572a9775a662410c5aff8300c8784Craig Stout     */
25547520b68e50572a9775a662410c5aff8300c8784Craig Stout    public final PresenterSelector getHoverCardPresenterSelector() {
25647520b68e50572a9775a662410c5aff8300c8784Craig Stout        return mHoverCardPresenterSelector;
25747520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
25847520b68e50572a9775a662410c5aff8300c8784Craig Stout
25947520b68e50572a9775a662410c5aff8300c8784Craig Stout    /*
26047520b68e50572a9775a662410c5aff8300c8784Craig Stout     * Perform operations when a child of horizontal grid view is selected.
26147520b68e50572a9775a662410c5aff8300c8784Craig Stout     */
26247520b68e50572a9775a662410c5aff8300c8784Craig Stout    private void selectChildView(ViewHolder rowViewHolder, View view) {
26347520b68e50572a9775a662410c5aff8300c8784Craig Stout        ItemBridgeAdapter.ViewHolder ibh = null;
26447520b68e50572a9775a662410c5aff8300c8784Craig Stout        if (view != null) {
26547520b68e50572a9775a662410c5aff8300c8784Craig Stout            ibh = (ItemBridgeAdapter.ViewHolder)
26647520b68e50572a9775a662410c5aff8300c8784Craig Stout                    rowViewHolder.mGridView.getChildViewHolder(view);
26747520b68e50572a9775a662410c5aff8300c8784Craig Stout        }
26847520b68e50572a9775a662410c5aff8300c8784Craig Stout        if (view == null) {
26947520b68e50572a9775a662410c5aff8300c8784Craig Stout            if (mHoverCardPresenterSelector != null) {
27047520b68e50572a9775a662410c5aff8300c8784Craig Stout                rowViewHolder.mHoverCardViewSwitcher.unselect();
27147520b68e50572a9775a662410c5aff8300c8784Craig Stout            }
27247520b68e50572a9775a662410c5aff8300c8784Craig Stout            if (getOnItemSelectedListener() != null) {
27347520b68e50572a9775a662410c5aff8300c8784Craig Stout                getOnItemSelectedListener().onItemSelected(null, rowViewHolder.mRow);
27447520b68e50572a9775a662410c5aff8300c8784Craig Stout            }
27547520b68e50572a9775a662410c5aff8300c8784Craig Stout        } else if (rowViewHolder.mExpanded && rowViewHolder.mSelected) {
27647520b68e50572a9775a662410c5aff8300c8784Craig Stout            if (mHoverCardPresenterSelector != null) {
27747520b68e50572a9775a662410c5aff8300c8784Craig Stout                rowViewHolder.mHoverCardViewSwitcher.select(rowViewHolder.mGridView, view,
27847520b68e50572a9775a662410c5aff8300c8784Craig Stout                        ibh.mItem);
27947520b68e50572a9775a662410c5aff8300c8784Craig Stout            }
28047520b68e50572a9775a662410c5aff8300c8784Craig Stout            if (getOnItemSelectedListener() != null) {
28147520b68e50572a9775a662410c5aff8300c8784Craig Stout                getOnItemSelectedListener().onItemSelected(ibh.mItem, rowViewHolder.mRow);
28247520b68e50572a9775a662410c5aff8300c8784Craig Stout            }
28347520b68e50572a9775a662410c5aff8300c8784Craig Stout        }
28447520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
28547520b68e50572a9775a662410c5aff8300c8784Craig Stout
2864cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    private static void initStatics(Context context) {
2874cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        if (sSelectedRowTopPadding == 0) {
2884cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            sSelectedRowTopPadding = context.getResources().getDimensionPixelSize(
2894cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout                    R.dimen.lb_browse_selected_row_top_padding);
2904cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            sExpandedSelectedRowTopPadding = context.getResources().getDimensionPixelSize(
2914cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout                    R.dimen.lb_browse_expanded_selected_row_top_padding);
2924cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            sExpandedRowNoHovercardBottomPadding = context.getResources().getDimensionPixelSize(
2934cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout                    R.dimen.lb_browse_expanded_row_no_hovercard_bottom_padding);
2944cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        }
2954cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    }
2964cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout
2974cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    private int getSpaceUnderBaseline(ListRowPresenter.ViewHolder vh) {
2984cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        RowHeaderPresenter.ViewHolder headerViewHolder = vh.getHeaderViewHolder();
2994cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        if (headerViewHolder != null) {
3004cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            if (getHeaderPresenter() != null) {
3014cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout                return getHeaderPresenter().getSpaceUnderBaseline(headerViewHolder);
3024cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            }
3034cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            return headerViewHolder.view.getPaddingBottom();
3044cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        }
3054cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        return 0;
3064cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    }
3074cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout
3084cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    private void setVerticalPadding(ListRowPresenter.ViewHolder vh) {
3094cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        int paddingTop, paddingBottom;
3104cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        if (vh.isExpanded()) {
3114cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            int headerSpaceUnderBaseline = getSpaceUnderBaseline(vh);
3124cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            if (DEBUG) Log.v(TAG, "headerSpaceUnderBaseline " + headerSpaceUnderBaseline);
3134cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            paddingTop = (vh.isSelected() ? sExpandedSelectedRowTopPadding : vh.mPaddingTop) -
3144cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout                    headerSpaceUnderBaseline;
3154cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            paddingBottom = mHoverCardPresenterSelector == null ?
3164cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout                    sExpandedRowNoHovercardBottomPadding : vh.mPaddingBottom;
3174cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        } else if (vh.isSelected()) {
3184cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            paddingTop = sSelectedRowTopPadding;
3194cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            paddingBottom = sSelectedRowTopPadding - vh.mPaddingTop;
3204cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        } else {
3214cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            paddingTop = vh.mPaddingTop;
3224cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            paddingBottom = 0;
3234cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        }
3244cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        vh.getGridView().setPadding(vh.mPaddingLeft, paddingTop, vh.mPaddingRight,
3254cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout                paddingBottom);
3264cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    }
3274cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout
32847520b68e50572a9775a662410c5aff8300c8784Craig Stout    @Override
32947520b68e50572a9775a662410c5aff8300c8784Craig Stout    protected RowPresenter.ViewHolder createRowViewHolder(ViewGroup parent) {
3304cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        initStatics(parent.getContext());
331cb13a318e577e14461eb008071dddf762847de42Dake Gu        ListRowView rowView = new ListRowView(parent.getContext());
3329240e796bc63422c28f2707840bd99c48573279bDake Gu        setupFadingEffect(rowView);
333f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout        if (mRowHeight != 0) {
334a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn            rowView.getGridView().setRowHeight(mRowHeight);
335a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn        }
33647520b68e50572a9775a662410c5aff8300c8784Craig Stout        return new ViewHolder(rowView, rowView.getGridView(), this);
33747520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
33847520b68e50572a9775a662410c5aff8300c8784Craig Stout
33947520b68e50572a9775a662410c5aff8300c8784Craig Stout    @Override
34047520b68e50572a9775a662410c5aff8300c8784Craig Stout    protected void onRowViewSelected(RowPresenter.ViewHolder holder, boolean selected) {
3412f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu        super.onRowViewSelected(holder, selected);
3424cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        ViewHolder vh = (ViewHolder) holder;
3434cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        setVerticalPadding(vh);
3444cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        updateFooterViewSwitcher(vh);
34547520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
34647520b68e50572a9775a662410c5aff8300c8784Craig Stout
34747520b68e50572a9775a662410c5aff8300c8784Craig Stout    /*
34847520b68e50572a9775a662410c5aff8300c8784Craig Stout     * Show or hide hover card when row selection or expanded state is changed.
34947520b68e50572a9775a662410c5aff8300c8784Craig Stout     */
35047520b68e50572a9775a662410c5aff8300c8784Craig Stout    private void updateFooterViewSwitcher(ViewHolder vh) {
35147520b68e50572a9775a662410c5aff8300c8784Craig Stout        if (vh.mExpanded && vh.mSelected) {
35247520b68e50572a9775a662410c5aff8300c8784Craig Stout            if (mHoverCardPresenterSelector != null) {
35347520b68e50572a9775a662410c5aff8300c8784Craig Stout                vh.mHoverCardViewSwitcher.init((ViewGroup) vh.view,
35447520b68e50572a9775a662410c5aff8300c8784Craig Stout                        mHoverCardPresenterSelector);
35547520b68e50572a9775a662410c5aff8300c8784Craig Stout            }
35602e411c2c69d20aab138f1a162a24ea650eff7a1Dake Gu            ItemBridgeAdapter.ViewHolder ibh = (ItemBridgeAdapter.ViewHolder)
35702e411c2c69d20aab138f1a162a24ea650eff7a1Dake Gu                    vh.mGridView.findViewHolderForPosition(
35802e411c2c69d20aab138f1a162a24ea650eff7a1Dake Gu                            vh.mGridView.getSelectedPosition());
35902e411c2c69d20aab138f1a162a24ea650eff7a1Dake Gu            selectChildView(vh, ibh == null ? null : ibh.itemView);
36047520b68e50572a9775a662410c5aff8300c8784Craig Stout        } else {
36147520b68e50572a9775a662410c5aff8300c8784Craig Stout            if (mHoverCardPresenterSelector != null) {
3622f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu                vh.mHoverCardViewSwitcher.unselect();
36347520b68e50572a9775a662410c5aff8300c8784Craig Stout            }
36447520b68e50572a9775a662410c5aff8300c8784Craig Stout        }
36547520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
36647520b68e50572a9775a662410c5aff8300c8784Craig Stout
3679240e796bc63422c28f2707840bd99c48573279bDake Gu    private void setupFadingEffect(ListRowView rowView) {
3689240e796bc63422c28f2707840bd99c48573279bDake Gu        // content is completely faded at 1/2 padding of left, fading length is 1/2 of padding.
3699240e796bc63422c28f2707840bd99c48573279bDake Gu        HorizontalGridView gridView = rowView.getGridView();
3709240e796bc63422c28f2707840bd99c48573279bDake Gu        if (mBrowseRowsFadingEdgeLength < 0) {
3719240e796bc63422c28f2707840bd99c48573279bDake Gu            TypedArray ta = gridView.getContext()
3729240e796bc63422c28f2707840bd99c48573279bDake Gu                    .obtainStyledAttributes(R.styleable.LeanbackTheme);
3739240e796bc63422c28f2707840bd99c48573279bDake Gu            mBrowseRowsFadingEdgeLength = (int) ta.getDimension(
3749240e796bc63422c28f2707840bd99c48573279bDake Gu                    R.styleable.LeanbackTheme_browseRowsFadingEdgeLength, 0);
3759240e796bc63422c28f2707840bd99c48573279bDake Gu            ta.recycle();
37647520b68e50572a9775a662410c5aff8300c8784Craig Stout        }
3779240e796bc63422c28f2707840bd99c48573279bDake Gu        gridView.setFadingLeftEdgeLength(mBrowseRowsFadingEdgeLength);
37847520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
37947520b68e50572a9775a662410c5aff8300c8784Craig Stout
38047520b68e50572a9775a662410c5aff8300c8784Craig Stout    @Override
38147520b68e50572a9775a662410c5aff8300c8784Craig Stout    protected void onRowViewExpanded(RowPresenter.ViewHolder holder, boolean expanded) {
38247520b68e50572a9775a662410c5aff8300c8784Craig Stout        super.onRowViewExpanded(holder, expanded);
38347520b68e50572a9775a662410c5aff8300c8784Craig Stout        ViewHolder vh = (ViewHolder) holder;
384a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn        if (getRowHeight() != getExpandedRowHeight()) {
385a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn            int newHeight = expanded ? getExpandedRowHeight() : getRowHeight();
386a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn            vh.getGridView().setRowHeight(newHeight);
387a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn        }
3884cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        setVerticalPadding(vh);
3899240e796bc63422c28f2707840bd99c48573279bDake Gu        vh.getGridView().setFadingLeftEdge(!expanded);
39047520b68e50572a9775a662410c5aff8300c8784Craig Stout        updateFooterViewSwitcher(vh);
39147520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
39247520b68e50572a9775a662410c5aff8300c8784Craig Stout
39347520b68e50572a9775a662410c5aff8300c8784Craig Stout    @Override
394cb13a318e577e14461eb008071dddf762847de42Dake Gu    protected void onBindRowViewHolder(RowPresenter.ViewHolder holder, Object item) {
395cb13a318e577e14461eb008071dddf762847de42Dake Gu        super.onBindRowViewHolder(holder, item);
396cb13a318e577e14461eb008071dddf762847de42Dake Gu        ViewHolder vh = (ViewHolder) holder;
39747520b68e50572a9775a662410c5aff8300c8784Craig Stout        ListRow rowItem = (ListRow) item;
39847520b68e50572a9775a662410c5aff8300c8784Craig Stout        vh.mItemBridgeAdapter.clear();
39947520b68e50572a9775a662410c5aff8300c8784Craig Stout        vh.mItemBridgeAdapter.setAdapter(rowItem.getAdapter());
40047520b68e50572a9775a662410c5aff8300c8784Craig Stout        vh.mGridView.setAdapter(vh.mItemBridgeAdapter);
40147520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
40247520b68e50572a9775a662410c5aff8300c8784Craig Stout
40347520b68e50572a9775a662410c5aff8300c8784Craig Stout    @Override
404cb13a318e577e14461eb008071dddf762847de42Dake Gu    protected void onUnbindRowViewHolder(RowPresenter.ViewHolder holder) {
405cb13a318e577e14461eb008071dddf762847de42Dake Gu        ((ViewHolder) holder).mGridView.setAdapter(null);
406cb13a318e577e14461eb008071dddf762847de42Dake Gu        super.onUnbindRowViewHolder(holder);
40747520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
40847520b68e50572a9775a662410c5aff8300c8784Craig Stout
409cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    /**
410cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * ListRowPresenter overrides the default select effect of {@link RowPresenter}
411cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * and return false.
412cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     */
413cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    @Override
414cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    public final boolean isUsingDefaultSelectEffect() {
415cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu        return false;
416cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    }
417cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu
418cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    /**
419cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * Returns true so that default select effect is applied to each individual
420cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * child of {@link HorizontalGridView}.  Subclass may return false to disable
421cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * the default implementation.
422cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * @see #onSelectLevelChanged(RowPresenter.ViewHolder)
423cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     */
424cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    public boolean isUsingDefaultListSelectEffect() {
425cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu        return true;
426cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    }
427cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu
428cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    /**
429dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu     * Returns true if SDK >= 18, where default shadow
430892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * is applied to each individual child of {@link HorizontalGridView}.
431892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * Subclass may return false to disable.
432892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     */
433892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    public boolean isUsingDefaultShadow() {
434dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu        return ShadowOverlayContainer.supportsShadow();
435892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    }
436892181367d658f347d00ea5e091aa31f086b2a20Dake Gu
437892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    /**
438892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * Enable or disable child shadow.
439892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * This is not only for enable/disable default shadow implementation but also subclass must
440892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * respect this flag.
441892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     */
442892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    public final void setShadowEnabled(boolean enabled) {
443892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        mShadowEnabled = enabled;
444892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    }
445892181367d658f347d00ea5e091aa31f086b2a20Dake Gu
446892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    /**
447892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * Returns true if child shadow is enabled.
448892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * This is not only for enable/disable default shadow implementation but also subclass must
449892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * respect this flag.
450892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     */
451892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    public final boolean getShadowEnabled() {
452892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        return mShadowEnabled;
453892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    }
454892181367d658f347d00ea5e091aa31f086b2a20Dake Gu
455892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    final boolean needsDefaultShadow() {
456892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        return isUsingDefaultShadow() && getShadowEnabled();
457892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    }
458892181367d658f347d00ea5e091aa31f086b2a20Dake Gu
459892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    @Override
460892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    public boolean canDrawOutOfBounds() {
461892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        return needsDefaultShadow();
462892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    }
463892181367d658f347d00ea5e091aa31f086b2a20Dake Gu
464892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    /**
465cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * Applies select level to header and draw a default color dim over each child
466cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * of {@link HorizontalGridView}.
467cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * <p>
468cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * Subclass may override this method.  A subclass
469cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * needs to call super.onSelectLevelChanged() for applying header select level
470cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * and optionally applying a default select level to each child view of
471cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * {@link HorizontalGridView} if {@link #isUsingDefaultListSelectEffect()}
472cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * is true.  Subclass may override {@link #isUsingDefaultListSelectEffect()} to return
473cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * false and deal with the individual item select level by itself.
474cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * </p>
475cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     */
476cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    @Override
477cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    protected void onSelectLevelChanged(RowPresenter.ViewHolder holder) {
478cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu        super.onSelectLevelChanged(holder);
479cb13a318e577e14461eb008071dddf762847de42Dake Gu        if (needsDefaultListSelectEffect()) {
480cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu            ViewHolder vh = (ViewHolder) holder;
481cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu            vh.mColorDimmer.setActiveLevel(holder.mSelectLevel);
482892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            int dimmedColor = vh.mColorDimmer.getPaint().getColor();
483892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            for (int i = 0, count = vh.mGridView.getChildCount(); i < count; i++) {
484dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu                ShadowOverlayContainer wrapper = (ShadowOverlayContainer) vh.mGridView.getChildAt(i);
485dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu                wrapper.setOverlayColor(dimmedColor);
486cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu            }
4879240e796bc63422c28f2707840bd99c48573279bDake Gu            if (vh.mGridView.getFadingLeftEdge()) {
4889240e796bc63422c28f2707840bd99c48573279bDake Gu                vh.mGridView.invalidate();
4899240e796bc63422c28f2707840bd99c48573279bDake Gu            }
490cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu        }
491cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    }
492cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu
49347520b68e50572a9775a662410c5aff8300c8784Craig Stout}
494