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; 19f4acd3cf076435ce836a6d4a9027b73ec3050defCraig Stoutimport android.support.v17.leanback.system.Settings; 204cd4cce277571385f4d1a56d5348578c38368cbeCraig Stoutimport android.util.Log; 2160bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stoutimport android.view.KeyEvent; 2247520b68e50572a9775a662410c5aff8300c8784Craig Stoutimport android.view.View; 2347520b68e50572a9775a662410c5aff8300c8784Craig Stoutimport android.view.ViewGroup; 24892181367d658f347d00ea5e091aa31f086b2a20Dake Guimport android.view.ViewGroup.LayoutParams; 2547520b68e50572a9775a662410c5aff8300c8784Craig Stout 26bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stoutimport java.util.HashMap; 27bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout 2847520b68e50572a9775a662410c5aff8300c8784Craig Stout/** 297aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * ListRowPresenter renders {@link ListRow} using a 30cb13a318e577e14461eb008071dddf762847de42Dake Gu * {@link HorizontalGridView} hosted in a {@link ListRowView}. 317aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * 327aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * <h3>Hover card</h3> 3347520b68e50572a9775a662410c5aff8300c8784Craig Stout * Optionally, {@link #setHoverCardPresenterSelector(PresenterSelector)} can be used to 3447520b68e50572a9775a662410c5aff8300c8784Craig Stout * display a view for the currently focused list item below the rendered 3547520b68e50572a9775a662410c5aff8300c8784Craig Stout * list. This view is known as a hover card. 367aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * 377aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * <h3>Selection animation</h3> 38a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * ListRowPresenter disables {@link RowPresenter}'s default dimming effect and draws 39a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * a dim overlay on each view individually. A subclass may override and disable 407aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * {@link #isUsingDefaultListSelectEffect()} and write its own dim effect in 417aaa6c6ef8807cc4ea4c4642716d6e30056bc4ebDake Gu * {@link #onSelectLevelChanged(RowPresenter.ViewHolder)}. 42dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu * 43dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu * <h3>Shadow</h3> 44a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * ListRowPresenter applies a default shadow to each child view. Call 45a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * {@link #setShadowEnabled(boolean)} to disable shadows. A subclass may override and return 46dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu * false in {@link #isUsingDefaultShadow()} and replace with its own shadow implementation. 4747520b68e50572a9775a662410c5aff8300c8784Craig Stout */ 4847520b68e50572a9775a662410c5aff8300c8784Craig Stoutpublic class ListRowPresenter extends RowPresenter { 4947520b68e50572a9775a662410c5aff8300c8784Craig Stout 5047520b68e50572a9775a662410c5aff8300c8784Craig Stout private static final String TAG = "ListRowPresenter"; 5147520b68e50572a9775a662410c5aff8300c8784Craig Stout private static final boolean DEBUG = false; 5247520b68e50572a9775a662410c5aff8300c8784Craig Stout 53bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout private static final int DEFAULT_RECYCLED_POOL_SIZE = 24; 54bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout 55a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout /** 56a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * ViewHolder for the ListRowPresenter. 57a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout */ 5847520b68e50572a9775a662410c5aff8300c8784Craig Stout public static class ViewHolder extends RowPresenter.ViewHolder { 5947520b68e50572a9775a662410c5aff8300c8784Craig Stout final ListRowPresenter mListRowPresenter; 6047520b68e50572a9775a662410c5aff8300c8784Craig Stout final HorizontalGridView mGridView; 6171fddded48048acfa744ac352166770c91a1c2b1Dake Gu ItemBridgeAdapter mItemBridgeAdapter; 6247520b68e50572a9775a662410c5aff8300c8784Craig Stout final HorizontalHoverCardSwitcher mHoverCardViewSwitcher = new HorizontalHoverCardSwitcher(); 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; 72e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu mPaddingTop = mGridView.getPaddingTop(); 73e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu mPaddingBottom = mGridView.getPaddingBottom(); 74e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu mPaddingLeft = mGridView.getPaddingLeft(); 75e43e9266c4b7e4902fefb5d2a0cacca90a3d2681Dake Gu mPaddingRight = mGridView.getPaddingRight(); 7647520b68e50572a9775a662410c5aff8300c8784Craig Stout } 7747520b68e50572a9775a662410c5aff8300c8784Craig Stout 7847520b68e50572a9775a662410c5aff8300c8784Craig Stout public final ListRowPresenter getListRowPresenter() { 7947520b68e50572a9775a662410c5aff8300c8784Craig Stout return mListRowPresenter; 8047520b68e50572a9775a662410c5aff8300c8784Craig Stout } 8147520b68e50572a9775a662410c5aff8300c8784Craig Stout 8247520b68e50572a9775a662410c5aff8300c8784Craig Stout public final HorizontalGridView getGridView() { 8347520b68e50572a9775a662410c5aff8300c8784Craig Stout return mGridView; 8447520b68e50572a9775a662410c5aff8300c8784Craig Stout } 859de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout 869de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout public final ItemBridgeAdapter getBridgeAdapter() { 879de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout return mItemBridgeAdapter; 889de682083d3da5b1127969ee1fd7b74561aa9acdCraig Stout } 8947520b68e50572a9775a662410c5aff8300c8784Craig Stout } 9047520b68e50572a9775a662410c5aff8300c8784Craig Stout 9171fddded48048acfa744ac352166770c91a1c2b1Dake Gu class ListRowPresenterItemBridgeAdapter extends ItemBridgeAdapter { 9271fddded48048acfa744ac352166770c91a1c2b1Dake Gu ListRowPresenter.ViewHolder mRowViewHolder; 9371fddded48048acfa744ac352166770c91a1c2b1Dake Gu 9471fddded48048acfa744ac352166770c91a1c2b1Dake Gu ListRowPresenterItemBridgeAdapter(ListRowPresenter.ViewHolder rowViewHolder) { 9571fddded48048acfa744ac352166770c91a1c2b1Dake Gu mRowViewHolder = rowViewHolder; 9671fddded48048acfa744ac352166770c91a1c2b1Dake Gu } 9771fddded48048acfa744ac352166770c91a1c2b1Dake Gu 9871fddded48048acfa744ac352166770c91a1c2b1Dake Gu @Override 9971fddded48048acfa744ac352166770c91a1c2b1Dake Gu public void onBind(final ItemBridgeAdapter.ViewHolder viewHolder) { 10071fddded48048acfa744ac352166770c91a1c2b1Dake Gu // Only when having an OnItemClickListner, we will attach the OnClickListener. 1013a5038bd0fefa5628a31a21422bf2126c53472a9Craig Stout if (mRowViewHolder.getOnItemViewClickedListener() != null) { 10271fddded48048acfa744ac352166770c91a1c2b1Dake Gu viewHolder.mHolder.view.setOnClickListener(new View.OnClickListener() { 10371fddded48048acfa744ac352166770c91a1c2b1Dake Gu @Override 10471fddded48048acfa744ac352166770c91a1c2b1Dake Gu public void onClick(View v) { 10571fddded48048acfa744ac352166770c91a1c2b1Dake Gu ItemBridgeAdapter.ViewHolder ibh = (ItemBridgeAdapter.ViewHolder) 10671fddded48048acfa744ac352166770c91a1c2b1Dake Gu mRowViewHolder.mGridView.getChildViewHolder(viewHolder.itemView); 1073a5038bd0fefa5628a31a21422bf2126c53472a9Craig Stout if (mRowViewHolder.getOnItemViewClickedListener() != null) { 1083a5038bd0fefa5628a31a21422bf2126c53472a9Craig Stout mRowViewHolder.getOnItemViewClickedListener().onItemClicked(viewHolder.mHolder, 10971fddded48048acfa744ac352166770c91a1c2b1Dake Gu ibh.mItem, mRowViewHolder, (ListRow) mRowViewHolder.mRow); 11071fddded48048acfa744ac352166770c91a1c2b1Dake Gu } 11171fddded48048acfa744ac352166770c91a1c2b1Dake Gu } 11271fddded48048acfa744ac352166770c91a1c2b1Dake Gu }); 11371fddded48048acfa744ac352166770c91a1c2b1Dake Gu } 11471fddded48048acfa744ac352166770c91a1c2b1Dake Gu } 11571fddded48048acfa744ac352166770c91a1c2b1Dake Gu 11671fddded48048acfa744ac352166770c91a1c2b1Dake Gu @Override 11771fddded48048acfa744ac352166770c91a1c2b1Dake Gu public void onUnbind(ItemBridgeAdapter.ViewHolder viewHolder) { 1183a5038bd0fefa5628a31a21422bf2126c53472a9Craig Stout if (mRowViewHolder.getOnItemViewClickedListener() != null) { 11971fddded48048acfa744ac352166770c91a1c2b1Dake Gu viewHolder.mHolder.view.setOnClickListener(null); 12071fddded48048acfa744ac352166770c91a1c2b1Dake Gu } 12171fddded48048acfa744ac352166770c91a1c2b1Dake Gu } 12271fddded48048acfa744ac352166770c91a1c2b1Dake Gu 12371fddded48048acfa744ac352166770c91a1c2b1Dake Gu @Override 12471fddded48048acfa744ac352166770c91a1c2b1Dake Gu public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder viewHolder) { 1255870e4aca782a55d0e8f7650f06aec86080b2f88Craig Stout if (needsDefaultListSelectEffect()) { 12671fddded48048acfa744ac352166770c91a1c2b1Dake Gu int dimmedColor = mRowViewHolder.mColorDimmer.getPaint().getColor(); 12771fddded48048acfa744ac352166770c91a1c2b1Dake Gu ((ShadowOverlayContainer) viewHolder.itemView).setOverlayColor(dimmedColor); 12871fddded48048acfa744ac352166770c91a1c2b1Dake Gu } 12971fddded48048acfa744ac352166770c91a1c2b1Dake Gu mRowViewHolder.syncActivatedStatus(viewHolder.itemView); 13071fddded48048acfa744ac352166770c91a1c2b1Dake Gu } 13171fddded48048acfa744ac352166770c91a1c2b1Dake Gu 13271fddded48048acfa744ac352166770c91a1c2b1Dake Gu @Override 13371fddded48048acfa744ac352166770c91a1c2b1Dake Gu public void onAddPresenter(Presenter presenter, int type) { 13471fddded48048acfa744ac352166770c91a1c2b1Dake Gu mRowViewHolder.getGridView().getRecycledViewPool().setMaxRecycledViews( 13571fddded48048acfa744ac352166770c91a1c2b1Dake Gu type, getRecycledPoolSize(presenter)); 13671fddded48048acfa744ac352166770c91a1c2b1Dake Gu } 13771fddded48048acfa744ac352166770c91a1c2b1Dake Gu } 13871fddded48048acfa744ac352166770c91a1c2b1Dake Gu 139a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn private int mRowHeight; 140a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn private int mExpandedRowHeight; 14147520b68e50572a9775a662410c5aff8300c8784Craig Stout private PresenterSelector mHoverCardPresenterSelector; 14241ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield private int mFocusZoomFactor; 14341ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield private boolean mUseFocusDimmer; 144892181367d658f347d00ea5e091aa31f086b2a20Dake Gu private boolean mShadowEnabled = true; 1459240e796bc63422c28f2707840bd99c48573279bDake Gu private int mBrowseRowsFadingEdgeLength = -1; 1464f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout private boolean mRoundedCornersEnabled = true; 147bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout private HashMap<Presenter, Integer> mRecycledPoolSize = new HashMap<Presenter, Integer>(); 148b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout 1494cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout private static int sSelectedRowTopPadding; 1504cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout private static int sExpandedSelectedRowTopPadding; 1514cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout private static int sExpandedRowNoHovercardBottomPadding; 1524cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout 153b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout /** 154b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout * Constructs a ListRowPresenter with defaults. 15541ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield * Uses {@link FocusHighlight#ZOOM_FACTOR_MEDIUM} for focus zooming and 15641ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield * disabled dimming on focus. 157b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout */ 158b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout public ListRowPresenter() { 159739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout this(FocusHighlight.ZOOM_FACTOR_MEDIUM); 160b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout } 161b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout 162b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout /** 163b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout * Constructs a ListRowPresenter with the given parameters. 164b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout * 16541ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield * @param focusZoomFactor Controls the zoom factor used when an item view is focused. One of 166739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * {@link FocusHighlight#ZOOM_FACTOR_NONE}, 167739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * {@link FocusHighlight#ZOOM_FACTOR_SMALL}, 168575dc8a5a5c023aee0c0ec297a7d357685cf49e9Craig Stout * {@link FocusHighlight#ZOOM_FACTOR_XSMALL}, 169739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * {@link FocusHighlight#ZOOM_FACTOR_MEDIUM}, 170739e3805bf2785e6773aede5e2e1643f537305f9Craig Stout * {@link FocusHighlight#ZOOM_FACTOR_LARGE} 17141ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield * Dimming on focus defaults to disabled. 172b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout */ 17341ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield public ListRowPresenter(int focusZoomFactor) { 17441ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield this(focusZoomFactor, false); 17541ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield } 17641ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield 17741ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield /** 17841ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield * Constructs a ListRowPresenter with the given parameters. 17941ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield * 18041ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield * @param focusZoomFactor Controls the zoom factor used when an item view is focused. One of 18141ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield * {@link FocusHighlight#ZOOM_FACTOR_NONE}, 18241ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield * {@link FocusHighlight#ZOOM_FACTOR_SMALL}, 18341ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield * {@link FocusHighlight#ZOOM_FACTOR_XSMALL}, 18441ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield * {@link FocusHighlight#ZOOM_FACTOR_MEDIUM}, 18541ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield * {@link FocusHighlight#ZOOM_FACTOR_LARGE} 18641ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield * @param useFocusDimmer determines if the FocusHighlighter will use the dimmer 18741ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield */ 18841ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield public ListRowPresenter(int focusZoomFactor, boolean useFocusDimmer) { 18941ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield if (!FocusHighlightHelper.isValidZoomIndex(focusZoomFactor)) { 190575dc8a5a5c023aee0c0ec297a7d357685cf49e9Craig Stout throw new IllegalArgumentException("Unhandled zoom factor"); 191575dc8a5a5c023aee0c0ec297a7d357685cf49e9Craig Stout } 19241ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield mFocusZoomFactor = focusZoomFactor; 19341ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield mUseFocusDimmer = useFocusDimmer; 194b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout } 195b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout 196b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout /** 197f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout * Sets the row height for rows created by this Presenter. Rows 198a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn * created before calling this method will not be updated. 199a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn * 200f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout * @param rowHeight Row height in pixels, or WRAP_CONTENT, or 0 201f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout * to use the default height. 202a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn */ 203a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn public void setRowHeight(int rowHeight) { 204a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn mRowHeight = rowHeight; 205a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn } 206a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn 207a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn /** 208f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout * Returns the row height for list rows created by this Presenter. 209a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn */ 210a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn public int getRowHeight() { 211a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn return mRowHeight; 212a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn } 213a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn 214a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn /** 215f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout * Sets the expanded row height for rows created by this Presenter. 216f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout * If not set, expanded rows have the same height as unexpanded 217a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn * rows. 218a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn * 219f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout * @param rowHeight The row height in to use when the row is expanded, 220f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout * in pixels, or WRAP_CONTENT, or 0 to use the default. 221a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn */ 222a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn public void setExpandedRowHeight(int rowHeight) { 223a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn mExpandedRowHeight = rowHeight; 224a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn } 225a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn 226a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn /** 227f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout * Returns the expanded row height for rows created by this Presenter. 228a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn */ 229a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn public int getExpandedRowHeight() { 230f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout return mExpandedRowHeight != 0 ? mExpandedRowHeight : mRowHeight; 231a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn } 232a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn 233a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn /** 234b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout * Returns the zoom factor used for focus highlighting. 235b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout */ 23641ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield public final int getFocusZoomFactor() { 23741ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield return mFocusZoomFactor; 23841ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield } 239a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout 24041ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield /** 24141ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield * Returns the zoom factor used for focus highlighting. 24241ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield * @deprecated use {@link #getFocusZoomFactor} instead. 24341ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield */ 244a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout @Deprecated 245a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout public final int getZoomFactor() { 24641ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield return mFocusZoomFactor; 24741ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield } 24841ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield 24941ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield /** 25041ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield * Returns true if the focus dimmer is used for focus highlighting; false otherwise. 25141ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield */ 25241ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield public final boolean isFocusDimmerUsed() { 25341ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield return mUseFocusDimmer; 254b9e89a1544f8cf582f191184fb9b2a4f24e1fa5bCraig Stout } 25547520b68e50572a9775a662410c5aff8300c8784Craig Stout 256892181367d658f347d00ea5e091aa31f086b2a20Dake Gu private ItemBridgeAdapter.Wrapper mCardWrapper = new ItemBridgeAdapter.Wrapper() { 257892181367d658f347d00ea5e091aa31f086b2a20Dake Gu @Override 258892181367d658f347d00ea5e091aa31f086b2a20Dake Gu public View createWrapper(View root) { 259dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu ShadowOverlayContainer wrapper = new ShadowOverlayContainer(root.getContext()); 260892181367d658f347d00ea5e091aa31f086b2a20Dake Gu wrapper.setLayoutParams( 261892181367d658f347d00ea5e091aa31f086b2a20Dake Gu new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 262f4acd3cf076435ce836a6d4a9027b73ec3050defCraig Stout if (isUsingZOrder(root.getContext())) { 263f4acd3cf076435ce836a6d4a9027b73ec3050defCraig Stout wrapper.useDynamicShadow(); 264f4acd3cf076435ce836a6d4a9027b73ec3050defCraig Stout } else { 265f4acd3cf076435ce836a6d4a9027b73ec3050defCraig Stout wrapper.useStaticShadow(); 266f4acd3cf076435ce836a6d4a9027b73ec3050defCraig Stout } 2674f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout wrapper.initialize(needsDefaultShadow(), 2684f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout needsDefaultListSelectEffect(), 2694f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout areChildRoundedCornersEnabled()); 270892181367d658f347d00ea5e091aa31f086b2a20Dake Gu return wrapper; 271892181367d658f347d00ea5e091aa31f086b2a20Dake Gu } 272892181367d658f347d00ea5e091aa31f086b2a20Dake Gu @Override 273892181367d658f347d00ea5e091aa31f086b2a20Dake Gu public void wrap(View wrapper, View wrapped) { 274dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu ((ShadowOverlayContainer) wrapper).wrap(wrapped); 275892181367d658f347d00ea5e091aa31f086b2a20Dake Gu } 276892181367d658f347d00ea5e091aa31f086b2a20Dake Gu }; 277892181367d658f347d00ea5e091aa31f086b2a20Dake Gu 27847520b68e50572a9775a662410c5aff8300c8784Craig Stout @Override 27947520b68e50572a9775a662410c5aff8300c8784Craig Stout protected void initializeRowViewHolder(RowPresenter.ViewHolder holder) { 28047520b68e50572a9775a662410c5aff8300c8784Craig Stout super.initializeRowViewHolder(holder); 28147520b68e50572a9775a662410c5aff8300c8784Craig Stout final ViewHolder rowViewHolder = (ViewHolder) holder; 28271fddded48048acfa744ac352166770c91a1c2b1Dake Gu rowViewHolder.mItemBridgeAdapter = new ListRowPresenterItemBridgeAdapter(rowViewHolder); 2834f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout if (needsDefaultListSelectEffect() || needsDefaultShadow() 2844f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout || areChildRoundedCornersEnabled()) { 285892181367d658f347d00ea5e091aa31f086b2a20Dake Gu rowViewHolder.mItemBridgeAdapter.setWrapper(mCardWrapper); 286892181367d658f347d00ea5e091aa31f086b2a20Dake Gu } 2875870e4aca782a55d0e8f7650f06aec86080b2f88Craig Stout if (needsDefaultShadow()) { 288dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu ShadowOverlayContainer.prepareParentForShadow(rowViewHolder.mGridView); 289cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu } 29046e7de54775fc37dc51041629c79249e6dae3242Dake Gu FocusHighlightHelper.setupBrowseItemFocusHighlight(rowViewHolder.mItemBridgeAdapter, 29141ad8b4ffe5adbc5c8568d359786a67a4937964dJohn Butterfield mFocusZoomFactor, mUseFocusDimmer); 292f4acd3cf076435ce836a6d4a9027b73ec3050defCraig Stout rowViewHolder.mGridView.setFocusDrawingOrderEnabled( 293f4acd3cf076435ce836a6d4a9027b73ec3050defCraig Stout !isUsingZOrder(rowViewHolder.getGridView().getContext())); 29447520b68e50572a9775a662410c5aff8300c8784Craig Stout rowViewHolder.mGridView.setOnChildSelectedListener( 29547520b68e50572a9775a662410c5aff8300c8784Craig Stout new OnChildSelectedListener() { 29647520b68e50572a9775a662410c5aff8300c8784Craig Stout @Override 29747520b68e50572a9775a662410c5aff8300c8784Craig Stout public void onChildSelected(ViewGroup parent, View view, int position, long id) { 2980246318f27a905a31df5a8af445cfe67d31dfb68Dake Gu selectChildView(rowViewHolder, view, true); 29947520b68e50572a9775a662410c5aff8300c8784Craig Stout } 30047520b68e50572a9775a662410c5aff8300c8784Craig Stout }); 30160bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout rowViewHolder.mGridView.setOnUnhandledKeyListener( 30260bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout new BaseGridView.OnUnhandledKeyListener() { 30360bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout @Override 30460bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout public boolean onUnhandledKey(KeyEvent event) { 30560bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout if (rowViewHolder.getOnKeyListener() != null && 30660bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout rowViewHolder.getOnKeyListener().onKey( 30760bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout rowViewHolder.view, event.getKeyCode(), event)) { 30860bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout return true; 30960bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout } 31060bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout return false; 31147520b68e50572a9775a662410c5aff8300c8784Craig Stout } 31247520b68e50572a9775a662410c5aff8300c8784Craig Stout }); 31347520b68e50572a9775a662410c5aff8300c8784Craig Stout } 31447520b68e50572a9775a662410c5aff8300c8784Craig Stout 315cb13a318e577e14461eb008071dddf762847de42Dake Gu final boolean needsDefaultListSelectEffect() { 316cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu return isUsingDefaultListSelectEffect() && getSelectEffectEnabled(); 317cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu } 318cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu 31947520b68e50572a9775a662410c5aff8300c8784Craig Stout /** 320bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout * Sets the recycled pool size for the given presenter. 321bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout */ 322bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout public void setRecycledPoolSize(Presenter presenter, int size) { 323bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout mRecycledPoolSize.put(presenter, size); 324bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout } 325bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout 326bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout /** 327bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout * Returns the recycled pool size for the given presenter. 328bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout */ 329bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout public int getRecycledPoolSize(Presenter presenter) { 330bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout return mRecycledPoolSize.containsKey(presenter) ? mRecycledPoolSize.get(presenter) : 331bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout DEFAULT_RECYCLED_POOL_SIZE; 332bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout } 333bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout 334bb370eee93bfe84a6e14be0e8476f48c32e2dcb0Craig Stout /** 335a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * Sets the {@link PresenterSelector} used for showing a select object in a hover card. 33647520b68e50572a9775a662410c5aff8300c8784Craig Stout */ 33747520b68e50572a9775a662410c5aff8300c8784Craig Stout public final void setHoverCardPresenterSelector(PresenterSelector selector) { 33847520b68e50572a9775a662410c5aff8300c8784Craig Stout mHoverCardPresenterSelector = selector; 33947520b68e50572a9775a662410c5aff8300c8784Craig Stout } 34047520b68e50572a9775a662410c5aff8300c8784Craig Stout 34147520b68e50572a9775a662410c5aff8300c8784Craig Stout /** 342a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * Returns the {@link PresenterSelector} used for showing a select object in a hover card. 34347520b68e50572a9775a662410c5aff8300c8784Craig Stout */ 34447520b68e50572a9775a662410c5aff8300c8784Craig Stout public final PresenterSelector getHoverCardPresenterSelector() { 34547520b68e50572a9775a662410c5aff8300c8784Craig Stout return mHoverCardPresenterSelector; 34647520b68e50572a9775a662410c5aff8300c8784Craig Stout } 34747520b68e50572a9775a662410c5aff8300c8784Craig Stout 34847520b68e50572a9775a662410c5aff8300c8784Craig Stout /* 34947520b68e50572a9775a662410c5aff8300c8784Craig Stout * Perform operations when a child of horizontal grid view is selected. 35047520b68e50572a9775a662410c5aff8300c8784Craig Stout */ 3510246318f27a905a31df5a8af445cfe67d31dfb68Dake Gu private void selectChildView(ViewHolder rowViewHolder, View view, boolean fireEvent) { 35247520b68e50572a9775a662410c5aff8300c8784Craig Stout if (view != null) { 3533173fdc69a928880a271036570c235f874b86f65butterfield@google.com if (rowViewHolder.mExpanded && rowViewHolder.mSelected) { 3543173fdc69a928880a271036570c235f874b86f65butterfield@google.com ItemBridgeAdapter.ViewHolder ibh = (ItemBridgeAdapter.ViewHolder) 3553173fdc69a928880a271036570c235f874b86f65butterfield@google.com rowViewHolder.mGridView.getChildViewHolder(view); 3563173fdc69a928880a271036570c235f874b86f65butterfield@google.com 3573173fdc69a928880a271036570c235f874b86f65butterfield@google.com if (mHoverCardPresenterSelector != null) { 3583a5038bd0fefa5628a31a21422bf2126c53472a9Craig Stout rowViewHolder.mHoverCardViewSwitcher.select( 3593a5038bd0fefa5628a31a21422bf2126c53472a9Craig Stout rowViewHolder.mGridView, view, ibh.mItem); 3603173fdc69a928880a271036570c235f874b86f65butterfield@google.com } 3610246318f27a905a31df5a8af445cfe67d31dfb68Dake Gu if (fireEvent && rowViewHolder.getOnItemViewSelectedListener() != null) { 3623a5038bd0fefa5628a31a21422bf2126c53472a9Craig Stout rowViewHolder.getOnItemViewSelectedListener().onItemSelected( 3633a5038bd0fefa5628a31a21422bf2126c53472a9Craig Stout ibh.mHolder, ibh.mItem, rowViewHolder, rowViewHolder.mRow); 3643173fdc69a928880a271036570c235f874b86f65butterfield@google.com } 3653173fdc69a928880a271036570c235f874b86f65butterfield@google.com } 3663173fdc69a928880a271036570c235f874b86f65butterfield@google.com } else { 36747520b68e50572a9775a662410c5aff8300c8784Craig Stout if (mHoverCardPresenterSelector != null) { 36847520b68e50572a9775a662410c5aff8300c8784Craig Stout rowViewHolder.mHoverCardViewSwitcher.unselect(); 36947520b68e50572a9775a662410c5aff8300c8784Craig Stout } 3700246318f27a905a31df5a8af445cfe67d31dfb68Dake Gu if (fireEvent && rowViewHolder.getOnItemViewSelectedListener() != null) { 3713a5038bd0fefa5628a31a21422bf2126c53472a9Craig Stout rowViewHolder.getOnItemViewSelectedListener().onItemSelected( 3723a5038bd0fefa5628a31a21422bf2126c53472a9Craig Stout null, null, rowViewHolder, rowViewHolder.mRow); 3739de363b8db05106b03d115c266859fe200d41db7Dake Gu } 37447520b68e50572a9775a662410c5aff8300c8784Craig Stout } 37547520b68e50572a9775a662410c5aff8300c8784Craig Stout } 37647520b68e50572a9775a662410c5aff8300c8784Craig Stout 3774cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout private static void initStatics(Context context) { 3784cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout if (sSelectedRowTopPadding == 0) { 3794cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout sSelectedRowTopPadding = context.getResources().getDimensionPixelSize( 3804cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout R.dimen.lb_browse_selected_row_top_padding); 3814cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout sExpandedSelectedRowTopPadding = context.getResources().getDimensionPixelSize( 3824cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout R.dimen.lb_browse_expanded_selected_row_top_padding); 3834cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout sExpandedRowNoHovercardBottomPadding = context.getResources().getDimensionPixelSize( 3844cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout R.dimen.lb_browse_expanded_row_no_hovercard_bottom_padding); 3854cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout } 3864cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout } 3874cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout 3884cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout private int getSpaceUnderBaseline(ListRowPresenter.ViewHolder vh) { 3894cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout RowHeaderPresenter.ViewHolder headerViewHolder = vh.getHeaderViewHolder(); 3904cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout if (headerViewHolder != null) { 3914cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout if (getHeaderPresenter() != null) { 3924cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout return getHeaderPresenter().getSpaceUnderBaseline(headerViewHolder); 3934cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout } 3944cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout return headerViewHolder.view.getPaddingBottom(); 3954cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout } 3964cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout return 0; 3974cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout } 3984cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout 3994cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout private void setVerticalPadding(ListRowPresenter.ViewHolder vh) { 4004cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout int paddingTop, paddingBottom; 4013146269a82645438b55a41c679047e3be36e65dfCraig Stout // Note: sufficient bottom padding needed for card shadows. 4024cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout if (vh.isExpanded()) { 4034cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout int headerSpaceUnderBaseline = getSpaceUnderBaseline(vh); 4044cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout if (DEBUG) Log.v(TAG, "headerSpaceUnderBaseline " + headerSpaceUnderBaseline); 4054cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout paddingTop = (vh.isSelected() ? sExpandedSelectedRowTopPadding : vh.mPaddingTop) - 4064cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout headerSpaceUnderBaseline; 4074cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout paddingBottom = mHoverCardPresenterSelector == null ? 4084cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout sExpandedRowNoHovercardBottomPadding : vh.mPaddingBottom; 4094cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout } else if (vh.isSelected()) { 4103146269a82645438b55a41c679047e3be36e65dfCraig Stout paddingTop = sSelectedRowTopPadding - vh.mPaddingBottom; 4113146269a82645438b55a41c679047e3be36e65dfCraig Stout paddingBottom = sSelectedRowTopPadding; 4124cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout } else { 4133146269a82645438b55a41c679047e3be36e65dfCraig Stout paddingTop = 0; 4143146269a82645438b55a41c679047e3be36e65dfCraig Stout paddingBottom = vh.mPaddingBottom; 4154cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout } 4164cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout vh.getGridView().setPadding(vh.mPaddingLeft, paddingTop, vh.mPaddingRight, 4174cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout paddingBottom); 4184cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout } 4194cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout 42047520b68e50572a9775a662410c5aff8300c8784Craig Stout @Override 42147520b68e50572a9775a662410c5aff8300c8784Craig Stout protected RowPresenter.ViewHolder createRowViewHolder(ViewGroup parent) { 4224cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout initStatics(parent.getContext()); 423cb13a318e577e14461eb008071dddf762847de42Dake Gu ListRowView rowView = new ListRowView(parent.getContext()); 4249240e796bc63422c28f2707840bd99c48573279bDake Gu setupFadingEffect(rowView); 425f272f7533fcb5aba341e9ab2f4ff0421d668a8caCraig Stout if (mRowHeight != 0) { 426a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn rowView.getGridView().setRowHeight(mRowHeight); 427a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn } 42847520b68e50572a9775a662410c5aff8300c8784Craig Stout return new ViewHolder(rowView, rowView.getGridView(), this); 42947520b68e50572a9775a662410c5aff8300c8784Craig Stout } 43047520b68e50572a9775a662410c5aff8300c8784Craig Stout 431cb04695965b44b6ff633a773426df286d3bfaad9John Butterfield /** 432cb04695965b44b6ff633a773426df286d3bfaad9John Butterfield * Dispatch item selected event using current selected item in the {@link HorizontalGridView}. 433cb04695965b44b6ff633a773426df286d3bfaad9John Butterfield * The method should only be called from onRowViewSelected(). 434cb04695965b44b6ff633a773426df286d3bfaad9John Butterfield */ 435cb04695965b44b6ff633a773426df286d3bfaad9John Butterfield @Override 436cb04695965b44b6ff633a773426df286d3bfaad9John Butterfield protected void dispatchItemSelectedListener(RowPresenter.ViewHolder holder, boolean selected) { 437cb04695965b44b6ff633a773426df286d3bfaad9John Butterfield ViewHolder vh = (ViewHolder)holder; 438cb04695965b44b6ff633a773426df286d3bfaad9John Butterfield ItemBridgeAdapter.ViewHolder itemViewHolder = (ItemBridgeAdapter.ViewHolder) 439cb04695965b44b6ff633a773426df286d3bfaad9John Butterfield vh.mGridView.findViewHolderForPosition(vh.mGridView.getSelectedPosition()); 440cb04695965b44b6ff633a773426df286d3bfaad9John Butterfield if (itemViewHolder == null) { 441cb04695965b44b6ff633a773426df286d3bfaad9John Butterfield super.dispatchItemSelectedListener(holder, selected); 442cb04695965b44b6ff633a773426df286d3bfaad9John Butterfield return; 443cb04695965b44b6ff633a773426df286d3bfaad9John Butterfield } 444cb04695965b44b6ff633a773426df286d3bfaad9John Butterfield 445cb04695965b44b6ff633a773426df286d3bfaad9John Butterfield if (selected) { 4463a5038bd0fefa5628a31a21422bf2126c53472a9Craig Stout if (holder.getOnItemViewSelectedListener() != null) { 4473a5038bd0fefa5628a31a21422bf2126c53472a9Craig Stout holder.getOnItemViewSelectedListener().onItemSelected( 448cb04695965b44b6ff633a773426df286d3bfaad9John Butterfield itemViewHolder.getViewHolder(), itemViewHolder.mItem, vh, vh.getRow()); 449cb04695965b44b6ff633a773426df286d3bfaad9John Butterfield } 450cb04695965b44b6ff633a773426df286d3bfaad9John Butterfield } 451cb04695965b44b6ff633a773426df286d3bfaad9John Butterfield } 452cb04695965b44b6ff633a773426df286d3bfaad9John Butterfield 45347520b68e50572a9775a662410c5aff8300c8784Craig Stout @Override 45447520b68e50572a9775a662410c5aff8300c8784Craig Stout protected void onRowViewSelected(RowPresenter.ViewHolder holder, boolean selected) { 4552f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu super.onRowViewSelected(holder, selected); 4564cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout ViewHolder vh = (ViewHolder) holder; 4574cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout setVerticalPadding(vh); 4584cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout updateFooterViewSwitcher(vh); 45947520b68e50572a9775a662410c5aff8300c8784Craig Stout } 46047520b68e50572a9775a662410c5aff8300c8784Craig Stout 46147520b68e50572a9775a662410c5aff8300c8784Craig Stout /* 46247520b68e50572a9775a662410c5aff8300c8784Craig Stout * Show or hide hover card when row selection or expanded state is changed. 46347520b68e50572a9775a662410c5aff8300c8784Craig Stout */ 46447520b68e50572a9775a662410c5aff8300c8784Craig Stout private void updateFooterViewSwitcher(ViewHolder vh) { 46547520b68e50572a9775a662410c5aff8300c8784Craig Stout if (vh.mExpanded && vh.mSelected) { 46647520b68e50572a9775a662410c5aff8300c8784Craig Stout if (mHoverCardPresenterSelector != null) { 46747520b68e50572a9775a662410c5aff8300c8784Craig Stout vh.mHoverCardViewSwitcher.init((ViewGroup) vh.view, 46847520b68e50572a9775a662410c5aff8300c8784Craig Stout mHoverCardPresenterSelector); 46947520b68e50572a9775a662410c5aff8300c8784Craig Stout } 47002e411c2c69d20aab138f1a162a24ea650eff7a1Dake Gu ItemBridgeAdapter.ViewHolder ibh = (ItemBridgeAdapter.ViewHolder) 47102e411c2c69d20aab138f1a162a24ea650eff7a1Dake Gu vh.mGridView.findViewHolderForPosition( 47202e411c2c69d20aab138f1a162a24ea650eff7a1Dake Gu vh.mGridView.getSelectedPosition()); 4730246318f27a905a31df5a8af445cfe67d31dfb68Dake Gu selectChildView(vh, ibh == null ? null : ibh.itemView, false); 47447520b68e50572a9775a662410c5aff8300c8784Craig Stout } else { 47547520b68e50572a9775a662410c5aff8300c8784Craig Stout if (mHoverCardPresenterSelector != null) { 4762f97594742886d045ca1ce409ebc6e6e780452f6Dake Gu vh.mHoverCardViewSwitcher.unselect(); 47747520b68e50572a9775a662410c5aff8300c8784Craig Stout } 47847520b68e50572a9775a662410c5aff8300c8784Craig Stout } 47947520b68e50572a9775a662410c5aff8300c8784Craig Stout } 48047520b68e50572a9775a662410c5aff8300c8784Craig Stout 4819240e796bc63422c28f2707840bd99c48573279bDake Gu private void setupFadingEffect(ListRowView rowView) { 4829240e796bc63422c28f2707840bd99c48573279bDake Gu // content is completely faded at 1/2 padding of left, fading length is 1/2 of padding. 4839240e796bc63422c28f2707840bd99c48573279bDake Gu HorizontalGridView gridView = rowView.getGridView(); 4849240e796bc63422c28f2707840bd99c48573279bDake Gu if (mBrowseRowsFadingEdgeLength < 0) { 4859240e796bc63422c28f2707840bd99c48573279bDake Gu TypedArray ta = gridView.getContext() 4869240e796bc63422c28f2707840bd99c48573279bDake Gu .obtainStyledAttributes(R.styleable.LeanbackTheme); 4879240e796bc63422c28f2707840bd99c48573279bDake Gu mBrowseRowsFadingEdgeLength = (int) ta.getDimension( 4889240e796bc63422c28f2707840bd99c48573279bDake Gu R.styleable.LeanbackTheme_browseRowsFadingEdgeLength, 0); 4899240e796bc63422c28f2707840bd99c48573279bDake Gu ta.recycle(); 49047520b68e50572a9775a662410c5aff8300c8784Craig Stout } 4919240e796bc63422c28f2707840bd99c48573279bDake Gu gridView.setFadingLeftEdgeLength(mBrowseRowsFadingEdgeLength); 49247520b68e50572a9775a662410c5aff8300c8784Craig Stout } 49347520b68e50572a9775a662410c5aff8300c8784Craig Stout 49447520b68e50572a9775a662410c5aff8300c8784Craig Stout @Override 49547520b68e50572a9775a662410c5aff8300c8784Craig Stout protected void onRowViewExpanded(RowPresenter.ViewHolder holder, boolean expanded) { 49647520b68e50572a9775a662410c5aff8300c8784Craig Stout super.onRowViewExpanded(holder, expanded); 49747520b68e50572a9775a662410c5aff8300c8784Craig Stout ViewHolder vh = (ViewHolder) holder; 498a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn if (getRowHeight() != getExpandedRowHeight()) { 499a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn int newHeight = expanded ? getExpandedRowHeight() : getRowHeight(); 500a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn vh.getGridView().setRowHeight(newHeight); 501a4560456facaa3dd341a7ab2f372f655d46f7ee6Tim Kilbourn } 5024cd4cce277571385f4d1a56d5348578c38368cbeCraig Stout setVerticalPadding(vh); 50347520b68e50572a9775a662410c5aff8300c8784Craig Stout updateFooterViewSwitcher(vh); 50447520b68e50572a9775a662410c5aff8300c8784Craig Stout } 50547520b68e50572a9775a662410c5aff8300c8784Craig Stout 50647520b68e50572a9775a662410c5aff8300c8784Craig Stout @Override 507cb13a318e577e14461eb008071dddf762847de42Dake Gu protected void onBindRowViewHolder(RowPresenter.ViewHolder holder, Object item) { 508cb13a318e577e14461eb008071dddf762847de42Dake Gu super.onBindRowViewHolder(holder, item); 509cb13a318e577e14461eb008071dddf762847de42Dake Gu ViewHolder vh = (ViewHolder) holder; 51047520b68e50572a9775a662410c5aff8300c8784Craig Stout ListRow rowItem = (ListRow) item; 51147520b68e50572a9775a662410c5aff8300c8784Craig Stout vh.mItemBridgeAdapter.setAdapter(rowItem.getAdapter()); 51247520b68e50572a9775a662410c5aff8300c8784Craig Stout vh.mGridView.setAdapter(vh.mItemBridgeAdapter); 51347520b68e50572a9775a662410c5aff8300c8784Craig Stout } 51447520b68e50572a9775a662410c5aff8300c8784Craig Stout 51547520b68e50572a9775a662410c5aff8300c8784Craig Stout @Override 516cb13a318e577e14461eb008071dddf762847de42Dake Gu protected void onUnbindRowViewHolder(RowPresenter.ViewHolder holder) { 5175358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout ViewHolder vh = (ViewHolder) holder; 5185358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout vh.mGridView.setAdapter(null); 5195358b0ca6ed795892bd097fdf15d41fb6b1a03d2Craig Stout vh.mItemBridgeAdapter.clear(); 520cb13a318e577e14461eb008071dddf762847de42Dake Gu super.onUnbindRowViewHolder(holder); 52147520b68e50572a9775a662410c5aff8300c8784Craig Stout } 52247520b68e50572a9775a662410c5aff8300c8784Craig Stout 523cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu /** 524cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu * ListRowPresenter overrides the default select effect of {@link RowPresenter} 525cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu * and return false. 526cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu */ 527cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu @Override 528cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu public final boolean isUsingDefaultSelectEffect() { 529cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu return false; 530cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu } 531cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu 532cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu /** 533cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu * Returns true so that default select effect is applied to each individual 534cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu * child of {@link HorizontalGridView}. Subclass may return false to disable 535cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu * the default implementation. 536cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu * @see #onSelectLevelChanged(RowPresenter.ViewHolder) 537cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu */ 538cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu public boolean isUsingDefaultListSelectEffect() { 539cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu return true; 540cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu } 541cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu 542cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu /** 543dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu * Returns true if SDK >= 18, where default shadow 544892181367d658f347d00ea5e091aa31f086b2a20Dake Gu * is applied to each individual child of {@link HorizontalGridView}. 545892181367d658f347d00ea5e091aa31f086b2a20Dake Gu * Subclass may return false to disable. 546892181367d658f347d00ea5e091aa31f086b2a20Dake Gu */ 547892181367d658f347d00ea5e091aa31f086b2a20Dake Gu public boolean isUsingDefaultShadow() { 548dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu return ShadowOverlayContainer.supportsShadow(); 549892181367d658f347d00ea5e091aa31f086b2a20Dake Gu } 550892181367d658f347d00ea5e091aa31f086b2a20Dake Gu 551892181367d658f347d00ea5e091aa31f086b2a20Dake Gu /** 5520fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu * Returns true if SDK >= L, where Z shadow is enabled so that Z order is enabled 5530fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu * on each child of horizontal list. If subclass returns false in isUsingDefaultShadow() 5540fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu * and does not use Z-shadow on SDK >= L, it should override isUsingZOrder() return false. 5550fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu */ 556f4acd3cf076435ce836a6d4a9027b73ec3050defCraig Stout public boolean isUsingZOrder(Context context) { 557f4acd3cf076435ce836a6d4a9027b73ec3050defCraig Stout return ShadowOverlayContainer.supportsDynamicShadow() && 558f4acd3cf076435ce836a6d4a9027b73ec3050defCraig Stout !Settings.getInstance(context).preferStaticShadows(); 5590fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu } 5600fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu 5610fcad32410ad29031630bb9cc2da35d33a4aa906Dake Gu /** 562a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * Enables or disables child shadow. 563892181367d658f347d00ea5e091aa31f086b2a20Dake Gu * This is not only for enable/disable default shadow implementation but also subclass must 564892181367d658f347d00ea5e091aa31f086b2a20Dake Gu * respect this flag. 565892181367d658f347d00ea5e091aa31f086b2a20Dake Gu */ 566892181367d658f347d00ea5e091aa31f086b2a20Dake Gu public final void setShadowEnabled(boolean enabled) { 567892181367d658f347d00ea5e091aa31f086b2a20Dake Gu mShadowEnabled = enabled; 568892181367d658f347d00ea5e091aa31f086b2a20Dake Gu } 569892181367d658f347d00ea5e091aa31f086b2a20Dake Gu 570892181367d658f347d00ea5e091aa31f086b2a20Dake Gu /** 571892181367d658f347d00ea5e091aa31f086b2a20Dake Gu * Returns true if child shadow is enabled. 572892181367d658f347d00ea5e091aa31f086b2a20Dake Gu * This is not only for enable/disable default shadow implementation but also subclass must 573892181367d658f347d00ea5e091aa31f086b2a20Dake Gu * respect this flag. 574892181367d658f347d00ea5e091aa31f086b2a20Dake Gu */ 575892181367d658f347d00ea5e091aa31f086b2a20Dake Gu public final boolean getShadowEnabled() { 576892181367d658f347d00ea5e091aa31f086b2a20Dake Gu return mShadowEnabled; 577892181367d658f347d00ea5e091aa31f086b2a20Dake Gu } 578892181367d658f347d00ea5e091aa31f086b2a20Dake Gu 5794f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout /** 5804f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout * Enables or disabled rounded corners on children of this row. 5814f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout * Supported on Android SDK >= L. 5824f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout */ 5834f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout public final void enableChildRoundedCorners(boolean enable) { 5844f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout mRoundedCornersEnabled = enable; 5854f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout } 5864f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout 5874f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout /** 5884f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout * Returns true if rounded corners are enabled for children of this row. 5894f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout */ 5904f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout public final boolean areChildRoundedCornersEnabled() { 5914f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout return mRoundedCornersEnabled; 5924f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout } 5934f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout 594892181367d658f347d00ea5e091aa31f086b2a20Dake Gu final boolean needsDefaultShadow() { 595892181367d658f347d00ea5e091aa31f086b2a20Dake Gu return isUsingDefaultShadow() && getShadowEnabled(); 596892181367d658f347d00ea5e091aa31f086b2a20Dake Gu } 597892181367d658f347d00ea5e091aa31f086b2a20Dake Gu 598892181367d658f347d00ea5e091aa31f086b2a20Dake Gu @Override 599892181367d658f347d00ea5e091aa31f086b2a20Dake Gu public boolean canDrawOutOfBounds() { 600892181367d658f347d00ea5e091aa31f086b2a20Dake Gu return needsDefaultShadow(); 601892181367d658f347d00ea5e091aa31f086b2a20Dake Gu } 602892181367d658f347d00ea5e091aa31f086b2a20Dake Gu 603892181367d658f347d00ea5e091aa31f086b2a20Dake Gu /** 604cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu * Applies select level to header and draw a default color dim over each child 605cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu * of {@link HorizontalGridView}. 606cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu * <p> 607cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu * Subclass may override this method. A subclass 608cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu * needs to call super.onSelectLevelChanged() for applying header select level 609cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu * and optionally applying a default select level to each child view of 610cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu * {@link HorizontalGridView} if {@link #isUsingDefaultListSelectEffect()} 611cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu * is true. Subclass may override {@link #isUsingDefaultListSelectEffect()} to return 612cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu * false and deal with the individual item select level by itself. 613cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu * </p> 614cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu */ 615cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu @Override 616cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu protected void onSelectLevelChanged(RowPresenter.ViewHolder holder) { 617cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu super.onSelectLevelChanged(holder); 618cb13a318e577e14461eb008071dddf762847de42Dake Gu if (needsDefaultListSelectEffect()) { 619cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu ViewHolder vh = (ViewHolder) holder; 620892181367d658f347d00ea5e091aa31f086b2a20Dake Gu int dimmedColor = vh.mColorDimmer.getPaint().getColor(); 621892181367d658f347d00ea5e091aa31f086b2a20Dake Gu for (int i = 0, count = vh.mGridView.getChildCount(); i < count; i++) { 622dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu ShadowOverlayContainer wrapper = (ShadowOverlayContainer) vh.mGridView.getChildAt(i); 623dfd01bbadc107b6b3b2081ddb0236128c425f380Dake Gu wrapper.setOverlayColor(dimmedColor); 624cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu } 6259240e796bc63422c28f2707840bd99c48573279bDake Gu if (vh.mGridView.getFadingLeftEdge()) { 6269240e796bc63422c28f2707840bd99c48573279bDake Gu vh.mGridView.invalidate(); 6279240e796bc63422c28f2707840bd99c48573279bDake Gu } 628cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu } 629cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu } 630cf94c5fa8ae8edb7e26a623133207415ceeed187Dake Gu 631709bb7083a089e788d84ffa81f2c4f60a1bc8cf2Dake Gu @Override 632709bb7083a089e788d84ffa81f2c4f60a1bc8cf2Dake Gu public void freeze(RowPresenter.ViewHolder holder, boolean freeze) { 633709bb7083a089e788d84ffa81f2c4f60a1bc8cf2Dake Gu ViewHolder vh = (ViewHolder) holder; 634709bb7083a089e788d84ffa81f2c4f60a1bc8cf2Dake Gu vh.mGridView.setScrollEnabled(!freeze); 635709bb7083a089e788d84ffa81f2c4f60a1bc8cf2Dake Gu } 636709bb7083a089e788d84ffa81f2c4f60a1bc8cf2Dake Gu 637c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu @Override 6383f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu public void setEntranceTransitionState(RowPresenter.ViewHolder holder, 6393f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu boolean afterEntrance) { 6403f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu super.setEntranceTransitionState(holder, afterEntrance); 641c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu ((ViewHolder) holder).mGridView.setChildrenVisibility( 6423f0f3eb255bde49549a77c0b5d252decaa2a0202Dake Gu afterEntrance? View.VISIBLE : View.INVISIBLE); 643c04ca1b14c5bf9ecac80fc53d3f28a5a7fdd4e77Dake Gu } 64447520b68e50572a9775a662410c5aff8300c8784Craig Stout} 645