DetailsOverviewRowPresenter.java revision 3a5038bd0fefa5628a31a21422bf2126c53472a9
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 */
14a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournpackage android.support.v17.leanback.widget;
15a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
164121f22713bbed467a977ec0d867ef53989ff374Dake Guimport android.app.Activity;
17d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stoutimport android.content.Context;
18e23ea69ec54eb70d17239ba671fcd75563780553Craig Stoutimport android.graphics.Bitmap;
19d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stoutimport android.graphics.Color;
207728d53c5c50e8ed807e8f4a189e34684de04800Craig Stoutimport android.graphics.drawable.Drawable;
21e23ea69ec54eb70d17239ba671fcd75563780553Craig Stoutimport android.graphics.drawable.BitmapDrawable;
2209d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stoutimport android.graphics.drawable.ColorDrawable;
23d825ff3727407a154a35e20b3a9adc79e57879b9Dake Guimport android.os.Handler;
24a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournimport android.support.v17.leanback.R;
252e0c922430f8c285b4325da52d69c09451069c93Craig Stoutimport android.support.v7.widget.RecyclerView;
262e0c922430f8c285b4325da52d69c09451069c93Craig Stoutimport android.util.Log;
27d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stoutimport android.util.TypedValue;
2860bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stoutimport android.view.KeyEvent;
29a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournimport android.view.LayoutInflater;
30a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournimport android.view.View;
31a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournimport android.view.ViewGroup;
32a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournimport android.widget.FrameLayout;
33a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournimport android.widget.ImageView;
34a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
35a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournimport java.util.Collection;
36a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
37a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn/**
3880d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn * A DetailsOverviewRowPresenter renders a {@link DetailsOverviewRow} to display an
39a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn * overview of an item. Typically this row will be the first row in a fragment
4080d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn * such as the {@link android.support.v17.leanback.app.DetailsFragment
4118c8048f17940359b8bce99cb46d24337bff8997Dake Gu * DetailsFragment}.  View created by DetailsOverviewRowPresenter is made in three parts:
4218c8048f17940359b8bce99cb46d24337bff8997Dake Gu * ImageView on the left, action list view on the bottom and a customizable detailed
4318c8048f17940359b8bce99cb46d24337bff8997Dake Gu * description view on the right.
44a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn *
4518c8048f17940359b8bce99cb46d24337bff8997Dake Gu * <p>The detailed description is rendered using a {@link Presenter} passed in
4618c8048f17940359b8bce99cb46d24337bff8997Dake Gu * {@link #DetailsOverviewRowPresenter(Presenter)}.  User can access detailed description
4718c8048f17940359b8bce99cb46d24337bff8997Dake Gu * ViewHolder from {@link ViewHolder#mDetailsDescriptionViewHolder}.
4818c8048f17940359b8bce99cb46d24337bff8997Dake Gu * </p>
4918c8048f17940359b8bce99cb46d24337bff8997Dake Gu *
5018c8048f17940359b8bce99cb46d24337bff8997Dake Gu * <p>
5118c8048f17940359b8bce99cb46d24337bff8997Dake Gu * To participate in activity transition, call {@link #setSharedElementEnterTransition(Activity,
5218c8048f17940359b8bce99cb46d24337bff8997Dake Gu * String)} during Activity's onCreate().
5318c8048f17940359b8bce99cb46d24337bff8997Dake Gu * </p>
5418c8048f17940359b8bce99cb46d24337bff8997Dake Gu *
5518c8048f17940359b8bce99cb46d24337bff8997Dake Gu * <p>
5618c8048f17940359b8bce99cb46d24337bff8997Dake Gu * Because transition support and layout are fully controlled by DetailsOverviewRowPresenter,
5718c8048f17940359b8bce99cb46d24337bff8997Dake Gu * developer can not override DetailsOverviewRowPresenter.ViewHolder for adding/replacing views
5818c8048f17940359b8bce99cb46d24337bff8997Dake Gu * of DetailsOverviewRowPresenter.  If developer wants more customization beyond replacing
5918c8048f17940359b8bce99cb46d24337bff8997Dake Gu * detailed description , he/she should write a new presenter class for row object.
6018c8048f17940359b8bce99cb46d24337bff8997Dake Gu * </p>
61a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn */
62a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournpublic class DetailsOverviewRowPresenter extends RowPresenter {
63a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
64a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    private static final String TAG = "DetailsOverviewRowPresenter";
65a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    private static final boolean DEBUG = false;
66a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
672e0c922430f8c285b4325da52d69c09451069c93Craig Stout    private static final int MORE_ACTIONS_FADE_MS = 100;
68d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu    private static final long DEFAULT_TIMEOUT = 5000;
692e0c922430f8c285b4325da52d69c09451069c93Craig Stout
7071fddded48048acfa744ac352166770c91a1c2b1Dake Gu    class ActionsItemBridgeAdapter extends ItemBridgeAdapter {
7171fddded48048acfa744ac352166770c91a1c2b1Dake Gu        DetailsOverviewRowPresenter.ViewHolder mViewHolder;
7271fddded48048acfa744ac352166770c91a1c2b1Dake Gu
7371fddded48048acfa744ac352166770c91a1c2b1Dake Gu        ActionsItemBridgeAdapter(DetailsOverviewRowPresenter.ViewHolder viewHolder) {
7471fddded48048acfa744ac352166770c91a1c2b1Dake Gu            mViewHolder = viewHolder;
7571fddded48048acfa744ac352166770c91a1c2b1Dake Gu        }
7671fddded48048acfa744ac352166770c91a1c2b1Dake Gu
7771fddded48048acfa744ac352166770c91a1c2b1Dake Gu        @Override
7871fddded48048acfa744ac352166770c91a1c2b1Dake Gu        public void onBind(final ItemBridgeAdapter.ViewHolder ibvh) {
793a5038bd0fefa5628a31a21422bf2126c53472a9Craig Stout            if (mViewHolder.getOnItemViewClickedListener() != null ||
803a5038bd0fefa5628a31a21422bf2126c53472a9Craig Stout                    mActionClickedListener != null) {
8171fddded48048acfa744ac352166770c91a1c2b1Dake Gu                ibvh.getPresenter().setOnClickListener(
8271fddded48048acfa744ac352166770c91a1c2b1Dake Gu                        ibvh.getViewHolder(), new View.OnClickListener() {
8371fddded48048acfa744ac352166770c91a1c2b1Dake Gu                            @Override
8471fddded48048acfa744ac352166770c91a1c2b1Dake Gu                            public void onClick(View v) {
853a5038bd0fefa5628a31a21422bf2126c53472a9Craig Stout                                if (mViewHolder.getOnItemViewClickedListener() != null) {
863a5038bd0fefa5628a31a21422bf2126c53472a9Craig Stout                                    mViewHolder.getOnItemViewClickedListener().onItemClicked(
8771fddded48048acfa744ac352166770c91a1c2b1Dake Gu                                            ibvh.getViewHolder(), ibvh.getItem(),
8871fddded48048acfa744ac352166770c91a1c2b1Dake Gu                                            mViewHolder, mViewHolder.getRow());
8971fddded48048acfa744ac352166770c91a1c2b1Dake Gu                                }
9071fddded48048acfa744ac352166770c91a1c2b1Dake Gu                                if (mActionClickedListener != null) {
9171fddded48048acfa744ac352166770c91a1c2b1Dake Gu                                    mActionClickedListener.onActionClicked((Action) ibvh.getItem());
9271fddded48048acfa744ac352166770c91a1c2b1Dake Gu                                }
9371fddded48048acfa744ac352166770c91a1c2b1Dake Gu                            }
9471fddded48048acfa744ac352166770c91a1c2b1Dake Gu                        });
9571fddded48048acfa744ac352166770c91a1c2b1Dake Gu            }
9671fddded48048acfa744ac352166770c91a1c2b1Dake Gu        }
9771fddded48048acfa744ac352166770c91a1c2b1Dake Gu        @Override
9871fddded48048acfa744ac352166770c91a1c2b1Dake Gu        public void onUnbind(final ItemBridgeAdapter.ViewHolder ibvh) {
993a5038bd0fefa5628a31a21422bf2126c53472a9Craig Stout            if (mViewHolder.getOnItemViewClickedListener() != null ||
1003a5038bd0fefa5628a31a21422bf2126c53472a9Craig Stout                    mActionClickedListener != null) {
10171fddded48048acfa744ac352166770c91a1c2b1Dake Gu                ibvh.getPresenter().setOnClickListener(ibvh.getViewHolder(), null);
10271fddded48048acfa744ac352166770c91a1c2b1Dake Gu            }
10371fddded48048acfa744ac352166770c91a1c2b1Dake Gu        }
10471fddded48048acfa744ac352166770c91a1c2b1Dake Gu        @Override
10571fddded48048acfa744ac352166770c91a1c2b1Dake Gu        public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder viewHolder) {
10671fddded48048acfa744ac352166770c91a1c2b1Dake Gu            // Remove first to ensure we don't add ourselves more than once.
10771fddded48048acfa744ac352166770c91a1c2b1Dake Gu            viewHolder.itemView.removeOnLayoutChangeListener(mViewHolder.mLayoutChangeListener);
10871fddded48048acfa744ac352166770c91a1c2b1Dake Gu            viewHolder.itemView.addOnLayoutChangeListener(mViewHolder.mLayoutChangeListener);
10971fddded48048acfa744ac352166770c91a1c2b1Dake Gu        }
11071fddded48048acfa744ac352166770c91a1c2b1Dake Gu        @Override
11171fddded48048acfa744ac352166770c91a1c2b1Dake Gu        public void onDetachedFromWindow(ItemBridgeAdapter.ViewHolder viewHolder) {
11271fddded48048acfa744ac352166770c91a1c2b1Dake Gu            viewHolder.itemView.removeOnLayoutChangeListener(mViewHolder.mLayoutChangeListener);
11371fddded48048acfa744ac352166770c91a1c2b1Dake Gu            mViewHolder.checkFirstAndLastPosition(false);
11471fddded48048acfa744ac352166770c91a1c2b1Dake Gu        }
11571fddded48048acfa744ac352166770c91a1c2b1Dake Gu    }
11671fddded48048acfa744ac352166770c91a1c2b1Dake Gu
11780d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn    /**
11880d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     * A ViewHolder for the DetailsOverviewRow.
11980d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     */
120cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout    public final class ViewHolder extends RowPresenter.ViewHolder {
12109d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout        final FrameLayout mOverviewFrame;
122b34a2372153298ebdc3e148e1c1f3b3924efab08Dake Gu        final ViewGroup mOverviewView;
123a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        final ImageView mImageView;
1244121f22713bbed467a977ec0d867ef53989ff374Dake Gu        final ViewGroup mRightPanel;
125a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        final FrameLayout mDetailsDescriptionFrame;
126a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        final HorizontalGridView mActionsRow;
12718c8048f17940359b8bce99cb46d24337bff8997Dake Gu        public final Presenter.ViewHolder mDetailsDescriptionViewHolder;
12883118b72d02074ee35f07ad0253579565c16882bCraig Stout        int mNumItems;
12983118b72d02074ee35f07ad0253579565c16882bCraig Stout        boolean mShowMoreRight;
13083118b72d02074ee35f07ad0253579565c16882bCraig Stout        boolean mShowMoreLeft;
13171fddded48048acfa744ac352166770c91a1c2b1Dake Gu        ItemBridgeAdapter mActionBridgeAdapter;
132d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu        final Handler mHandler = new Handler();
133a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
134d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu        final Runnable mUpdateDrawableCallback = new Runnable() {
135d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu            @Override
136d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu            public void run() {
137d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu                bindImageDrawable(ViewHolder.this);
138d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu            }
139d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu        };
140d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu
141d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu        final DetailsOverviewRow.Listener mListener = new DetailsOverviewRow.Listener() {
142d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu            @Override
143d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu            public void onImageDrawableChanged(DetailsOverviewRow row) {
144d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu                mHandler.removeCallbacks(mUpdateDrawableCallback);
145d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu                mHandler.post(mUpdateDrawableCallback);
146d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu            }
147d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu
148d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu            @Override
149d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu            public void onItemChanged(DetailsOverviewRow row) {
150d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu                if (mDetailsDescriptionViewHolder != null) {
151d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu                    mDetailsPresenter.onUnbindViewHolder(mDetailsDescriptionViewHolder);
152d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu                }
153d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu                mDetailsPresenter.onBindViewHolder(mDetailsDescriptionViewHolder, row.getItem());
154d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu            }
155d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu
156d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu            @Override
157d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu            public void onActionsAdapterChanged(DetailsOverviewRow row) {
158d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu                bindActions(row.getActionsAdapter());
159d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu            }
160d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu        };
161d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu
162d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu        void bindActions(ObjectAdapter adapter) {
163cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            mActionBridgeAdapter.setAdapter(adapter);
16437eb0e53ba5363bbe15314c7d19d4b2d6024a5aaDake Gu            mActionsRow.setAdapter(mActionBridgeAdapter);
165cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            mNumItems = mActionBridgeAdapter.getItemCount();
1662e0c922430f8c285b4325da52d69c09451069c93Craig Stout
16783118b72d02074ee35f07ad0253579565c16882bCraig Stout            mShowMoreRight = false;
16883118b72d02074ee35f07ad0253579565c16882bCraig Stout            mShowMoreLeft = true;
16983118b72d02074ee35f07ad0253579565c16882bCraig Stout            showMoreLeft(false);
17083118b72d02074ee35f07ad0253579565c16882bCraig Stout        }
17183118b72d02074ee35f07ad0253579565c16882bCraig Stout
172819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout        final View.OnLayoutChangeListener mLayoutChangeListener =
173819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout                new View.OnLayoutChangeListener() {
174819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout
175819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout            @Override
176819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout            public void onLayoutChange(View v, int left, int top, int right,
177819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout                    int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
178819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout                if (DEBUG) Log.v(TAG, "onLayoutChange " + v);
179819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout                checkFirstAndLastPosition(false);
180819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout            }
181819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout        };
182819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout
183cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        final OnChildSelectedListener mChildSelectedListener = new OnChildSelectedListener() {
184cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            @Override
185cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            public void onChildSelected(ViewGroup parent, View view, int position, long id) {
186cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                dispatchItemSelection(view);
187cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            }
188cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        };
189cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout
190cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        void dispatchItemSelection(View view) {
191cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            if (!isSelected()) {
192cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                return;
193cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            }
194cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            ItemBridgeAdapter.ViewHolder ibvh = (ItemBridgeAdapter.ViewHolder) (view != null ?
195cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                    mActionsRow.getChildViewHolder(view) :
196cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                    mActionsRow.findViewHolderForPosition(mActionsRow.getSelectedPosition()));
197cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            if (ibvh == null) {
198cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                if (getOnItemViewSelectedListener() != null) {
199cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                    getOnItemViewSelectedListener().onItemSelected(null, null,
200cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                            ViewHolder.this, getRow());
201cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                }
202cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            } else {
203cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                if (getOnItemViewSelectedListener() != null) {
204cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                    getOnItemViewSelectedListener().onItemSelected(ibvh.getViewHolder(), ibvh.getItem(),
205cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                            ViewHolder.this, getRow());
206cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                }
207cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            }
208cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        };
209cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout
21083118b72d02074ee35f07ad0253579565c16882bCraig Stout        final RecyclerView.OnScrollListener mScrollListener =
21183118b72d02074ee35f07ad0253579565c16882bCraig Stout                new RecyclerView.OnScrollListener() {
2122e0c922430f8c285b4325da52d69c09451069c93Craig Stout
2132e0c922430f8c285b4325da52d69c09451069c93Craig Stout            @Override
214cef7b4942bacc862ea4eac66952e9f7aba027d18Yigit Boyar            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
2152e0c922430f8c285b4325da52d69c09451069c93Craig Stout            }
2162e0c922430f8c285b4325da52d69c09451069c93Craig Stout            @Override
217cef7b4942bacc862ea4eac66952e9f7aba027d18Yigit Boyar            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
21883118b72d02074ee35f07ad0253579565c16882bCraig Stout                checkFirstAndLastPosition(true);
2192e0c922430f8c285b4325da52d69c09451069c93Craig Stout            }
22083118b72d02074ee35f07ad0253579565c16882bCraig Stout        };
22183118b72d02074ee35f07ad0253579565c16882bCraig Stout
22283118b72d02074ee35f07ad0253579565c16882bCraig Stout        private int getViewCenter(View view) {
22383118b72d02074ee35f07ad0253579565c16882bCraig Stout            return (view.getRight() - view.getLeft()) / 2;
22483118b72d02074ee35f07ad0253579565c16882bCraig Stout        }
22583118b72d02074ee35f07ad0253579565c16882bCraig Stout
22683118b72d02074ee35f07ad0253579565c16882bCraig Stout        private void checkFirstAndLastPosition(boolean fromScroll) {
22783118b72d02074ee35f07ad0253579565c16882bCraig Stout            RecyclerView.ViewHolder viewHolder;
2282e0c922430f8c285b4325da52d69c09451069c93Craig Stout
22983118b72d02074ee35f07ad0253579565c16882bCraig Stout            viewHolder = mActionsRow.findViewHolderForPosition(mNumItems - 1);
23083118b72d02074ee35f07ad0253579565c16882bCraig Stout            boolean showRight = (viewHolder == null ||
23183118b72d02074ee35f07ad0253579565c16882bCraig Stout                    viewHolder.itemView.getRight() > mActionsRow.getWidth());
23283118b72d02074ee35f07ad0253579565c16882bCraig Stout
23383118b72d02074ee35f07ad0253579565c16882bCraig Stout            viewHolder = mActionsRow.findViewHolderForPosition(0);
23483118b72d02074ee35f07ad0253579565c16882bCraig Stout            boolean showLeft = (viewHolder == null || viewHolder.itemView.getLeft() < 0);
23583118b72d02074ee35f07ad0253579565c16882bCraig Stout
23683118b72d02074ee35f07ad0253579565c16882bCraig Stout            if (DEBUG) Log.v(TAG, "checkFirstAndLast fromScroll " + fromScroll +
23783118b72d02074ee35f07ad0253579565c16882bCraig Stout                    " showRight " + showRight + " showLeft " + showLeft);
23883118b72d02074ee35f07ad0253579565c16882bCraig Stout
23983118b72d02074ee35f07ad0253579565c16882bCraig Stout            showMoreRight(showRight);
24083118b72d02074ee35f07ad0253579565c16882bCraig Stout            showMoreLeft(showLeft);
24183118b72d02074ee35f07ad0253579565c16882bCraig Stout        }
24283118b72d02074ee35f07ad0253579565c16882bCraig Stout
24383118b72d02074ee35f07ad0253579565c16882bCraig Stout        private void showMoreLeft(boolean show) {
24483118b72d02074ee35f07ad0253579565c16882bCraig Stout            if (show != mShowMoreLeft) {
24583118b72d02074ee35f07ad0253579565c16882bCraig Stout                mActionsRow.setFadingLeftEdge(show);
24683118b72d02074ee35f07ad0253579565c16882bCraig Stout                mShowMoreLeft = show;
2472e0c922430f8c285b4325da52d69c09451069c93Craig Stout            }
24883118b72d02074ee35f07ad0253579565c16882bCraig Stout        }
2492e0c922430f8c285b4325da52d69c09451069c93Craig Stout
25083118b72d02074ee35f07ad0253579565c16882bCraig Stout        private void showMoreRight(boolean show) {
25183118b72d02074ee35f07ad0253579565c16882bCraig Stout            if (show != mShowMoreRight) {
25283118b72d02074ee35f07ad0253579565c16882bCraig Stout                mActionsRow.setFadingRightEdge(show);
25383118b72d02074ee35f07ad0253579565c16882bCraig Stout                mShowMoreRight = show;
2542e0c922430f8c285b4325da52d69c09451069c93Craig Stout            }
2552e0c922430f8c285b4325da52d69c09451069c93Craig Stout        }
2562e0c922430f8c285b4325da52d69c09451069c93Craig Stout
25780d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn        /**
25880d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn         * Constructor for the ViewHolder.
25980d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn         *
26080d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn         * @param rootView The root View that this view holder will be attached
26180d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn         *        to.
26280d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn         */
26318c8048f17940359b8bce99cb46d24337bff8997Dake Gu        public ViewHolder(View rootView, Presenter detailsPresenter) {
264a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn            super(rootView);
26509d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout            mOverviewFrame = (FrameLayout) rootView.findViewById(R.id.details_frame);
266b34a2372153298ebdc3e148e1c1f3b3924efab08Dake Gu            mOverviewView = (ViewGroup) rootView.findViewById(R.id.details_overview);
267a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn            mImageView = (ImageView) rootView.findViewById(R.id.details_overview_image);
2684121f22713bbed467a977ec0d867ef53989ff374Dake Gu            mRightPanel = (ViewGroup) rootView.findViewById(R.id.details_overview_right_panel);
269a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn            mDetailsDescriptionFrame =
2704121f22713bbed467a977ec0d867ef53989ff374Dake Gu                    (FrameLayout) mRightPanel.findViewById(R.id.details_overview_description);
27170c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn            mActionsRow =
2724121f22713bbed467a977ec0d867ef53989ff374Dake Gu                    (HorizontalGridView) mRightPanel.findViewById(R.id.details_overview_actions);
273ceb7ab2ddd6e157cd4ade0f14a382c39428163c4Dake Gu            mActionsRow.setHasOverlappingRendering(false);
2742e0c922430f8c285b4325da52d69c09451069c93Craig Stout            mActionsRow.setOnScrollListener(mScrollListener);
275cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            mActionsRow.setAdapter(mActionBridgeAdapter);
276cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            mActionsRow.setOnChildSelectedListener(mChildSelectedListener);
2772e0c922430f8c285b4325da52d69c09451069c93Craig Stout
2782e0c922430f8c285b4325da52d69c09451069c93Craig Stout            final int fadeLength = rootView.getResources().getDimensionPixelSize(
2792e0c922430f8c285b4325da52d69c09451069c93Craig Stout                    R.dimen.lb_details_overview_actions_fade_size);
2802e0c922430f8c285b4325da52d69c09451069c93Craig Stout            mActionsRow.setFadingRightEdgeLength(fadeLength);
2812e0c922430f8c285b4325da52d69c09451069c93Craig Stout            mActionsRow.setFadingLeftEdgeLength(fadeLength);
28218c8048f17940359b8bce99cb46d24337bff8997Dake Gu            mDetailsDescriptionViewHolder =
28318c8048f17940359b8bce99cb46d24337bff8997Dake Gu                    detailsPresenter.onCreateViewHolder(mDetailsDescriptionFrame);
28418c8048f17940359b8bce99cb46d24337bff8997Dake Gu            mDetailsDescriptionFrame.addView(mDetailsDescriptionViewHolder.view);
285a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        }
286a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    }
287a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
288a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    private final Presenter mDetailsPresenter;
289cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout    private OnActionClickedListener mActionClickedListener;
290cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout
291d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    private int mBackgroundColor = Color.TRANSPARENT;
292d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    private boolean mBackgroundColorSet;
293d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    private boolean mIsStyleLarge = true;
294a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
2954121f22713bbed467a977ec0d867ef53989ff374Dake Gu    private DetailsOverviewSharedElementHelper mSharedElementHelper;
2964121f22713bbed467a977ec0d867ef53989ff374Dake Gu
297a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    /**
29880d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     * Constructor for a DetailsOverviewRowPresenter.
29980d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     *
30080d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     * @param detailsPresenter The {@link Presenter} used to render the detailed
30180d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     *        description of the row.
302a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn     */
303a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    public DetailsOverviewRowPresenter(Presenter detailsPresenter) {
304d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout        setHeaderPresenter(null);
305a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        setSelectEffectEnabled(false);
306a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        mDetailsPresenter = detailsPresenter;
307a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    }
308a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
30970c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn    /**
31080d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     * Sets the listener for Action click events.
31170c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn     */
31270c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn    public void setOnActionClickedListener(OnActionClickedListener listener) {
313cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        mActionClickedListener = listener;
31470c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn    }
31570c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn
31670c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn    /**
31780d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     * Gets the listener for Action click events.
31870c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn     */
31970c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn    public OnActionClickedListener getOnActionClickedListener() {
320cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        return mActionClickedListener;
32170c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn    }
32270c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn
323d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    /**
32480d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     * Sets the background color.  If not set, a default from the theme will be used.
325d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout     */
326d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    public void setBackgroundColor(int color) {
327d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout        mBackgroundColor = color;
328d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout        mBackgroundColorSet = true;
329d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    }
330d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout
331d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    /**
33280d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     * Returns the background color.  If no background color was set, transparent
33380d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     * is returned.
334d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout     */
335d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    public int getBackgroundColor() {
336d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout        return mBackgroundColor;
337d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    }
338d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout
339d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    /**
34080d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     * Sets the layout style to be large or small. This affects the height of
34180d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     * the overview, including the text description. The default is large.
342d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout     */
343d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    public void setStyleLarge(boolean large) {
344d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout        mIsStyleLarge = large;
345d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    }
346d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout
347d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    /**
348d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout     * Returns true if the layout style is large.
349d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout     */
350d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    public boolean isStyleLarge() {
351d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout        return mIsStyleLarge;
352d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    }
353d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout
3549de363b8db05106b03d115c266859fe200d41db7Dake Gu    /**
3554121f22713bbed467a977ec0d867ef53989ff374Dake Gu     * Set enter transition of target activity (typically a DetailActivity) to be
356d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * transiting into overview row created by this presenter.  The transition will
357d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * be cancelled if overview image is not loaded in the timeout period.
3584121f22713bbed467a977ec0d867ef53989ff374Dake Gu     * <p>
3594121f22713bbed467a977ec0d867ef53989ff374Dake Gu     * It assumes shared element passed from calling activity is an ImageView;
3604121f22713bbed467a977ec0d867ef53989ff374Dake Gu     * the shared element transits to overview image on the left of detail
3614121f22713bbed467a977ec0d867ef53989ff374Dake Gu     * overview row, while bounds of overview row grows and reveals text
3624121f22713bbed467a977ec0d867ef53989ff374Dake Gu     * and buttons on the right.
3634121f22713bbed467a977ec0d867ef53989ff374Dake Gu     * <p>
3644121f22713bbed467a977ec0d867ef53989ff374Dake Gu     * The method must be invoked in target Activity's onCreate().
3659de363b8db05106b03d115c266859fe200d41db7Dake Gu     */
3664121f22713bbed467a977ec0d867ef53989ff374Dake Gu    public final void setSharedElementEnterTransition(Activity activity,
367d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu            String sharedElementName, long timeoutMs) {
3684121f22713bbed467a977ec0d867ef53989ff374Dake Gu        if (mSharedElementHelper == null) {
3694121f22713bbed467a977ec0d867ef53989ff374Dake Gu            mSharedElementHelper = new DetailsOverviewSharedElementHelper();
3704121f22713bbed467a977ec0d867ef53989ff374Dake Gu        }
371d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu        mSharedElementHelper.setSharedElementEnterTransition(activity, sharedElementName,
372d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu                timeoutMs);
373d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu    }
374d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu
375d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu    /**
376d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * Set enter transition of target activity (typically a DetailActivity) to be
377d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * transiting into overview row created by this presenter.  The transition will
378d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * be cancelled if overview image is not loaded in a default timeout period.
379d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * <p>
380d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * It assumes shared element passed from calling activity is an ImageView;
381d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * the shared element transits to overview image on the left of detail
382d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * overview row, while bounds of overview row grows and reveals text
383d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * and buttons on the right.
384d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * <p>
385d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * The method must be invoked in target Activity's onCreate().
386d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     */
387d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu    public final void setSharedElementEnterTransition(Activity activity,
388d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu            String sharedElementName) {
389d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu        setSharedElementEnterTransition(activity, sharedElementName, DEFAULT_TIMEOUT);
3909de363b8db05106b03d115c266859fe200d41db7Dake Gu    }
3919de363b8db05106b03d115c266859fe200d41db7Dake Gu
392d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    private int getDefaultBackgroundColor(Context context) {
393d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout        TypedValue outValue = new TypedValue();
39446443cb5b092f1d9156342645088eead9da026f6Dake Gu        if (context.getTheme().resolveAttribute(R.attr.defaultBrandColor, outValue, true)) {
39546443cb5b092f1d9156342645088eead9da026f6Dake Gu            return context.getResources().getColor(outValue.resourceId);
39646443cb5b092f1d9156342645088eead9da026f6Dake Gu        }
39746443cb5b092f1d9156342645088eead9da026f6Dake Gu        return context.getResources().getColor(R.color.lb_default_brand_color);
398d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    }
399d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout
400d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu    @Override
401cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout    protected void onRowViewSelected(RowPresenter.ViewHolder vh, boolean selected) {
402cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        super.onRowViewSelected(vh, selected);
403cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        if (selected) {
404cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            ((ViewHolder) vh).dispatchItemSelection(null);
405cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        }
406cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout    }
407cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout
408a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    @Override
409a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    protected RowPresenter.ViewHolder createRowViewHolder(ViewGroup parent) {
410a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        View v = LayoutInflater.from(parent.getContext())
411a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn            .inflate(R.layout.lb_details_overview, parent, false);
41218c8048f17940359b8bce99cb46d24337bff8997Dake Gu        ViewHolder vh = new ViewHolder(v, mDetailsPresenter);
413a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
41450ea3557b75826b3f51480715df1973472e345c4Craig Stout        initDetailsOverview(vh);
415d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout
416a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        return vh;
417a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    }
418a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
419e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout    private int getCardHeight(Context context) {
420d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout        int resId = mIsStyleLarge ? R.dimen.lb_details_overview_height_large :
421d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout            R.dimen.lb_details_overview_height_small;
422e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        return context.getResources().getDimensionPixelSize(resId);
423e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout    }
424d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout
42560bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout    private void initDetailsOverview(final ViewHolder vh) {
42671fddded48048acfa744ac352166770c91a1c2b1Dake Gu        vh.mActionBridgeAdapter = new ActionsItemBridgeAdapter(vh);
42726c145aadca16cba3f294cc93c36edc6e9c98e6aCraig Stout        final View overview = vh.mOverviewFrame;
42850ea3557b75826b3f51480715df1973472e345c4Craig Stout        ViewGroup.LayoutParams lp = overview.getLayoutParams();
429e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        lp.height = getCardHeight(overview.getContext());
43050ea3557b75826b3f51480715df1973472e345c4Craig Stout        overview.setLayoutParams(lp);
431d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout
43209d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout        if (!getSelectEffectEnabled()) {
43309d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout            vh.mOverviewFrame.setForeground(null);
43409d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout        }
43560bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        vh.mActionsRow.setOnUnhandledKeyListener(new BaseGridView.OnUnhandledKeyListener() {
43660bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            @Override
43760bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            public boolean onUnhandledKey(KeyEvent event) {
43860bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                if (vh.getOnKeyListener() != null) {
43960bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                    if (vh.getOnKeyListener().onKey(vh.view, event.getKeyCode(), event)) {
44060bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                        return true;
44160bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                    }
44260bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                }
44360bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                return false;
44460bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            }
44560bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        });
446d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    }
447d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout
4487728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout    private static int getNonNegativeWidth(Drawable drawable) {
4497728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout        final int width = (drawable == null) ? 0 : drawable.getIntrinsicWidth();
4507728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout        return (width > 0 ? width : 0);
4517728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout    }
4527728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout
4537728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout    private static int getNonNegativeHeight(Drawable drawable) {
4547728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout        final int height = (drawable == null) ? 0 : drawable.getIntrinsicHeight();
4557728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout        return (height > 0 ? height : 0);
4567728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout    }
4577728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout
458d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu    private void bindImageDrawable(ViewHolder vh) {
459d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu        DetailsOverviewRow row = (DetailsOverviewRow) vh.getRow();
460e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout
461e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        ViewGroup.MarginLayoutParams layoutParams =
462e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout                (ViewGroup.MarginLayoutParams) vh.mImageView.getLayoutParams();
463e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        final int cardHeight = getCardHeight(vh.mImageView.getContext());
464e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        final int verticalMargin = vh.mImageView.getResources().getDimensionPixelSize(
465e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout                R.dimen.lb_details_overview_image_margin_vertical);
466e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        final int horizontalMargin = vh.mImageView.getResources().getDimensionPixelSize(
467e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout                R.dimen.lb_details_overview_image_margin_horizontal);
4687728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout        final int drawableWidth = getNonNegativeWidth(row.getImageDrawable());
4697728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout        final int drawableHeight = getNonNegativeHeight(row.getImageDrawable());
4707728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout
471e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        boolean scaleImage = row.isImageScaleUpAllowed();
472e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        boolean useMargin = false;
473e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout
4747728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout        if (row.getImageDrawable() != null) {
4757728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            boolean landscape = false;
4767728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout
4777728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            // If large style and landscape image we always use margin.
4787728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            if (drawableWidth > drawableHeight) {
4797728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout                landscape = true;
4807728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout                if (mIsStyleLarge) {
4817728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout                    useMargin = true;
4827728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout                }
483e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            }
4847728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            // If long dimension bigger than the card height we scale down.
4857728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            if ((landscape && drawableWidth > cardHeight) ||
4867728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout                    (!landscape && drawableHeight > cardHeight)) {
487e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout                scaleImage = true;
488e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            }
4897728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            // If we're not scaling to fit the card height then we always use margin.
4907728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            if (!scaleImage) {
4917728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout                useMargin = true;
4927728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            }
4937728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            // If using margin than may need to scale down.
4947728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            if (useMargin && !scaleImage) {
4957728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout                if (landscape && drawableWidth > cardHeight - horizontalMargin) {
4967728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout                    scaleImage = true;
4977728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout                } else if (!landscape && drawableHeight > cardHeight - 2 * verticalMargin) {
4987728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout                    scaleImage = true;
4997728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout                }
5007728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            }
501e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        }
502e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout
5034f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout        final int bgColor = mBackgroundColorSet ? mBackgroundColor :
5044f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout            getDefaultBackgroundColor(vh.mOverviewView.getContext());
5054f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout
506e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        if (useMargin) {
5074e602840ed6741b44a536826799625ad0be4b3c6Kris Giesing            layoutParams.setMarginStart(horizontalMargin);
508e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            layoutParams.topMargin = layoutParams.bottomMargin = verticalMargin;
50926c145aadca16cba3f294cc93c36edc6e9c98e6aCraig Stout            RoundedRectHelper.getInstance().setRoundedRectBackground(vh.mOverviewFrame, bgColor);
51072a2146f4c3e6dbb84a5f9f92e7ab42d142dab04Dake Gu            vh.mRightPanel.setBackground(null);
511836443f4a3b69eb7a88ffeb65a39e11439dee55eDake Gu            vh.mImageView.setBackground(null);
512e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        } else {
513e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            layoutParams.leftMargin = layoutParams.topMargin = layoutParams.bottomMargin = 0;
5144f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout            vh.mRightPanel.setBackgroundColor(bgColor);
5154f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout            vh.mImageView.setBackgroundColor(bgColor);
51626c145aadca16cba3f294cc93c36edc6e9c98e6aCraig Stout            RoundedRectHelper.getInstance().setRoundedRectBackground(vh.mOverviewFrame,
5174f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout                    Color.TRANSPARENT);
518e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        }
519e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        if (scaleImage) {
520e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            vh.mImageView.setScaleType(ImageView.ScaleType.FIT_START);
521e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            vh.mImageView.setAdjustViewBounds(true);
522e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            vh.mImageView.setMaxWidth(cardHeight);
523e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
524e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT;
525e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        } else {
526e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            vh.mImageView.setScaleType(ImageView.ScaleType.CENTER);
527e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            vh.mImageView.setAdjustViewBounds(false);
528e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
529e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            // Limit width to the card height
5307728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            layoutParams.width = Math.min(cardHeight, drawableWidth);
531e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        }
532e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        vh.mImageView.setLayoutParams(layoutParams);
533e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        vh.mImageView.setImageDrawable(row.getImageDrawable());
5344121f22713bbed467a977ec0d867ef53989ff374Dake Gu        if (row.getImageDrawable() != null && mSharedElementHelper != null) {
5354121f22713bbed467a977ec0d867ef53989ff374Dake Gu            mSharedElementHelper.onBindToDrawable(vh);
5364121f22713bbed467a977ec0d867ef53989ff374Dake Gu        }
537a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    }
538a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
539a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    @Override
540d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu    protected void onBindRowViewHolder(RowPresenter.ViewHolder holder, Object item) {
541d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu        super.onBindRowViewHolder(holder, item);
542d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu
543d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu        DetailsOverviewRow row = (DetailsOverviewRow) item;
544d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu        ViewHolder vh = (ViewHolder) holder;
545d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu
546d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu        bindImageDrawable(vh);
547d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu        mDetailsPresenter.onBindViewHolder(vh.mDetailsDescriptionViewHolder, row.getItem());
548d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu        vh.bindActions(row.getActionsAdapter());
549d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu        row.addListener(vh.mListener);
550d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu    }
551d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu
552d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu    @Override
553cb13a318e577e14461eb008071dddf762847de42Dake Gu    protected void onUnbindRowViewHolder(RowPresenter.ViewHolder holder) {
554a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        ViewHolder vh = (ViewHolder) holder;
555d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu        DetailsOverviewRow dor = (DetailsOverviewRow) vh.getRow();
556d825ff3727407a154a35e20b3a9adc79e57879b9Dake Gu        dor.removeListener(vh.mListener);
557a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        if (vh.mDetailsDescriptionViewHolder != null) {
558a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn            mDetailsPresenter.onUnbindViewHolder(vh.mDetailsDescriptionViewHolder);
559a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        }
560fc8f0f06c93c224d86b85c8b9f7ae737968fd797Dake Gu        super.onUnbindRowViewHolder(holder);
561a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    }
56209d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout
56309d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout    @Override
56409d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout    public final boolean isUsingDefaultSelectEffect() {
56509d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout        return false;
56609d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout    }
56709d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout
56809d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout    @Override
56909d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout    protected void onSelectLevelChanged(RowPresenter.ViewHolder holder) {
57009d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout        super.onSelectLevelChanged(holder);
57109d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout        if (getSelectEffectEnabled()) {
57209d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout            ViewHolder vh = (ViewHolder) holder;
57309d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout            int dimmedColor = vh.mColorDimmer.getPaint().getColor();
57409d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout            ((ColorDrawable) vh.mOverviewFrame.getForeground().mutate()).setColor(dimmedColor);
57509d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout        }
57609d52d76912e3689cc2b58b7bb3f44b923915fd8Craig Stout    }
57726d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout
57826d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout    @Override
57926d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout    protected void onRowViewAttachedToWindow(RowPresenter.ViewHolder vh) {
58026d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout        super.onRowViewAttachedToWindow(vh);
58126d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout        if (mDetailsPresenter != null) {
58226d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout            mDetailsPresenter.onViewAttachedToWindow(
58326d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout                    ((ViewHolder) vh).mDetailsDescriptionViewHolder);
58426d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout        }
58526d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout    }
58626d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout
58726d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout    @Override
58826d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout    protected void onRowViewDetachedFromWindow(RowPresenter.ViewHolder vh) {
58926d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout        super.onRowViewDetachedFromWindow(vh);
59026d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout        if (mDetailsPresenter != null) {
59126d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout            mDetailsPresenter.onViewDetachedFromWindow(
59226d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout                    ((ViewHolder) vh).mDetailsDescriptionViewHolder);
59326d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout        }
59426d11212c4a66b075807888caacac5ee7fc10dc1Craig Stout    }
595a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn}
596