1a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn/* 2a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn * Copyright (C) 2014 The Android Open Source Project 3a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn * 4a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn * in compliance with the License. You may obtain a copy of the License at 6a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn * 7a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn * http://www.apache.org/licenses/LICENSE-2.0 8a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn * 9a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn * Unless required by applicable law or agreed to in writing, software distributed under the License 10a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn * or implied. See the License for the specific language governing permissions and limitations under 12a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn * the License. 13a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn */ 14ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.leanback.widget; 15a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn 164121f22713bbed467a977ec0d867ef53989ff374Dake Guimport android.app.Activity; 17d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stoutimport android.content.Context; 18d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stoutimport android.graphics.Color; 1909d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stoutimport android.graphics.drawable.ColorDrawable; 203103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport android.graphics.drawable.Drawable; 21d825ff3727407a154a35e20b3a9adc79e57879b9Dake Guimport android.os.Handler; 222e0c922430f8c285b4325da52d69c09451069c93Craig Stoutimport android.util.Log; 23d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stoutimport android.util.TypedValue; 2460bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stoutimport android.view.KeyEvent; 25a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournimport android.view.LayoutInflater; 26a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournimport android.view.View; 27a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournimport android.view.ViewGroup; 28a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournimport android.widget.FrameLayout; 29a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournimport android.widget.ImageView; 30a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn 318619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.annotation.ColorInt; 328619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.leanback.R; 338619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.recyclerview.widget.RecyclerView; 348619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikas 35a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn/** 36a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * Renders a {@link DetailsOverviewRow} to display an overview of an item. 37a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * Typically this row will be the first row in a fragment 38ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * such as the {@link androidx.leanback.app.DetailsFragment 39a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * DetailsFragment}. The View created by the DetailsOverviewRowPresenter is made in three parts: 4018c8048f17940359b8bce99cb46d24337bff8997Dake Gu * ImageView on the left, action list view on the bottom and a customizable detailed 4118c8048f17940359b8bce99cb46d24337bff8997Dake Gu * description view on the right. 42a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn * 4318c8048f17940359b8bce99cb46d24337bff8997Dake Gu * <p>The detailed description is rendered using a {@link Presenter} passed in 44a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * {@link #DetailsOverviewRowPresenter(Presenter)}. Typically this will be an instance of 45a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * {@link AbstractDetailsDescriptionPresenter}. The application can access the 46a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * detailed description ViewHolder from {@link ViewHolder#mDetailsDescriptionViewHolder}. 4718c8048f17940359b8bce99cb46d24337bff8997Dake Gu * </p> 4818c8048f17940359b8bce99cb46d24337bff8997Dake Gu * 4918c8048f17940359b8bce99cb46d24337bff8997Dake Gu * <p> 5018c8048f17940359b8bce99cb46d24337bff8997Dake Gu * To participate in activity transition, call {@link #setSharedElementEnterTransition(Activity, 5118c8048f17940359b8bce99cb46d24337bff8997Dake Gu * String)} during Activity's onCreate(). 5218c8048f17940359b8bce99cb46d24337bff8997Dake Gu * </p> 5318c8048f17940359b8bce99cb46d24337bff8997Dake Gu * 5418c8048f17940359b8bce99cb46d24337bff8997Dake Gu * <p> 5518c8048f17940359b8bce99cb46d24337bff8997Dake Gu * Because transition support and layout are fully controlled by DetailsOverviewRowPresenter, 5618c8048f17940359b8bce99cb46d24337bff8997Dake Gu * developer can not override DetailsOverviewRowPresenter.ViewHolder for adding/replacing views 57a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * of DetailsOverviewRowPresenter. If further customization is required beyond replacing 58a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * the detailed description, the application should create a new row presenter class. 5918c8048f17940359b8bce99cb46d24337bff8997Dake Gu * </p> 600246318f27a905a31df5a8af445cfe67d31dfb68Dake Gu * @deprecated Use {@link FullWidthDetailsOverviewRowPresenter} 61a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn */ 620246318f27a905a31df5a8af445cfe67d31dfb68Dake Gu@Deprecated 63a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournpublic class DetailsOverviewRowPresenter extends RowPresenter { 64a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn 6560e00f895b6f4dd25f181f377adf98e0715be4b6Dake Gu static final String TAG = "DetailsOverviewRowP"; 6699ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas static final boolean DEBUG = false; 67a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn 682e0c922430f8c285b4325da52d69c09451069c93Craig Stout private static final int MORE_ACTIONS_FADE_MS = 100; 69d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu private static final long DEFAULT_TIMEOUT = 5000; 702e0c922430f8c285b4325da52d69c09451069c93Craig Stout 7171fddded48048acfa744ac352166770c91a1c2b1Dake Gu class ActionsItemBridgeAdapter extends ItemBridgeAdapter { 7271fddded48048acfa744ac352166770c91a1c2b1Dake Gu DetailsOverviewRowPresenter.ViewHolder mViewHolder; 7371fddded48048acfa744ac352166770c91a1c2b1Dake Gu 7471fddded48048acfa744ac352166770c91a1c2b1Dake Gu ActionsItemBridgeAdapter(DetailsOverviewRowPresenter.ViewHolder viewHolder) { 7571fddded48048acfa744ac352166770c91a1c2b1Dake Gu mViewHolder = viewHolder; 7671fddded48048acfa744ac352166770c91a1c2b1Dake Gu } 7771fddded48048acfa744ac352166770c91a1c2b1Dake Gu 7871fddded48048acfa744ac352166770c91a1c2b1Dake Gu @Override 7971fddded48048acfa744ac352166770c91a1c2b1Dake Gu public void onBind(final ItemBridgeAdapter.ViewHolder ibvh) { 803103f63e99d47573823957f7aa34308555873221Aurimas Liutikas if (mViewHolder.getOnItemViewClickedListener() != null 813103f63e99d47573823957f7aa34308555873221Aurimas Liutikas || mActionClickedListener != null) { 8271fddded48048acfa744ac352166770c91a1c2b1Dake Gu ibvh.getPresenter().setOnClickListener( 8371fddded48048acfa744ac352166770c91a1c2b1Dake Gu ibvh.getViewHolder(), new View.OnClickListener() { 8471fddded48048acfa744ac352166770c91a1c2b1Dake Gu @Override 8571fddded48048acfa744ac352166770c91a1c2b1Dake Gu public void onClick(View v) { 863a5038bd0fefa5628a31a21422bf2126c53472a9Craig Stout if (mViewHolder.getOnItemViewClickedListener() != null) { 873a5038bd0fefa5628a31a21422bf2126c53472a9Craig Stout mViewHolder.getOnItemViewClickedListener().onItemClicked( 8871fddded48048acfa744ac352166770c91a1c2b1Dake Gu ibvh.getViewHolder(), ibvh.getItem(), 8971fddded48048acfa744ac352166770c91a1c2b1Dake Gu mViewHolder, mViewHolder.getRow()); 9071fddded48048acfa744ac352166770c91a1c2b1Dake Gu } 9171fddded48048acfa744ac352166770c91a1c2b1Dake Gu if (mActionClickedListener != null) { 9271fddded48048acfa744ac352166770c91a1c2b1Dake Gu mActionClickedListener.onActionClicked((Action) ibvh.getItem()); 9371fddded48048acfa744ac352166770c91a1c2b1Dake Gu } 9471fddded48048acfa744ac352166770c91a1c2b1Dake Gu } 9571fddded48048acfa744ac352166770c91a1c2b1Dake Gu }); 9671fddded48048acfa744ac352166770c91a1c2b1Dake Gu } 9771fddded48048acfa744ac352166770c91a1c2b1Dake Gu } 9871fddded48048acfa744ac352166770c91a1c2b1Dake Gu @Override 9971fddded48048acfa744ac352166770c91a1c2b1Dake Gu public void onUnbind(final ItemBridgeAdapter.ViewHolder ibvh) { 1003103f63e99d47573823957f7aa34308555873221Aurimas Liutikas if (mViewHolder.getOnItemViewClickedListener() != null 1013103f63e99d47573823957f7aa34308555873221Aurimas Liutikas || mActionClickedListener != null) { 10271fddded48048acfa744ac352166770c91a1c2b1Dake Gu ibvh.getPresenter().setOnClickListener(ibvh.getViewHolder(), null); 10371fddded48048acfa744ac352166770c91a1c2b1Dake Gu } 10471fddded48048acfa744ac352166770c91a1c2b1Dake Gu } 10571fddded48048acfa744ac352166770c91a1c2b1Dake Gu @Override 10671fddded48048acfa744ac352166770c91a1c2b1Dake Gu public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder viewHolder) { 10771fddded48048acfa744ac352166770c91a1c2b1Dake Gu // Remove first to ensure we don't add ourselves more than once. 10871fddded48048acfa744ac352166770c91a1c2b1Dake Gu viewHolder.itemView.removeOnLayoutChangeListener(mViewHolder.mLayoutChangeListener); 10971fddded48048acfa744ac352166770c91a1c2b1Dake Gu viewHolder.itemView.addOnLayoutChangeListener(mViewHolder.mLayoutChangeListener); 11071fddded48048acfa744ac352166770c91a1c2b1Dake Gu } 11171fddded48048acfa744ac352166770c91a1c2b1Dake Gu @Override 11271fddded48048acfa744ac352166770c91a1c2b1Dake Gu public void onDetachedFromWindow(ItemBridgeAdapter.ViewHolder viewHolder) { 11371fddded48048acfa744ac352166770c91a1c2b1Dake Gu viewHolder.itemView.removeOnLayoutChangeListener(mViewHolder.mLayoutChangeListener); 11471fddded48048acfa744ac352166770c91a1c2b1Dake Gu mViewHolder.checkFirstAndLastPosition(false); 11571fddded48048acfa744ac352166770c91a1c2b1Dake Gu } 11671fddded48048acfa744ac352166770c91a1c2b1Dake Gu } 11771fddded48048acfa744ac352166770c91a1c2b1Dake Gu 11880d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn /** 11980d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn * A ViewHolder for the DetailsOverviewRow. 12080d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn */ 121cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout public final class ViewHolder extends RowPresenter.ViewHolder { 12209d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout final FrameLayout mOverviewFrame; 123b34a2372153298ebdc3e148e1c1f3b3924efab08Dake Gu final ViewGroup mOverviewView; 124a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn final ImageView mImageView; 1254121f22713bbed467a977ec0d867ef53989ff374Dake Gu final ViewGroup mRightPanel; 126a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn final FrameLayout mDetailsDescriptionFrame; 127a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn final HorizontalGridView mActionsRow; 12818c8048f17940359b8bce99cb46d24337bff8997Dake Gu public final Presenter.ViewHolder mDetailsDescriptionViewHolder; 12983118b72d02074ee35f07ad0253579565c16882bCraig Stout int mNumItems; 13083118b72d02074ee35f07ad0253579565c16882bCraig Stout boolean mShowMoreRight; 13183118b72d02074ee35f07ad0253579565c16882bCraig Stout boolean mShowMoreLeft; 13271fddded48048acfa744ac352166770c91a1c2b1Dake Gu ItemBridgeAdapter mActionBridgeAdapter; 133d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu final Handler mHandler = new Handler(); 134a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn 135d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu final Runnable mUpdateDrawableCallback = new Runnable() { 136d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu @Override 137d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu public void run() { 138d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu bindImageDrawable(ViewHolder.this); 139d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu } 140d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu }; 141d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu 142d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu final DetailsOverviewRow.Listener mListener = new DetailsOverviewRow.Listener() { 143d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu @Override 144d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu public void onImageDrawableChanged(DetailsOverviewRow row) { 145d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu mHandler.removeCallbacks(mUpdateDrawableCallback); 146d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu mHandler.post(mUpdateDrawableCallback); 147d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu } 148d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu 149d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu @Override 150d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu public void onItemChanged(DetailsOverviewRow row) { 151d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu if (mDetailsDescriptionViewHolder != null) { 152d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu mDetailsPresenter.onUnbindViewHolder(mDetailsDescriptionViewHolder); 153d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu } 154d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu mDetailsPresenter.onBindViewHolder(mDetailsDescriptionViewHolder, row.getItem()); 155d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu } 156d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu 157d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu @Override 158d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu public void onActionsAdapterChanged(DetailsOverviewRow row) { 159d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu bindActions(row.getActionsAdapter()); 160d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu } 161d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu }; 162d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu 163d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu void bindActions(ObjectAdapter adapter) { 164cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout mActionBridgeAdapter.setAdapter(adapter); 16537eb0e53ba5363bbe15314c7d19d4b2d6024a5aaDake Gu mActionsRow.setAdapter(mActionBridgeAdapter); 166cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout mNumItems = mActionBridgeAdapter.getItemCount(); 1672e0c922430f8c285b4325da52d69c09451069c93Craig Stout 16883118b72d02074ee35f07ad0253579565c16882bCraig Stout mShowMoreRight = false; 16983118b72d02074ee35f07ad0253579565c16882bCraig Stout mShowMoreLeft = true; 17083118b72d02074ee35f07ad0253579565c16882bCraig Stout showMoreLeft(false); 17183118b72d02074ee35f07ad0253579565c16882bCraig Stout } 17283118b72d02074ee35f07ad0253579565c16882bCraig Stout 173819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout final View.OnLayoutChangeListener mLayoutChangeListener = 174819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout new View.OnLayoutChangeListener() { 175819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout 176819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout @Override 177819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout public void onLayoutChange(View v, int left, int top, int right, 178819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { 179819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout if (DEBUG) Log.v(TAG, "onLayoutChange " + v); 180819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout checkFirstAndLastPosition(false); 181819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout } 182819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout }; 183819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout 184cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout final OnChildSelectedListener mChildSelectedListener = new OnChildSelectedListener() { 185cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout @Override 186cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout public void onChildSelected(ViewGroup parent, View view, int position, long id) { 187cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout dispatchItemSelection(view); 188cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout } 189cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout }; 190cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout 191cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout void dispatchItemSelection(View view) { 192cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout if (!isSelected()) { 193cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout return; 194cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout } 1953103f63e99d47573823957f7aa34308555873221Aurimas Liutikas ItemBridgeAdapter.ViewHolder ibvh = (ItemBridgeAdapter.ViewHolder) (view != null 1963103f63e99d47573823957f7aa34308555873221Aurimas Liutikas ? mActionsRow.getChildViewHolder(view) 1973103f63e99d47573823957f7aa34308555873221Aurimas Liutikas : mActionsRow.findViewHolderForPosition(mActionsRow.getSelectedPosition())); 198cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout if (ibvh == null) { 199cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout if (getOnItemViewSelectedListener() != null) { 200cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout getOnItemViewSelectedListener().onItemSelected(null, null, 201cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout ViewHolder.this, getRow()); 202cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout } 203cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout } else { 204cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout if (getOnItemViewSelectedListener() != null) { 205cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout getOnItemViewSelectedListener().onItemSelected(ibvh.getViewHolder(), ibvh.getItem(), 206cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout ViewHolder.this, getRow()); 207cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout } 208cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout } 209cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout }; 210cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout 21183118b72d02074ee35f07ad0253579565c16882bCraig Stout final RecyclerView.OnScrollListener mScrollListener = 21283118b72d02074ee35f07ad0253579565c16882bCraig Stout new RecyclerView.OnScrollListener() { 2132e0c922430f8c285b4325da52d69c09451069c93Craig Stout 2142e0c922430f8c285b4325da52d69c09451069c93Craig Stout @Override 215cef7b4942bacc862ea4eac66952e9f7aba027d18Yigit Boyar public void onScrollStateChanged(RecyclerView recyclerView, int newState) { 2162e0c922430f8c285b4325da52d69c09451069c93Craig Stout } 2172e0c922430f8c285b4325da52d69c09451069c93Craig Stout @Override 218cef7b4942bacc862ea4eac66952e9f7aba027d18Yigit Boyar public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 21983118b72d02074ee35f07ad0253579565c16882bCraig Stout checkFirstAndLastPosition(true); 2202e0c922430f8c285b4325da52d69c09451069c93Craig Stout } 22183118b72d02074ee35f07ad0253579565c16882bCraig Stout }; 22283118b72d02074ee35f07ad0253579565c16882bCraig Stout 22383118b72d02074ee35f07ad0253579565c16882bCraig Stout private int getViewCenter(View view) { 22483118b72d02074ee35f07ad0253579565c16882bCraig Stout return (view.getRight() - view.getLeft()) / 2; 22583118b72d02074ee35f07ad0253579565c16882bCraig Stout } 22683118b72d02074ee35f07ad0253579565c16882bCraig Stout 22799ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas void checkFirstAndLastPosition(boolean fromScroll) { 22883118b72d02074ee35f07ad0253579565c16882bCraig Stout RecyclerView.ViewHolder viewHolder; 2292e0c922430f8c285b4325da52d69c09451069c93Craig Stout 23083118b72d02074ee35f07ad0253579565c16882bCraig Stout viewHolder = mActionsRow.findViewHolderForPosition(mNumItems - 1); 2313103f63e99d47573823957f7aa34308555873221Aurimas Liutikas boolean showRight = (viewHolder == null 2323103f63e99d47573823957f7aa34308555873221Aurimas Liutikas || viewHolder.itemView.getRight() > mActionsRow.getWidth()); 23383118b72d02074ee35f07ad0253579565c16882bCraig Stout 23483118b72d02074ee35f07ad0253579565c16882bCraig Stout viewHolder = mActionsRow.findViewHolderForPosition(0); 23583118b72d02074ee35f07ad0253579565c16882bCraig Stout boolean showLeft = (viewHolder == null || viewHolder.itemView.getLeft() < 0); 23683118b72d02074ee35f07ad0253579565c16882bCraig Stout 2373103f63e99d47573823957f7aa34308555873221Aurimas Liutikas if (DEBUG) { 2383103f63e99d47573823957f7aa34308555873221Aurimas Liutikas Log.v(TAG, "checkFirstAndLast fromScroll " + fromScroll 2393103f63e99d47573823957f7aa34308555873221Aurimas Liutikas + " showRight " + showRight + " showLeft " + showLeft); 2403103f63e99d47573823957f7aa34308555873221Aurimas Liutikas } 24183118b72d02074ee35f07ad0253579565c16882bCraig Stout 24283118b72d02074ee35f07ad0253579565c16882bCraig Stout showMoreRight(showRight); 24383118b72d02074ee35f07ad0253579565c16882bCraig Stout showMoreLeft(showLeft); 24483118b72d02074ee35f07ad0253579565c16882bCraig Stout } 24583118b72d02074ee35f07ad0253579565c16882bCraig Stout 24683118b72d02074ee35f07ad0253579565c16882bCraig Stout private void showMoreLeft(boolean show) { 24783118b72d02074ee35f07ad0253579565c16882bCraig Stout if (show != mShowMoreLeft) { 24883118b72d02074ee35f07ad0253579565c16882bCraig Stout mActionsRow.setFadingLeftEdge(show); 24983118b72d02074ee35f07ad0253579565c16882bCraig Stout mShowMoreLeft = show; 2502e0c922430f8c285b4325da52d69c09451069c93Craig Stout } 25183118b72d02074ee35f07ad0253579565c16882bCraig Stout } 2522e0c922430f8c285b4325da52d69c09451069c93Craig Stout 25383118b72d02074ee35f07ad0253579565c16882bCraig Stout private void showMoreRight(boolean show) { 25483118b72d02074ee35f07ad0253579565c16882bCraig Stout if (show != mShowMoreRight) { 25583118b72d02074ee35f07ad0253579565c16882bCraig Stout mActionsRow.setFadingRightEdge(show); 25683118b72d02074ee35f07ad0253579565c16882bCraig Stout mShowMoreRight = show; 2572e0c922430f8c285b4325da52d69c09451069c93Craig Stout } 2582e0c922430f8c285b4325da52d69c09451069c93Craig Stout } 2592e0c922430f8c285b4325da52d69c09451069c93Craig Stout 26080d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn /** 26180d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn * Constructor for the ViewHolder. 26280d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn * 26380d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn * @param rootView The root View that this view holder will be attached 26480d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn * to. 26580d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn */ 26618c8048f17940359b8bce99cb46d24337bff8997Dake Gu public ViewHolder(View rootView, Presenter detailsPresenter) { 267a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn super(rootView); 26809d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout mOverviewFrame = (FrameLayout) rootView.findViewById(R.id.details_frame); 269b34a2372153298ebdc3e148e1c1f3b3924efab08Dake Gu mOverviewView = (ViewGroup) rootView.findViewById(R.id.details_overview); 270a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn mImageView = (ImageView) rootView.findViewById(R.id.details_overview_image); 2714121f22713bbed467a977ec0d867ef53989ff374Dake Gu mRightPanel = (ViewGroup) rootView.findViewById(R.id.details_overview_right_panel); 272a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn mDetailsDescriptionFrame = 2734121f22713bbed467a977ec0d867ef53989ff374Dake Gu (FrameLayout) mRightPanel.findViewById(R.id.details_overview_description); 27470c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn mActionsRow = 2754121f22713bbed467a977ec0d867ef53989ff374Dake Gu (HorizontalGridView) mRightPanel.findViewById(R.id.details_overview_actions); 276ceb7ab2ddd6e157cd4ade0f14a382c39428163c4Dake Gu mActionsRow.setHasOverlappingRendering(false); 2772e0c922430f8c285b4325da52d69c09451069c93Craig Stout mActionsRow.setOnScrollListener(mScrollListener); 278cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout mActionsRow.setAdapter(mActionBridgeAdapter); 279cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout mActionsRow.setOnChildSelectedListener(mChildSelectedListener); 2802e0c922430f8c285b4325da52d69c09451069c93Craig Stout 2812e0c922430f8c285b4325da52d69c09451069c93Craig Stout final int fadeLength = rootView.getResources().getDimensionPixelSize( 2822e0c922430f8c285b4325da52d69c09451069c93Craig Stout R.dimen.lb_details_overview_actions_fade_size); 2832e0c922430f8c285b4325da52d69c09451069c93Craig Stout mActionsRow.setFadingRightEdgeLength(fadeLength); 2842e0c922430f8c285b4325da52d69c09451069c93Craig Stout mActionsRow.setFadingLeftEdgeLength(fadeLength); 28518c8048f17940359b8bce99cb46d24337bff8997Dake Gu mDetailsDescriptionViewHolder = 28618c8048f17940359b8bce99cb46d24337bff8997Dake Gu detailsPresenter.onCreateViewHolder(mDetailsDescriptionFrame); 28718c8048f17940359b8bce99cb46d24337bff8997Dake Gu mDetailsDescriptionFrame.addView(mDetailsDescriptionViewHolder.view); 288a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn } 289a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn } 290a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn 29199ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas final Presenter mDetailsPresenter; 29299ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas OnActionClickedListener mActionClickedListener; 293cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout 294d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout private int mBackgroundColor = Color.TRANSPARENT; 295d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout private boolean mBackgroundColorSet; 296d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout private boolean mIsStyleLarge = true; 297a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn 2984121f22713bbed467a977ec0d867ef53989ff374Dake Gu private DetailsOverviewSharedElementHelper mSharedElementHelper; 2994121f22713bbed467a977ec0d867ef53989ff374Dake Gu 300a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn /** 30180d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn * Constructor for a DetailsOverviewRowPresenter. 30280d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn * 30380d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn * @param detailsPresenter The {@link Presenter} used to render the detailed 30480d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn * description of the row. 305a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn */ 306a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn public DetailsOverviewRowPresenter(Presenter detailsPresenter) { 307d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout setHeaderPresenter(null); 308a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn setSelectEffectEnabled(false); 309a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn mDetailsPresenter = detailsPresenter; 310a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn } 311a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn 31270c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn /** 31380d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn * Sets the listener for Action click events. 31470c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn */ 31570c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn public void setOnActionClickedListener(OnActionClickedListener listener) { 316cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout mActionClickedListener = listener; 31770c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn } 31870c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn 31970c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn /** 320a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * Returns the listener for Action click events. 32170c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn */ 32270c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn public OnActionClickedListener getOnActionClickedListener() { 323cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout return mActionClickedListener; 32470c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn } 32570c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn 326d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout /** 32780d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn * Sets the background color. If not set, a default from the theme will be used. 328d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout */ 32970acb0c19be3831a2080e4f902324de16bfbf62eTor Norbye public void setBackgroundColor(@ColorInt int color) { 330d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout mBackgroundColor = color; 331d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout mBackgroundColorSet = true; 332d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout } 333d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout 334d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout /** 33580d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn * Returns the background color. If no background color was set, transparent 33680d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn * is returned. 337d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout */ 33870acb0c19be3831a2080e4f902324de16bfbf62eTor Norbye @ColorInt 339d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout public int getBackgroundColor() { 340d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout return mBackgroundColor; 341d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout } 342d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout 343d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout /** 34480d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn * Sets the layout style to be large or small. This affects the height of 34580d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn * the overview, including the text description. The default is large. 346d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout */ 347d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout public void setStyleLarge(boolean large) { 348d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout mIsStyleLarge = large; 349d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout } 350d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout 351d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout /** 352d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout * Returns true if the layout style is large. 353d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout */ 354d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout public boolean isStyleLarge() { 355d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout return mIsStyleLarge; 356d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout } 357d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout 3589de363b8db05106b03d115c266859fe200d41db7Dake Gu /** 359a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * Sets the enter transition of target activity to be 360d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu * transiting into overview row created by this presenter. The transition will 361a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * be cancelled if the overview image is not loaded in the timeout period. 3624121f22713bbed467a977ec0d867ef53989ff374Dake Gu * <p> 3634121f22713bbed467a977ec0d867ef53989ff374Dake Gu * It assumes shared element passed from calling activity is an ImageView; 364a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * the shared element transits to overview image on the starting edge of the detail 3654121f22713bbed467a977ec0d867ef53989ff374Dake Gu * overview row, while bounds of overview row grows and reveals text 366a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * and action buttons. 3674121f22713bbed467a977ec0d867ef53989ff374Dake Gu * <p> 3684121f22713bbed467a977ec0d867ef53989ff374Dake Gu * The method must be invoked in target Activity's onCreate(). 3699de363b8db05106b03d115c266859fe200d41db7Dake Gu */ 3704121f22713bbed467a977ec0d867ef53989ff374Dake Gu public final void setSharedElementEnterTransition(Activity activity, 371d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu String sharedElementName, long timeoutMs) { 3724121f22713bbed467a977ec0d867ef53989ff374Dake Gu if (mSharedElementHelper == null) { 3734121f22713bbed467a977ec0d867ef53989ff374Dake Gu mSharedElementHelper = new DetailsOverviewSharedElementHelper(); 3744121f22713bbed467a977ec0d867ef53989ff374Dake Gu } 375d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu mSharedElementHelper.setSharedElementEnterTransition(activity, sharedElementName, 376d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu timeoutMs); 377d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu } 378d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu 379d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu /** 380a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * Sets the enter transition of target activity to be 381d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu * transiting into overview row created by this presenter. The transition will 382d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu * be cancelled if overview image is not loaded in a default timeout period. 383d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu * <p> 384d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu * It assumes shared element passed from calling activity is an ImageView; 385a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * the shared element transits to overview image on the starting edge of the detail 386d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu * overview row, while bounds of overview row grows and reveals text 387a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * and action buttons. 388d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu * <p> 389d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu * The method must be invoked in target Activity's onCreate(). 390d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu */ 391d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu public final void setSharedElementEnterTransition(Activity activity, 392d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu String sharedElementName) { 393d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu setSharedElementEnterTransition(activity, sharedElementName, DEFAULT_TIMEOUT); 3949de363b8db05106b03d115c266859fe200d41db7Dake Gu } 3959de363b8db05106b03d115c266859fe200d41db7Dake Gu 396d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout private int getDefaultBackgroundColor(Context context) { 397d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout TypedValue outValue = new TypedValue(); 39846443cb5b092f1d9156342645088eead9da026f6Dake Gu if (context.getTheme().resolveAttribute(R.attr.defaultBrandColor, outValue, true)) { 39946443cb5b092f1d9156342645088eead9da026f6Dake Gu return context.getResources().getColor(outValue.resourceId); 40046443cb5b092f1d9156342645088eead9da026f6Dake Gu } 40146443cb5b092f1d9156342645088eead9da026f6Dake Gu return context.getResources().getColor(R.color.lb_default_brand_color); 402d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout } 403d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout 404d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu @Override 405cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout protected void onRowViewSelected(RowPresenter.ViewHolder vh, boolean selected) { 406cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout super.onRowViewSelected(vh, selected); 407cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout if (selected) { 408cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout ((ViewHolder) vh).dispatchItemSelection(null); 409cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout } 410cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout } 411cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout 412a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn @Override 413a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn protected RowPresenter.ViewHolder createRowViewHolder(ViewGroup parent) { 414a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn View v = LayoutInflater.from(parent.getContext()) 415a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn .inflate(R.layout.lb_details_overview, parent, false); 41618c8048f17940359b8bce99cb46d24337bff8997Dake Gu ViewHolder vh = new ViewHolder(v, mDetailsPresenter); 417a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn 41850ea3557b75826b3f51480715df1973472e345c4Craig Stout initDetailsOverview(vh); 419d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout 420a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn return vh; 421a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn } 422a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn 423e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout private int getCardHeight(Context context) { 424d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout int resId = mIsStyleLarge ? R.dimen.lb_details_overview_height_large : 425d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout R.dimen.lb_details_overview_height_small; 426e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout return context.getResources().getDimensionPixelSize(resId); 427e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout } 428d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout 42960bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout private void initDetailsOverview(final ViewHolder vh) { 43071fddded48048acfa744ac352166770c91a1c2b1Dake Gu vh.mActionBridgeAdapter = new ActionsItemBridgeAdapter(vh); 43126c145aadca16cba3f294cc93c36edc6e9c98e6aCraig Stout final View overview = vh.mOverviewFrame; 43250ea3557b75826b3f51480715df1973472e345c4Craig Stout ViewGroup.LayoutParams lp = overview.getLayoutParams(); 433e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout lp.height = getCardHeight(overview.getContext()); 43450ea3557b75826b3f51480715df1973472e345c4Craig Stout overview.setLayoutParams(lp); 435d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout 43609d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout if (!getSelectEffectEnabled()) { 43709d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout vh.mOverviewFrame.setForeground(null); 43809d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout } 43960bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout vh.mActionsRow.setOnUnhandledKeyListener(new BaseGridView.OnUnhandledKeyListener() { 44060bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout @Override 44160bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout public boolean onUnhandledKey(KeyEvent event) { 44260bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout if (vh.getOnKeyListener() != null) { 44360bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout if (vh.getOnKeyListener().onKey(vh.view, event.getKeyCode(), event)) { 44460bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout return true; 44560bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout } 44660bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout } 44760bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout return false; 44860bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout } 44960bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout }); 450d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout } 451d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout 4527728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout private static int getNonNegativeWidth(Drawable drawable) { 4537728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout final int width = (drawable == null) ? 0 : drawable.getIntrinsicWidth(); 4547728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout return (width > 0 ? width : 0); 4557728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout } 4567728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout 4577728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout private static int getNonNegativeHeight(Drawable drawable) { 4587728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout final int height = (drawable == null) ? 0 : drawable.getIntrinsicHeight(); 4597728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout return (height > 0 ? height : 0); 4607728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout } 4617728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout 46299ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas void bindImageDrawable(ViewHolder vh) { 463d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu DetailsOverviewRow row = (DetailsOverviewRow) vh.getRow(); 464e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout 465e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout ViewGroup.MarginLayoutParams layoutParams = 466e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout (ViewGroup.MarginLayoutParams) vh.mImageView.getLayoutParams(); 467e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout final int cardHeight = getCardHeight(vh.mImageView.getContext()); 468e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout final int verticalMargin = vh.mImageView.getResources().getDimensionPixelSize( 469e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout R.dimen.lb_details_overview_image_margin_vertical); 470e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout final int horizontalMargin = vh.mImageView.getResources().getDimensionPixelSize( 471e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout R.dimen.lb_details_overview_image_margin_horizontal); 4727728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout final int drawableWidth = getNonNegativeWidth(row.getImageDrawable()); 4737728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout final int drawableHeight = getNonNegativeHeight(row.getImageDrawable()); 4747728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout 475e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout boolean scaleImage = row.isImageScaleUpAllowed(); 476e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout boolean useMargin = false; 477e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout 4787728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout if (row.getImageDrawable() != null) { 4797728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout boolean landscape = false; 4807728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout 4817728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout // If large style and landscape image we always use margin. 4827728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout if (drawableWidth > drawableHeight) { 4837728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout landscape = true; 4847728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout if (mIsStyleLarge) { 4857728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout useMargin = true; 4867728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout } 487e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout } 4887728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout // If long dimension bigger than the card height we scale down. 4893103f63e99d47573823957f7aa34308555873221Aurimas Liutikas if ((landscape && drawableWidth > cardHeight) 4903103f63e99d47573823957f7aa34308555873221Aurimas Liutikas || (!landscape && drawableHeight > cardHeight)) { 491e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout scaleImage = true; 492e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout } 4937728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout // If we're not scaling to fit the card height then we always use margin. 4947728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout if (!scaleImage) { 4957728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout useMargin = true; 4967728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout } 4977728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout // If using margin than may need to scale down. 4987728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout if (useMargin && !scaleImage) { 4997728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout if (landscape && drawableWidth > cardHeight - horizontalMargin) { 5007728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout scaleImage = true; 5017728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout } else if (!landscape && drawableHeight > cardHeight - 2 * verticalMargin) { 5027728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout scaleImage = true; 5037728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout } 5047728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout } 505e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout } 506e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout 5074f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout final int bgColor = mBackgroundColorSet ? mBackgroundColor : 5084f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout getDefaultBackgroundColor(vh.mOverviewView.getContext()); 5094f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout 510e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout if (useMargin) { 5114e602840ed6741b44a536826799625ad0be4b3c6Kris Giesing layoutParams.setMarginStart(horizontalMargin); 512e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout layoutParams.topMargin = layoutParams.bottomMargin = verticalMargin; 5136b447e693090017258eb48a51ae4119fb0f5119eCraig Stout vh.mOverviewFrame.setBackgroundColor(bgColor); 51472a2146f4c3e6dbb84a5f9f92e7ab42d142dab04Dake Gu vh.mRightPanel.setBackground(null); 515836443f4a3b69eb7a88ffeb65a39e11439dee55eDake Gu vh.mImageView.setBackground(null); 516e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout } else { 517e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout layoutParams.leftMargin = layoutParams.topMargin = layoutParams.bottomMargin = 0; 5184f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout vh.mRightPanel.setBackgroundColor(bgColor); 5194f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout vh.mImageView.setBackgroundColor(bgColor); 5206b447e693090017258eb48a51ae4119fb0f5119eCraig Stout vh.mOverviewFrame.setBackground(null); 521e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout } 5229cc4c25ccaefdb9fd3186323f0d1520ef4458aa8Jake Wharton RoundedRectHelper.setClipToRoundedOutline(vh.mOverviewFrame, true); 5236b447e693090017258eb48a51ae4119fb0f5119eCraig Stout 524e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout if (scaleImage) { 525e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout vh.mImageView.setScaleType(ImageView.ScaleType.FIT_START); 526e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout vh.mImageView.setAdjustViewBounds(true); 527e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout vh.mImageView.setMaxWidth(cardHeight); 528e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT; 529e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT; 530e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout } else { 531e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout vh.mImageView.setScaleType(ImageView.ScaleType.CENTER); 532e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout vh.mImageView.setAdjustViewBounds(false); 533e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT; 534e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout // Limit width to the card height 5357728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout layoutParams.width = Math.min(cardHeight, drawableWidth); 536e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout } 537e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout vh.mImageView.setLayoutParams(layoutParams); 538e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout vh.mImageView.setImageDrawable(row.getImageDrawable()); 5394121f22713bbed467a977ec0d867ef53989ff374Dake Gu if (row.getImageDrawable() != null && mSharedElementHelper != null) { 5404121f22713bbed467a977ec0d867ef53989ff374Dake Gu mSharedElementHelper.onBindToDrawable(vh); 5414121f22713bbed467a977ec0d867ef53989ff374Dake Gu } 542a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn } 543a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn 544a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn @Override 545d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu protected void onBindRowViewHolder(RowPresenter.ViewHolder holder, Object item) { 546d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu super.onBindRowViewHolder(holder, item); 547d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu 548d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu DetailsOverviewRow row = (DetailsOverviewRow) item; 549d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu ViewHolder vh = (ViewHolder) holder; 550d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu 551d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu bindImageDrawable(vh); 552d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu mDetailsPresenter.onBindViewHolder(vh.mDetailsDescriptionViewHolder, row.getItem()); 553d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu vh.bindActions(row.getActionsAdapter()); 554d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu row.addListener(vh.mListener); 555d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu } 556d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu 557d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu @Override 558cb13a318e577e14461eb008071dddf762847de42Dake Gu protected void onUnbindRowViewHolder(RowPresenter.ViewHolder holder) { 559a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn ViewHolder vh = (ViewHolder) holder; 560d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu DetailsOverviewRow dor = (DetailsOverviewRow) vh.getRow(); 561d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu dor.removeListener(vh.mListener); 562a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn if (vh.mDetailsDescriptionViewHolder != null) { 563a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn mDetailsPresenter.onUnbindViewHolder(vh.mDetailsDescriptionViewHolder); 564a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn } 565fc8f0f06c93c224d86b85c8b9f7ae737968fd797Dake Gu super.onUnbindRowViewHolder(holder); 566a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn } 56709d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout 56809d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout @Override 56909d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout public final boolean isUsingDefaultSelectEffect() { 57009d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout return false; 57109d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout } 57209d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout 57309d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout @Override 57409d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout protected void onSelectLevelChanged(RowPresenter.ViewHolder holder) { 57509d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout super.onSelectLevelChanged(holder); 57609d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout if (getSelectEffectEnabled()) { 57709d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout ViewHolder vh = (ViewHolder) holder; 57809d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout int dimmedColor = vh.mColorDimmer.getPaint().getColor(); 57909d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout ((ColorDrawable) vh.mOverviewFrame.getForeground().mutate()).setColor(dimmedColor); 58009d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout } 58109d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout } 58226d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout 58326d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout @Override 58426d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout protected void onRowViewAttachedToWindow(RowPresenter.ViewHolder vh) { 58526d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout super.onRowViewAttachedToWindow(vh); 58626d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout if (mDetailsPresenter != null) { 58726d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout mDetailsPresenter.onViewAttachedToWindow( 58826d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout ((ViewHolder) vh).mDetailsDescriptionViewHolder); 58926d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout } 59026d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout } 59126d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout 59226d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout @Override 59326d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout protected void onRowViewDetachedFromWindow(RowPresenter.ViewHolder vh) { 59426d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout super.onRowViewDetachedFromWindow(vh); 59526d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout if (mDetailsPresenter != null) { 59626d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout mDetailsPresenter.onViewDetachedFromWindow( 59726d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout ((ViewHolder) vh).mDetailsDescriptionViewHolder); 59826d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout } 59926d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout } 600a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn} 601