ListRowPresenter.java revision 9de363b8db05106b03d115c266859fe200d41db7
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
2547520b68e50572a9775a662410c5aff8300c8784Craig Stout/**
267aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * ListRowPresenter renders {@link ListRow} using a
27cb13a318e577e14461eb008071dddf762847de42Dake Gu * {@link HorizontalGridView} hosted in a {@link ListRowView}.
287aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu *
297aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * <h3>Hover card</h3>
3047520b68e50572a9775a662410c5aff8300c8784Craig Stout * Optionally, {@link #setHoverCardPresenterSelector(PresenterSelector)} can be used to
3147520b68e50572a9775a662410c5aff8300c8784Craig Stout * display a view for the currently focused list item below the rendered
3247520b68e50572a9775a662410c5aff8300c8784Craig Stout * list. This view is known as a hover card.
337aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu *
347aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * <h3>Selection animation</h3>
357aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * ListRowPresenter disables {@link RowPresenter}'s default dimming effect and draw
367aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * a dim overlay on top of each individual child items.  Subclass may override and disable
377aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * {@link #isUsingDefaultListSelectEffect()} and write its own dim effect in
387aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * {@link #onSelectLevelChanged(RowPresenter.ViewHolder)}.
39dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu *
40dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu * <h3>Shadow</h3>
41dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu * ListRowPresenter applies a default shadow to child of each view.  Call
42dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu * {@link #setShadowEnabled(boolean)} to disable shadow.  Subclass may override and return
43dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu * false in {@link #isUsingDefaultShadow()} and replace with its own shadow implementation.
4447520b68e50572a9775a662410c5aff8300c8784Craig Stout */
4547520b68e50572a9775a662410c5aff8300c8784Craig Stoutpublic class ListRowPresenter extends RowPresenter {
4647520b68e50572a9775a662410c5aff8300c8784Craig Stout
4747520b68e50572a9775a662410c5aff8300c8784Craig Stout    private static final String TAG = "ListRowPresenter";
4847520b68e50572a9775a662410c5aff8300c8784Craig Stout    private static final boolean DEBUG = false;
4947520b68e50572a9775a662410c5aff8300c8784Craig Stout
5047520b68e50572a9775a662410c5aff8300c8784Craig Stout    public static class ViewHolder extends RowPresenter.ViewHolder {
5147520b68e50572a9775a662410c5aff8300c8784Craig Stout        final ListRowPresenter mListRowPresenter;
5247520b68e50572a9775a662410c5aff8300c8784Craig Stout        final HorizontalGridView mGridView;
5347520b68e50572a9775a662410c5aff8300c8784Craig Stout        final ItemBridgeAdapter mItemBridgeAdapter = new ItemBridgeAdapter();
5447520b68e50572a9775a662410c5aff8300c8784Craig Stout        final HorizontalHoverCardSwitcher mHoverCardViewSwitcher = new HorizontalHoverCardSwitcher();
55cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu        final ColorOverlayDimmer mColorDimmer;
56e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu        final int mPaddingTop;
57e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu        final int mPaddingBottom;
58e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu        final int mPaddingLeft;
59e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu        final int mPaddingRight;
6047520b68e50572a9775a662410c5aff8300c8784Craig Stout
6147520b68e50572a9775a662410c5aff8300c8784Craig Stout        public ViewHolder(View rootView, HorizontalGridView gridView, ListRowPresenter p) {
6247520b68e50572a9775a662410c5aff8300c8784Craig Stout            super(rootView);
6347520b68e50572a9775a662410c5aff8300c8784Craig Stout            mGridView = gridView;
6447520b68e50572a9775a662410c5aff8300c8784Craig Stout            mListRowPresenter = p;
65cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu            mColorDimmer = ColorOverlayDimmer.createDefault(rootView.getContext());
66e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu            mPaddingTop = mGridView.getPaddingTop();
67e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu            mPaddingBottom = mGridView.getPaddingBottom();
68e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu            mPaddingLeft = mGridView.getPaddingLeft();
69e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu            mPaddingRight = mGridView.getPaddingRight();
7047520b68e50572a9775a662410c5aff8300c8784Craig Stout        }
7147520b68e50572a9775a662410c5aff8300c8784Craig Stout
7247520b68e50572a9775a662410c5aff8300c8784Craig Stout        public final ListRowPresenter getListRowPresenter() {
7347520b68e50572a9775a662410c5aff8300c8784Craig Stout            return mListRowPresenter;
7447520b68e50572a9775a662410c5aff8300c8784Craig Stout        }
7547520b68e50572a9775a662410c5aff8300c8784Craig Stout
7647520b68e50572a9775a662410c5aff8300c8784Craig Stout        public final HorizontalGridView getGridView() {
7747520b68e50572a9775a662410c5aff8300c8784Craig Stout            return mGridView;
7847520b68e50572a9775a662410c5aff8300c8784Craig Stout        }
799de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout
809de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout        public final ItemBridgeAdapter getBridgeAdapter() {
819de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout            return mItemBridgeAdapter;
829de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout        }
8347520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
8447520b68e50572a9775a662410c5aff8300c8784Craig Stout
85a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    private int mRowHeight;
86a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    private int mExpandedRowHeight;
8747520b68e50572a9775a662410c5aff8300c8784Craig Stout    private PresenterSelector mHoverCardPresenterSelector;
88b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    private int mZoomFactor;
89892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    private boolean mShadowEnabled = true;
909240e796bc63422c28f2707840bd99c48573279bDake Gu    private int mBrowseRowsFadingEdgeLength = -1;
91b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout
924cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    private static int sSelectedRowTopPadding;
934cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    private static int sExpandedSelectedRowTopPadding;
944cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    private static int sExpandedRowNoHovercardBottomPadding;
954cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout
96b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    /**
97b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     * Constructs a ListRowPresenter with defaults.
98739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     * Uses {@link FocusHighlight#ZOOM_FACTOR_MEDIUM} for focus zooming.
99b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     */
100b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    public ListRowPresenter() {
101739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout        this(FocusHighlight.ZOOM_FACTOR_MEDIUM);
102b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    }
103b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout
104b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    /**
105b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     * Constructs a ListRowPresenter with the given parameters.
106b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     *
107b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     * @param zoomFactor Controls the zoom factor used when an item view is focused. One of
108739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     *         {@link FocusHighlight#ZOOM_FACTOR_NONE},
109739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     *         {@link FocusHighlight#ZOOM_FACTOR_SMALL},
110739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     *         {@link FocusHighlight#ZOOM_FACTOR_MEDIUM},
111739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout     *         {@link FocusHighlight#ZOOM_FACTOR_LARGE}
112b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     */
113b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    public ListRowPresenter(int zoomFactor) {
114b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout        mZoomFactor = zoomFactor;
115b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    }
116b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout
117b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    /**
118f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * Sets the row height for rows created by this Presenter. Rows
119a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     * created before calling this method will not be updated.
120a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     *
121f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * @param rowHeight Row height in pixels, or WRAP_CONTENT, or 0
122f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * to use the default height.
123a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     */
124a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    public void setRowHeight(int rowHeight) {
125a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn        mRowHeight = rowHeight;
126a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    }
127a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn
128a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    /**
129f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * Returns the row height for list rows created by this Presenter.
130a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     */
131a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    public int getRowHeight() {
132a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn        return mRowHeight;
133a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    }
134a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn
135a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    /**
136f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * Sets the expanded row height for rows created by this Presenter.
137f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * If not set, expanded rows have the same height as unexpanded
138a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     * rows.
139a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     *
140f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * @param rowHeight The row height in to use when the row is expanded,
141f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     *        in pixels, or WRAP_CONTENT, or 0 to use the default.
142a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     */
143a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    public void setExpandedRowHeight(int rowHeight) {
144a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn        mExpandedRowHeight = rowHeight;
145a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    }
146a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn
147a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    /**
148f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout     * Returns the expanded row height for rows created by this Presenter.
149a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn     */
150a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    public int getExpandedRowHeight() {
151f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout        return mExpandedRowHeight != 0 ? mExpandedRowHeight : mRowHeight;
152a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    }
153a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn
154a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn    /**
155b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     * Returns the zoom factor used for focus highlighting.
156b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout     */
157b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    public final int getZoomFactor() {
158b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout        return mZoomFactor;
159b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout    }
16047520b68e50572a9775a662410c5aff8300c8784Craig Stout
161892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    private ItemBridgeAdapter.Wrapper mCardWrapper = new ItemBridgeAdapter.Wrapper() {
162892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        @Override
163892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        public View createWrapper(View root) {
164dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu            ShadowOverlayContainer wrapper = new ShadowOverlayContainer(root.getContext());
165892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            wrapper.setLayoutParams(
166892181367d658f347d00ea5e091aa31f086b2a20Dake Gu                    new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
167cb13a318e577e14461eb008071dddf762847de42Dake Gu            wrapper.initialize(needsDefaultShadow(), needsDefaultListSelectEffect());
168892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            return wrapper;
169892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        }
170892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        @Override
171892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        public void wrap(View wrapper, View wrapped) {
172dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu            ((ShadowOverlayContainer) wrapper).wrap(wrapped);
173892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        }
174892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    };
175892181367d658f347d00ea5e091aa31f086b2a20Dake Gu
17647520b68e50572a9775a662410c5aff8300c8784Craig Stout    @Override
17747520b68e50572a9775a662410c5aff8300c8784Craig Stout    protected void initializeRowViewHolder(RowPresenter.ViewHolder holder) {
17847520b68e50572a9775a662410c5aff8300c8784Craig Stout        super.initializeRowViewHolder(holder);
17947520b68e50572a9775a662410c5aff8300c8784Craig Stout        final ViewHolder rowViewHolder = (ViewHolder) holder;
180c4b1a043ab39a881b2a05d50e93c35e6f6ebfffbDake Gu        if (needsDefaultListSelectEffect() || needsDefaultShadow()) {
181892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            rowViewHolder.mItemBridgeAdapter.setWrapper(mCardWrapper);
182892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        }
183cb13a318e577e14461eb008071dddf762847de42Dake Gu        if (needsDefaultListSelectEffect()) {
184dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu            ShadowOverlayContainer.prepareParentForShadow(rowViewHolder.mGridView);
185892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            ((ViewGroup) rowViewHolder.view).setClipChildren(false);
186cb13a318e577e14461eb008071dddf762847de42Dake Gu            if (rowViewHolder.mContainerViewHolder != null) {
187cb13a318e577e14461eb008071dddf762847de42Dake Gu                ((ViewGroup) rowViewHolder.mContainerViewHolder.view).setClipChildren(false);
188cb13a318e577e14461eb008071dddf762847de42Dake Gu            }
189cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu        }
190b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout        FocusHighlightHelper.setupBrowseItemFocusHighlight(rowViewHolder.mItemBridgeAdapter, mZoomFactor);
1910fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu        rowViewHolder.mGridView.setFocusDrawingOrderEnabled(!isUsingZOrder());
19247520b68e50572a9775a662410c5aff8300c8784Craig Stout        rowViewHolder.mGridView.setOnChildSelectedListener(
19347520b68e50572a9775a662410c5aff8300c8784Craig Stout                new OnChildSelectedListener() {
19447520b68e50572a9775a662410c5aff8300c8784Craig Stout            @Override
19547520b68e50572a9775a662410c5aff8300c8784Craig Stout            public void onChildSelected(ViewGroup parent, View view, int position, long id) {
19647520b68e50572a9775a662410c5aff8300c8784Craig Stout                selectChildView(rowViewHolder, view);
19747520b68e50572a9775a662410c5aff8300c8784Craig Stout            }
19847520b68e50572a9775a662410c5aff8300c8784Craig Stout        });
199892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        rowViewHolder.mItemBridgeAdapter.setAdapterListener(
200892181367d658f347d00ea5e091aa31f086b2a20Dake Gu                new ItemBridgeAdapter.AdapterListener() {
201892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            @Override
202892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            public void onCreate(final ItemBridgeAdapter.ViewHolder viewHolder) {
203892181367d658f347d00ea5e091aa31f086b2a20Dake Gu                // Only when having an OnItemClickListner, we will attach the OnClickListener.
2049de363b8db05106b03d115c266859fe200d41db7Dake Gu                if (getOnItemClickedListener() != null || getOnItemViewClickedListener() != null) {
20547520b68e50572a9775a662410c5aff8300c8784Craig Stout                    viewHolder.mHolder.view.setOnClickListener(new View.OnClickListener() {
20647520b68e50572a9775a662410c5aff8300c8784Craig Stout                        @Override
20747520b68e50572a9775a662410c5aff8300c8784Craig Stout                        public void onClick(View v) {
20847520b68e50572a9775a662410c5aff8300c8784Craig Stout                            ItemBridgeAdapter.ViewHolder ibh = (ItemBridgeAdapter.ViewHolder)
2099de363b8db05106b03d115c266859fe200d41db7Dake Gu                                    rowViewHolder.mGridView
2109de363b8db05106b03d115c266859fe200d41db7Dake Gu                                            .getChildViewHolder(viewHolder.itemView);
21147520b68e50572a9775a662410c5aff8300c8784Craig Stout                            if (getOnItemClickedListener() != null) {
21247520b68e50572a9775a662410c5aff8300c8784Craig Stout                                getOnItemClickedListener().onItemClicked(ibh.mItem,
21347520b68e50572a9775a662410c5aff8300c8784Craig Stout                                        (ListRow) rowViewHolder.mRow);
21447520b68e50572a9775a662410c5aff8300c8784Craig Stout                            }
2159de363b8db05106b03d115c266859fe200d41db7Dake Gu                            if (getOnItemViewClickedListener() != null) {
2169de363b8db05106b03d115c266859fe200d41db7Dake Gu                                getOnItemViewClickedListener().onItemClicked(viewHolder.mHolder,
2179de363b8db05106b03d115c266859fe200d41db7Dake Gu                                        ibh.mItem, rowViewHolder, (ListRow) rowViewHolder.mRow);
2189de363b8db05106b03d115c266859fe200d41db7Dake Gu                            }
21947520b68e50572a9775a662410c5aff8300c8784Craig Stout                        }
22047520b68e50572a9775a662410c5aff8300c8784Craig Stout                    });
22147520b68e50572a9775a662410c5aff8300c8784Craig Stout                }
222892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            }
223892181367d658f347d00ea5e091aa31f086b2a20Dake Gu
224892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            @Override
22529246e5ca814f17dcf368eeacd1b44a329592ae0Dake Gu            public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder viewHolder) {
226dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu                if (viewHolder.itemView instanceof ShadowOverlayContainer) {
227892181367d658f347d00ea5e091aa31f086b2a20Dake Gu                    int dimmedColor = rowViewHolder.mColorDimmer.getPaint().getColor();
228dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu                    ((ShadowOverlayContainer) viewHolder.itemView).setOverlayColor(dimmedColor);
229892181367d658f347d00ea5e091aa31f086b2a20Dake Gu                }
2304df06cbe8f6dd087fc8f1068faa77923cb297365Tim Kilbourn                viewHolder.itemView.setActivated(rowViewHolder.mExpanded);
231892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            }
2329de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout
2339de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout            @Override
2349de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout            public void onAddPresenter(Presenter presenter, int type) {
2359de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout                rowViewHolder.getGridView().getRecycledViewPool().setMaxRecycledViews(type, 24);
2369de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout            }
237892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        });
23847520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
23947520b68e50572a9775a662410c5aff8300c8784Craig Stout
240cb13a318e577e14461eb008071dddf762847de42Dake Gu    final boolean needsDefaultListSelectEffect() {
241cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu        return isUsingDefaultListSelectEffect() && getSelectEffectEnabled();
242cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    }
243cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu
24447520b68e50572a9775a662410c5aff8300c8784Craig Stout    /**
24547520b68e50572a9775a662410c5aff8300c8784Craig Stout     * Set {@link PresenterSelector} used for showing a select object in a hover card.
24647520b68e50572a9775a662410c5aff8300c8784Craig Stout     */
24747520b68e50572a9775a662410c5aff8300c8784Craig Stout    public final void setHoverCardPresenterSelector(PresenterSelector selector) {
24847520b68e50572a9775a662410c5aff8300c8784Craig Stout        mHoverCardPresenterSelector = selector;
24947520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
25047520b68e50572a9775a662410c5aff8300c8784Craig Stout
25147520b68e50572a9775a662410c5aff8300c8784Craig Stout    /**
25247520b68e50572a9775a662410c5aff8300c8784Craig Stout     * Get {@link PresenterSelector} used for showing a select object in a hover card.
25347520b68e50572a9775a662410c5aff8300c8784Craig Stout     */
25447520b68e50572a9775a662410c5aff8300c8784Craig Stout    public final PresenterSelector getHoverCardPresenterSelector() {
25547520b68e50572a9775a662410c5aff8300c8784Craig Stout        return mHoverCardPresenterSelector;
25647520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
25747520b68e50572a9775a662410c5aff8300c8784Craig Stout
25847520b68e50572a9775a662410c5aff8300c8784Craig Stout    /*
25947520b68e50572a9775a662410c5aff8300c8784Craig Stout     * Perform operations when a child of horizontal grid view is selected.
26047520b68e50572a9775a662410c5aff8300c8784Craig Stout     */
26147520b68e50572a9775a662410c5aff8300c8784Craig Stout    private void selectChildView(ViewHolder rowViewHolder, View view) {
26247520b68e50572a9775a662410c5aff8300c8784Craig Stout        ItemBridgeAdapter.ViewHolder ibh = null;
26347520b68e50572a9775a662410c5aff8300c8784Craig Stout        if (view != null) {
26447520b68e50572a9775a662410c5aff8300c8784Craig Stout            ibh = (ItemBridgeAdapter.ViewHolder)
26547520b68e50572a9775a662410c5aff8300c8784Craig Stout                    rowViewHolder.mGridView.getChildViewHolder(view);
26647520b68e50572a9775a662410c5aff8300c8784Craig Stout        }
26747520b68e50572a9775a662410c5aff8300c8784Craig Stout        if (view == null) {
26847520b68e50572a9775a662410c5aff8300c8784Craig Stout            if (mHoverCardPresenterSelector != null) {
26947520b68e50572a9775a662410c5aff8300c8784Craig Stout                rowViewHolder.mHoverCardViewSwitcher.unselect();
27047520b68e50572a9775a662410c5aff8300c8784Craig Stout            }
2719de363b8db05106b03d115c266859fe200d41db7Dake Gu            if (getOnItemViewSelectedListener() != null) {
2729de363b8db05106b03d115c266859fe200d41db7Dake Gu                getOnItemViewSelectedListener().onItemSelected(null, null,
2739de363b8db05106b03d115c266859fe200d41db7Dake Gu                        rowViewHolder, rowViewHolder.mRow);
2749de363b8db05106b03d115c266859fe200d41db7Dake Gu            }
27547520b68e50572a9775a662410c5aff8300c8784Craig Stout            if (getOnItemSelectedListener() != null) {
27647520b68e50572a9775a662410c5aff8300c8784Craig Stout                getOnItemSelectedListener().onItemSelected(null, rowViewHolder.mRow);
27747520b68e50572a9775a662410c5aff8300c8784Craig Stout            }
27847520b68e50572a9775a662410c5aff8300c8784Craig Stout        } else if (rowViewHolder.mExpanded && rowViewHolder.mSelected) {
27947520b68e50572a9775a662410c5aff8300c8784Craig Stout            if (mHoverCardPresenterSelector != null) {
28047520b68e50572a9775a662410c5aff8300c8784Craig Stout                rowViewHolder.mHoverCardViewSwitcher.select(rowViewHolder.mGridView, view,
28147520b68e50572a9775a662410c5aff8300c8784Craig Stout                        ibh.mItem);
28247520b68e50572a9775a662410c5aff8300c8784Craig Stout            }
2839de363b8db05106b03d115c266859fe200d41db7Dake Gu            if (getOnItemViewSelectedListener() != null) {
2849de363b8db05106b03d115c266859fe200d41db7Dake Gu                getOnItemViewSelectedListener().onItemSelected(ibh.mHolder, ibh.mItem,
2859de363b8db05106b03d115c266859fe200d41db7Dake Gu                        rowViewHolder, rowViewHolder.mRow);
2869de363b8db05106b03d115c266859fe200d41db7Dake Gu            }
28747520b68e50572a9775a662410c5aff8300c8784Craig Stout            if (getOnItemSelectedListener() != null) {
28847520b68e50572a9775a662410c5aff8300c8784Craig Stout                getOnItemSelectedListener().onItemSelected(ibh.mItem, rowViewHolder.mRow);
28947520b68e50572a9775a662410c5aff8300c8784Craig Stout            }
29047520b68e50572a9775a662410c5aff8300c8784Craig Stout        }
29147520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
29247520b68e50572a9775a662410c5aff8300c8784Craig Stout
2934cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    private static void initStatics(Context context) {
2944cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        if (sSelectedRowTopPadding == 0) {
2954cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            sSelectedRowTopPadding = context.getResources().getDimensionPixelSize(
2964cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout                    R.dimen.lb_browse_selected_row_top_padding);
2974cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            sExpandedSelectedRowTopPadding = context.getResources().getDimensionPixelSize(
2984cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout                    R.dimen.lb_browse_expanded_selected_row_top_padding);
2994cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            sExpandedRowNoHovercardBottomPadding = context.getResources().getDimensionPixelSize(
3004cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout                    R.dimen.lb_browse_expanded_row_no_hovercard_bottom_padding);
3014cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        }
3024cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    }
3034cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout
3044cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    private int getSpaceUnderBaseline(ListRowPresenter.ViewHolder vh) {
3054cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        RowHeaderPresenter.ViewHolder headerViewHolder = vh.getHeaderViewHolder();
3064cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        if (headerViewHolder != null) {
3074cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            if (getHeaderPresenter() != null) {
3084cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout                return getHeaderPresenter().getSpaceUnderBaseline(headerViewHolder);
3094cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            }
3104cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            return headerViewHolder.view.getPaddingBottom();
3114cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        }
3124cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        return 0;
3134cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    }
3144cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout
3154cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    private void setVerticalPadding(ListRowPresenter.ViewHolder vh) {
3164cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        int paddingTop, paddingBottom;
3174cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        if (vh.isExpanded()) {
3184cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            int headerSpaceUnderBaseline = getSpaceUnderBaseline(vh);
3194cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            if (DEBUG) Log.v(TAG, "headerSpaceUnderBaseline " + headerSpaceUnderBaseline);
3204cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            paddingTop = (vh.isSelected() ? sExpandedSelectedRowTopPadding : vh.mPaddingTop) -
3214cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout                    headerSpaceUnderBaseline;
3224cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            paddingBottom = mHoverCardPresenterSelector == null ?
3234cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout                    sExpandedRowNoHovercardBottomPadding : vh.mPaddingBottom;
3244cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        } else if (vh.isSelected()) {
3254cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            paddingTop = sSelectedRowTopPadding;
3264cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            paddingBottom = sSelectedRowTopPadding - vh.mPaddingTop;
3274cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        } else {
3284cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            paddingTop = vh.mPaddingTop;
3294cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout            paddingBottom = 0;
3304cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        }
3314cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        vh.getGridView().setPadding(vh.mPaddingLeft, paddingTop, vh.mPaddingRight,
3324cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout                paddingBottom);
3334cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout    }
3344cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout
33547520b68e50572a9775a662410c5aff8300c8784Craig Stout    @Override
33647520b68e50572a9775a662410c5aff8300c8784Craig Stout    protected RowPresenter.ViewHolder createRowViewHolder(ViewGroup parent) {
3374cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        initStatics(parent.getContext());
338cb13a318e577e14461eb008071dddf762847de42Dake Gu        ListRowView rowView = new ListRowView(parent.getContext());
3399240e796bc63422c28f2707840bd99c48573279bDake Gu        setupFadingEffect(rowView);
340f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout        if (mRowHeight != 0) {
341a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn            rowView.getGridView().setRowHeight(mRowHeight);
342a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn        }
34347520b68e50572a9775a662410c5aff8300c8784Craig Stout        return new ViewHolder(rowView, rowView.getGridView(), this);
34447520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
34547520b68e50572a9775a662410c5aff8300c8784Craig Stout
34647520b68e50572a9775a662410c5aff8300c8784Craig Stout    @Override
34747520b68e50572a9775a662410c5aff8300c8784Craig Stout    protected void onRowViewSelected(RowPresenter.ViewHolder holder, boolean selected) {
3482f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu        super.onRowViewSelected(holder, selected);
3494cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        ViewHolder vh = (ViewHolder) holder;
3504cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        setVerticalPadding(vh);
3514cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        updateFooterViewSwitcher(vh);
35247520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
35347520b68e50572a9775a662410c5aff8300c8784Craig Stout
35447520b68e50572a9775a662410c5aff8300c8784Craig Stout    /*
35547520b68e50572a9775a662410c5aff8300c8784Craig Stout     * Show or hide hover card when row selection or expanded state is changed.
35647520b68e50572a9775a662410c5aff8300c8784Craig Stout     */
35747520b68e50572a9775a662410c5aff8300c8784Craig Stout    private void updateFooterViewSwitcher(ViewHolder vh) {
35847520b68e50572a9775a662410c5aff8300c8784Craig Stout        if (vh.mExpanded && vh.mSelected) {
35947520b68e50572a9775a662410c5aff8300c8784Craig Stout            if (mHoverCardPresenterSelector != null) {
36047520b68e50572a9775a662410c5aff8300c8784Craig Stout                vh.mHoverCardViewSwitcher.init((ViewGroup) vh.view,
36147520b68e50572a9775a662410c5aff8300c8784Craig Stout                        mHoverCardPresenterSelector);
36247520b68e50572a9775a662410c5aff8300c8784Craig Stout            }
36302e411c2c69d20aab138f1a162a24ea650eff7a1Dake Gu            ItemBridgeAdapter.ViewHolder ibh = (ItemBridgeAdapter.ViewHolder)
36402e411c2c69d20aab138f1a162a24ea650eff7a1Dake Gu                    vh.mGridView.findViewHolderForPosition(
36502e411c2c69d20aab138f1a162a24ea650eff7a1Dake Gu                            vh.mGridView.getSelectedPosition());
36602e411c2c69d20aab138f1a162a24ea650eff7a1Dake Gu            selectChildView(vh, ibh == null ? null : ibh.itemView);
36747520b68e50572a9775a662410c5aff8300c8784Craig Stout        } else {
36847520b68e50572a9775a662410c5aff8300c8784Craig Stout            if (mHoverCardPresenterSelector != null) {
3692f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu                vh.mHoverCardViewSwitcher.unselect();
37047520b68e50572a9775a662410c5aff8300c8784Craig Stout            }
37147520b68e50572a9775a662410c5aff8300c8784Craig Stout        }
37247520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
37347520b68e50572a9775a662410c5aff8300c8784Craig Stout
3749240e796bc63422c28f2707840bd99c48573279bDake Gu    private void setupFadingEffect(ListRowView rowView) {
3759240e796bc63422c28f2707840bd99c48573279bDake Gu        // content is completely faded at 1/2 padding of left, fading length is 1/2 of padding.
3769240e796bc63422c28f2707840bd99c48573279bDake Gu        HorizontalGridView gridView = rowView.getGridView();
3779240e796bc63422c28f2707840bd99c48573279bDake Gu        if (mBrowseRowsFadingEdgeLength < 0) {
3789240e796bc63422c28f2707840bd99c48573279bDake Gu            TypedArray ta = gridView.getContext()
3799240e796bc63422c28f2707840bd99c48573279bDake Gu                    .obtainStyledAttributes(R.styleable.LeanbackTheme);
3809240e796bc63422c28f2707840bd99c48573279bDake Gu            mBrowseRowsFadingEdgeLength = (int) ta.getDimension(
3819240e796bc63422c28f2707840bd99c48573279bDake Gu                    R.styleable.LeanbackTheme_browseRowsFadingEdgeLength, 0);
3829240e796bc63422c28f2707840bd99c48573279bDake Gu            ta.recycle();
38347520b68e50572a9775a662410c5aff8300c8784Craig Stout        }
3849240e796bc63422c28f2707840bd99c48573279bDake Gu        gridView.setFadingLeftEdgeLength(mBrowseRowsFadingEdgeLength);
38547520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
38647520b68e50572a9775a662410c5aff8300c8784Craig Stout
38747520b68e50572a9775a662410c5aff8300c8784Craig Stout    @Override
38847520b68e50572a9775a662410c5aff8300c8784Craig Stout    protected void onRowViewExpanded(RowPresenter.ViewHolder holder, boolean expanded) {
38947520b68e50572a9775a662410c5aff8300c8784Craig Stout        super.onRowViewExpanded(holder, expanded);
39047520b68e50572a9775a662410c5aff8300c8784Craig Stout        ViewHolder vh = (ViewHolder) holder;
391a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn        if (getRowHeight() != getExpandedRowHeight()) {
392a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn            int newHeight = expanded ? getExpandedRowHeight() : getRowHeight();
393a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn            vh.getGridView().setRowHeight(newHeight);
394a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn        }
3954cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout        setVerticalPadding(vh);
3969240e796bc63422c28f2707840bd99c48573279bDake Gu        vh.getGridView().setFadingLeftEdge(!expanded);
39747520b68e50572a9775a662410c5aff8300c8784Craig Stout        updateFooterViewSwitcher(vh);
39847520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
39947520b68e50572a9775a662410c5aff8300c8784Craig Stout
40047520b68e50572a9775a662410c5aff8300c8784Craig Stout    @Override
401cb13a318e577e14461eb008071dddf762847de42Dake Gu    protected void onBindRowViewHolder(RowPresenter.ViewHolder holder, Object item) {
402cb13a318e577e14461eb008071dddf762847de42Dake Gu        super.onBindRowViewHolder(holder, item);
403cb13a318e577e14461eb008071dddf762847de42Dake Gu        ViewHolder vh = (ViewHolder) holder;
40447520b68e50572a9775a662410c5aff8300c8784Craig Stout        ListRow rowItem = (ListRow) item;
40547520b68e50572a9775a662410c5aff8300c8784Craig Stout        vh.mItemBridgeAdapter.clear();
40647520b68e50572a9775a662410c5aff8300c8784Craig Stout        vh.mItemBridgeAdapter.setAdapter(rowItem.getAdapter());
40747520b68e50572a9775a662410c5aff8300c8784Craig Stout        vh.mGridView.setAdapter(vh.mItemBridgeAdapter);
40847520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
40947520b68e50572a9775a662410c5aff8300c8784Craig Stout
41047520b68e50572a9775a662410c5aff8300c8784Craig Stout    @Override
411cb13a318e577e14461eb008071dddf762847de42Dake Gu    protected void onUnbindRowViewHolder(RowPresenter.ViewHolder holder) {
412cb13a318e577e14461eb008071dddf762847de42Dake Gu        ((ViewHolder) holder).mGridView.setAdapter(null);
413cb13a318e577e14461eb008071dddf762847de42Dake Gu        super.onUnbindRowViewHolder(holder);
41447520b68e50572a9775a662410c5aff8300c8784Craig Stout    }
41547520b68e50572a9775a662410c5aff8300c8784Craig Stout
416cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    /**
417cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * ListRowPresenter overrides the default select effect of {@link RowPresenter}
418cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * and return false.
419cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     */
420cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    @Override
421cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    public final boolean isUsingDefaultSelectEffect() {
422cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu        return false;
423cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    }
424cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu
425cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    /**
426cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * Returns true so that default select effect is applied to each individual
427cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * child of {@link HorizontalGridView}.  Subclass may return false to disable
428cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * the default implementation.
429cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * @see #onSelectLevelChanged(RowPresenter.ViewHolder)
430cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     */
431cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    public boolean isUsingDefaultListSelectEffect() {
432cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu        return true;
433cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    }
434cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu
435cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    /**
436dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu     * Returns true if SDK >= 18, where default shadow
437892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * is applied to each individual child of {@link HorizontalGridView}.
438892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * Subclass may return false to disable.
439892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     */
440892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    public boolean isUsingDefaultShadow() {
441dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu        return ShadowOverlayContainer.supportsShadow();
442892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    }
443892181367d658f347d00ea5e091aa31f086b2a20Dake Gu
444892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    /**
4450fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu     * Returns true if SDK >= L, where Z shadow is enabled so that Z order is enabled
4460fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu     * on each child of horizontal list.   If subclass returns false in isUsingDefaultShadow()
4470fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu     * and does not use Z-shadow on SDK >= L, it should override isUsingZOrder() return false.
4480fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu     */
4490fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu    public boolean isUsingZOrder() {
4500fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu        return ShadowHelper.getInstance().usesZShadow();
4510fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu    }
4520fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu
4530fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu    /**
454892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * Enable or disable child shadow.
455892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * This is not only for enable/disable default shadow implementation but also subclass must
456892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * respect this flag.
457892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     */
458892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    public final void setShadowEnabled(boolean enabled) {
459892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        mShadowEnabled = enabled;
460892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    }
461892181367d658f347d00ea5e091aa31f086b2a20Dake Gu
462892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    /**
463892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * Returns true if child shadow is enabled.
464892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * This is not only for enable/disable default shadow implementation but also subclass must
465892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     * respect this flag.
466892181367d658f347d00ea5e091aa31f086b2a20Dake Gu     */
467892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    public final boolean getShadowEnabled() {
468892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        return mShadowEnabled;
469892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    }
470892181367d658f347d00ea5e091aa31f086b2a20Dake Gu
471892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    final boolean needsDefaultShadow() {
472892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        return isUsingDefaultShadow() && getShadowEnabled();
473892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    }
474892181367d658f347d00ea5e091aa31f086b2a20Dake Gu
475892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    @Override
476892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    public boolean canDrawOutOfBounds() {
477892181367d658f347d00ea5e091aa31f086b2a20Dake Gu        return needsDefaultShadow();
478892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    }
479892181367d658f347d00ea5e091aa31f086b2a20Dake Gu
480892181367d658f347d00ea5e091aa31f086b2a20Dake Gu    /**
481cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * Applies select level to header and draw a default color dim over each child
482cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * of {@link HorizontalGridView}.
483cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * <p>
484cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * Subclass may override this method.  A subclass
485cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * needs to call super.onSelectLevelChanged() for applying header select level
486cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * and optionally applying a default select level to each child view of
487cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * {@link HorizontalGridView} if {@link #isUsingDefaultListSelectEffect()}
488cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * is true.  Subclass may override {@link #isUsingDefaultListSelectEffect()} to return
489cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * false and deal with the individual item select level by itself.
490cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     * </p>
491cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu     */
492cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    @Override
493cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    protected void onSelectLevelChanged(RowPresenter.ViewHolder holder) {
494cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu        super.onSelectLevelChanged(holder);
495cb13a318e577e14461eb008071dddf762847de42Dake Gu        if (needsDefaultListSelectEffect()) {
496cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu            ViewHolder vh = (ViewHolder) holder;
497cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu            vh.mColorDimmer.setActiveLevel(holder.mSelectLevel);
498892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            int dimmedColor = vh.mColorDimmer.getPaint().getColor();
499892181367d658f347d00ea5e091aa31f086b2a20Dake Gu            for (int i = 0, count = vh.mGridView.getChildCount(); i < count; i++) {
500dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu                ShadowOverlayContainer wrapper = (ShadowOverlayContainer) vh.mGridView.getChildAt(i);
501dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu                wrapper.setOverlayColor(dimmedColor);
502cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu            }
5039240e796bc63422c28f2707840bd99c48573279bDake Gu            if (vh.mGridView.getFadingLeftEdge()) {
5049240e796bc63422c28f2707840bd99c48573279bDake Gu                vh.mGridView.invalidate();
5059240e796bc63422c28f2707840bd99c48573279bDake Gu            }
506cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu        }
507cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu    }
508cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu
50947520b68e50572a9775a662410c5aff8300c8784Craig Stout}
510