DetailsOverviewRowPresenter.java revision d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4
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;
22a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournimport android.support.v17.leanback.R;
232e0c922430f8c285b4325da52d69c09451069c93Craig Stoutimport android.support.v7.widget.RecyclerView;
242e0c922430f8c285b4325da52d69c09451069c93Craig Stoutimport android.util.Log;
25d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stoutimport android.util.TypedValue;
26a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournimport android.view.LayoutInflater;
27a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournimport android.view.View;
28a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournimport android.view.ViewGroup;
29a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournimport android.widget.FrameLayout;
30a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournimport android.widget.ImageView;
31a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
32a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournimport java.util.Collection;
33a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
34a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn/**
3580d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn * A DetailsOverviewRowPresenter renders a {@link DetailsOverviewRow} to display an
36a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn * overview of an item. Typically this row will be the first row in a fragment
3780d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn * such as the {@link android.support.v17.leanback.app.DetailsFragment
3818c8048f17940359b8bce99cb46d24337bff8997Dake Gu * DetailsFragment}.  View created by DetailsOverviewRowPresenter is made in three parts:
3918c8048f17940359b8bce99cb46d24337bff8997Dake Gu * ImageView on the left, action list view on the bottom and a customizable detailed
4018c8048f17940359b8bce99cb46d24337bff8997Dake Gu * description view on the right.
41a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn *
4218c8048f17940359b8bce99cb46d24337bff8997Dake Gu * <p>The detailed description is rendered using a {@link Presenter} passed in
4318c8048f17940359b8bce99cb46d24337bff8997Dake Gu * {@link #DetailsOverviewRowPresenter(Presenter)}.  User can access detailed description
4418c8048f17940359b8bce99cb46d24337bff8997Dake Gu * ViewHolder from {@link ViewHolder#mDetailsDescriptionViewHolder}.
4518c8048f17940359b8bce99cb46d24337bff8997Dake Gu * </p>
4618c8048f17940359b8bce99cb46d24337bff8997Dake Gu *
4718c8048f17940359b8bce99cb46d24337bff8997Dake Gu * <p>
4818c8048f17940359b8bce99cb46d24337bff8997Dake Gu * To participate in activity transition, call {@link #setSharedElementEnterTransition(Activity,
4918c8048f17940359b8bce99cb46d24337bff8997Dake Gu * String)} during Activity's onCreate().
5018c8048f17940359b8bce99cb46d24337bff8997Dake Gu * </p>
5118c8048f17940359b8bce99cb46d24337bff8997Dake Gu *
5218c8048f17940359b8bce99cb46d24337bff8997Dake Gu * <p>
5318c8048f17940359b8bce99cb46d24337bff8997Dake Gu * Because transition support and layout are fully controlled by DetailsOverviewRowPresenter,
5418c8048f17940359b8bce99cb46d24337bff8997Dake Gu * developer can not override DetailsOverviewRowPresenter.ViewHolder for adding/replacing views
5518c8048f17940359b8bce99cb46d24337bff8997Dake Gu * of DetailsOverviewRowPresenter.  If developer wants more customization beyond replacing
5618c8048f17940359b8bce99cb46d24337bff8997Dake Gu * detailed description , he/she should write a new presenter class for row object.
5718c8048f17940359b8bce99cb46d24337bff8997Dake Gu * </p>
58a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn */
59a83005b70853ea52c5d98910762344de16b850a8Tim Kilbournpublic class DetailsOverviewRowPresenter extends RowPresenter {
60a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
61a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    private static final String TAG = "DetailsOverviewRowPresenter";
62a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    private static final boolean DEBUG = false;
63a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
642e0c922430f8c285b4325da52d69c09451069c93Craig Stout    private static final int MORE_ACTIONS_FADE_MS = 100;
65d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu    private static final long DEFAULT_TIMEOUT = 5000;
662e0c922430f8c285b4325da52d69c09451069c93Craig Stout
6780d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn    /**
6880d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     * A ViewHolder for the DetailsOverviewRow.
6980d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     */
70cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout    public final class ViewHolder extends RowPresenter.ViewHolder {
71b34a2372153298ebdc3e148e1c1f3b3924efab08Dake Gu        final ViewGroup mOverviewView;
72a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        final ImageView mImageView;
734121f22713bbed467a977ec0d867ef53989ff374Dake Gu        final ViewGroup mRightPanel;
74a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        final FrameLayout mDetailsDescriptionFrame;
75a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        final HorizontalGridView mActionsRow;
7618c8048f17940359b8bce99cb46d24337bff8997Dake Gu        public final Presenter.ViewHolder mDetailsDescriptionViewHolder;
7783118b72d02074ee35f07ad0253579565c16882bCraig Stout        int mNumItems;
7883118b72d02074ee35f07ad0253579565c16882bCraig Stout        boolean mShowMoreRight;
7983118b72d02074ee35f07ad0253579565c16882bCraig Stout        boolean mShowMoreLeft;
80cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        final ItemBridgeAdapter mActionBridgeAdapter = new ItemBridgeAdapter();
81a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
82cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        void bind(ObjectAdapter adapter) {
83cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            mActionBridgeAdapter.setAdapter(adapter);
8437eb0e53ba5363bbe15314c7d19d4b2d6024a5aaDake Gu            mActionsRow.setAdapter(mActionBridgeAdapter);
85cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            mNumItems = mActionBridgeAdapter.getItemCount();
862e0c922430f8c285b4325da52d69c09451069c93Craig Stout
8783118b72d02074ee35f07ad0253579565c16882bCraig Stout            mShowMoreRight = false;
8883118b72d02074ee35f07ad0253579565c16882bCraig Stout            mShowMoreLeft = true;
8983118b72d02074ee35f07ad0253579565c16882bCraig Stout            showMoreLeft(false);
9083118b72d02074ee35f07ad0253579565c16882bCraig Stout        }
9183118b72d02074ee35f07ad0253579565c16882bCraig Stout
92819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout        final View.OnLayoutChangeListener mLayoutChangeListener =
93819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout                new View.OnLayoutChangeListener() {
94819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout
95819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout            @Override
96819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout            public void onLayoutChange(View v, int left, int top, int right,
97819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout                    int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
98819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout                if (DEBUG) Log.v(TAG, "onLayoutChange " + v);
99819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout                checkFirstAndLastPosition(false);
100819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout            }
101819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout        };
102819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout
103cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        final OnChildSelectedListener mChildSelectedListener = new OnChildSelectedListener() {
104cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            @Override
105cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            public void onChildSelected(ViewGroup parent, View view, int position, long id) {
106cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                dispatchItemSelection(view);
107cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            }
108cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        };
109cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout
110cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        void dispatchItemSelection(View view) {
111cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            if (!isSelected()) {
112cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                return;
113cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            }
114cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            ItemBridgeAdapter.ViewHolder ibvh = (ItemBridgeAdapter.ViewHolder) (view != null ?
115cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                    mActionsRow.getChildViewHolder(view) :
116cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                    mActionsRow.findViewHolderForPosition(mActionsRow.getSelectedPosition()));
117cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            if (ibvh == null) {
118cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                if (getOnItemSelectedListener() != null) {
119cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                    getOnItemSelectedListener().onItemSelected(null, getRow());
120cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                }
121cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                if (getOnItemViewSelectedListener() != null) {
122cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                    getOnItemViewSelectedListener().onItemSelected(null, null,
123cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                            ViewHolder.this, getRow());
124cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                }
125cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            } else {
126cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                if (getOnItemSelectedListener() != null) {
127cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                    getOnItemSelectedListener().onItemSelected(ibvh.getItem(), getRow());
128cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                }
129cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                if (getOnItemViewSelectedListener() != null) {
130cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                    getOnItemViewSelectedListener().onItemSelected(ibvh.getViewHolder(), ibvh.getItem(),
131cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                            ViewHolder.this, getRow());
132cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                }
133cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            }
134cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        };
135cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout
13683118b72d02074ee35f07ad0253579565c16882bCraig Stout        final ItemBridgeAdapter.AdapterListener mAdapterListener =
13783118b72d02074ee35f07ad0253579565c16882bCraig Stout                new ItemBridgeAdapter.AdapterListener() {
1382e0c922430f8c285b4325da52d69c09451069c93Craig Stout
13983118b72d02074ee35f07ad0253579565c16882bCraig Stout            @Override
140cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            public void onBind(final ItemBridgeAdapter.ViewHolder ibvh) {
141cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                if (getOnItemViewClickedListener() != null || getOnItemClickedListener() != null
142cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                        || mActionClickedListener != null) {
143cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                    ibvh.getPresenter().setOnClickListener(
144cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                            ibvh.getViewHolder(), new View.OnClickListener() {
145cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                                @Override
146cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                                public void onClick(View v) {
147cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                                    if (getOnItemViewClickedListener() != null) {
148cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                                        getOnItemViewClickedListener().onItemClicked(ibvh.getViewHolder(),
149cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                                                ibvh.getItem(), ViewHolder.this, getRow());
150cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                                    }
151cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                                    if (mActionClickedListener != null) {
152cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                                        mActionClickedListener.onActionClicked((Action) ibvh.getItem());
153cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                                    }
154cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                                }
155cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                            });
156cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                }
157cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            }
158cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            @Override
159cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            public void onUnbind(final ItemBridgeAdapter.ViewHolder ibvh) {
160cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                if (getOnItemViewClickedListener() != null || getOnItemClickedListener() != null
161cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                        || mActionClickedListener != null) {
162cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                    ibvh.getPresenter().setOnClickListener(ibvh.getViewHolder(), null);
163cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout                }
164cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            }
165cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            @Override
16683118b72d02074ee35f07ad0253579565c16882bCraig Stout            public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder viewHolder) {
167819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout                // Remove first to ensure we don't add ourselves more than once.
168819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout                viewHolder.itemView.removeOnLayoutChangeListener(mLayoutChangeListener);
169819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout                viewHolder.itemView.addOnLayoutChangeListener(mLayoutChangeListener);
17083118b72d02074ee35f07ad0253579565c16882bCraig Stout            }
17183118b72d02074ee35f07ad0253579565c16882bCraig Stout            @Override
17283118b72d02074ee35f07ad0253579565c16882bCraig Stout            public void onDetachedFromWindow(ItemBridgeAdapter.ViewHolder viewHolder) {
173819b4e55bcf37847548a55c5dac0dfa8323975f6Craig Stout                viewHolder.itemView.removeOnLayoutChangeListener(mLayoutChangeListener);
17483118b72d02074ee35f07ad0253579565c16882bCraig Stout                checkFirstAndLastPosition(false);
1752e0c922430f8c285b4325da52d69c09451069c93Craig Stout            }
17683118b72d02074ee35f07ad0253579565c16882bCraig Stout        };
17783118b72d02074ee35f07ad0253579565c16882bCraig Stout
17883118b72d02074ee35f07ad0253579565c16882bCraig Stout        final RecyclerView.OnScrollListener mScrollListener =
17983118b72d02074ee35f07ad0253579565c16882bCraig Stout                new RecyclerView.OnScrollListener() {
1802e0c922430f8c285b4325da52d69c09451069c93Craig Stout
1812e0c922430f8c285b4325da52d69c09451069c93Craig Stout            @Override
182cef7b4942bacc862ea4eac66952e9f7aba027d18Yigit Boyar            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
1832e0c922430f8c285b4325da52d69c09451069c93Craig Stout            }
1842e0c922430f8c285b4325da52d69c09451069c93Craig Stout            @Override
185cef7b4942bacc862ea4eac66952e9f7aba027d18Yigit Boyar            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
18683118b72d02074ee35f07ad0253579565c16882bCraig Stout                checkFirstAndLastPosition(true);
1872e0c922430f8c285b4325da52d69c09451069c93Craig Stout            }
18883118b72d02074ee35f07ad0253579565c16882bCraig Stout        };
18983118b72d02074ee35f07ad0253579565c16882bCraig Stout
19083118b72d02074ee35f07ad0253579565c16882bCraig Stout        private int getViewCenter(View view) {
19183118b72d02074ee35f07ad0253579565c16882bCraig Stout            return (view.getRight() - view.getLeft()) / 2;
19283118b72d02074ee35f07ad0253579565c16882bCraig Stout        }
19383118b72d02074ee35f07ad0253579565c16882bCraig Stout
19483118b72d02074ee35f07ad0253579565c16882bCraig Stout        private void checkFirstAndLastPosition(boolean fromScroll) {
19583118b72d02074ee35f07ad0253579565c16882bCraig Stout            RecyclerView.ViewHolder viewHolder;
1962e0c922430f8c285b4325da52d69c09451069c93Craig Stout
19783118b72d02074ee35f07ad0253579565c16882bCraig Stout            viewHolder = mActionsRow.findViewHolderForPosition(mNumItems - 1);
19883118b72d02074ee35f07ad0253579565c16882bCraig Stout            boolean showRight = (viewHolder == null ||
19983118b72d02074ee35f07ad0253579565c16882bCraig Stout                    viewHolder.itemView.getRight() > mActionsRow.getWidth());
20083118b72d02074ee35f07ad0253579565c16882bCraig Stout
20183118b72d02074ee35f07ad0253579565c16882bCraig Stout            viewHolder = mActionsRow.findViewHolderForPosition(0);
20283118b72d02074ee35f07ad0253579565c16882bCraig Stout            boolean showLeft = (viewHolder == null || viewHolder.itemView.getLeft() < 0);
20383118b72d02074ee35f07ad0253579565c16882bCraig Stout
20483118b72d02074ee35f07ad0253579565c16882bCraig Stout            if (DEBUG) Log.v(TAG, "checkFirstAndLast fromScroll " + fromScroll +
20583118b72d02074ee35f07ad0253579565c16882bCraig Stout                    " showRight " + showRight + " showLeft " + showLeft);
20683118b72d02074ee35f07ad0253579565c16882bCraig Stout
20783118b72d02074ee35f07ad0253579565c16882bCraig Stout            showMoreRight(showRight);
20883118b72d02074ee35f07ad0253579565c16882bCraig Stout            showMoreLeft(showLeft);
20983118b72d02074ee35f07ad0253579565c16882bCraig Stout        }
21083118b72d02074ee35f07ad0253579565c16882bCraig Stout
21183118b72d02074ee35f07ad0253579565c16882bCraig Stout        private void showMoreLeft(boolean show) {
21283118b72d02074ee35f07ad0253579565c16882bCraig Stout            if (show != mShowMoreLeft) {
21383118b72d02074ee35f07ad0253579565c16882bCraig Stout                mActionsRow.setFadingLeftEdge(show);
21483118b72d02074ee35f07ad0253579565c16882bCraig Stout                mShowMoreLeft = show;
2152e0c922430f8c285b4325da52d69c09451069c93Craig Stout            }
21683118b72d02074ee35f07ad0253579565c16882bCraig Stout        }
2172e0c922430f8c285b4325da52d69c09451069c93Craig Stout
21883118b72d02074ee35f07ad0253579565c16882bCraig Stout        private void showMoreRight(boolean show) {
21983118b72d02074ee35f07ad0253579565c16882bCraig Stout            if (show != mShowMoreRight) {
22083118b72d02074ee35f07ad0253579565c16882bCraig Stout                mActionsRow.setFadingRightEdge(show);
22183118b72d02074ee35f07ad0253579565c16882bCraig Stout                mShowMoreRight = show;
2222e0c922430f8c285b4325da52d69c09451069c93Craig Stout            }
2232e0c922430f8c285b4325da52d69c09451069c93Craig Stout        }
2242e0c922430f8c285b4325da52d69c09451069c93Craig Stout
22580d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn        /**
22680d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn         * Constructor for the ViewHolder.
22780d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn         *
22880d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn         * @param rootView The root View that this view holder will be attached
22980d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn         *        to.
23080d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn         */
23118c8048f17940359b8bce99cb46d24337bff8997Dake Gu        public ViewHolder(View rootView, Presenter detailsPresenter) {
232a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn            super(rootView);
233b34a2372153298ebdc3e148e1c1f3b3924efab08Dake Gu            mOverviewView = (ViewGroup) rootView.findViewById(R.id.details_overview);
234a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn            mImageView = (ImageView) rootView.findViewById(R.id.details_overview_image);
2354121f22713bbed467a977ec0d867ef53989ff374Dake Gu            mRightPanel = (ViewGroup) rootView.findViewById(R.id.details_overview_right_panel);
236a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn            mDetailsDescriptionFrame =
2374121f22713bbed467a977ec0d867ef53989ff374Dake Gu                    (FrameLayout) mRightPanel.findViewById(R.id.details_overview_description);
23870c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn            mActionsRow =
2394121f22713bbed467a977ec0d867ef53989ff374Dake Gu                    (HorizontalGridView) mRightPanel.findViewById(R.id.details_overview_actions);
240ceb7ab2ddd6e157cd4ade0f14a382c39428163c4Dake Gu            mActionsRow.setHasOverlappingRendering(false);
2412e0c922430f8c285b4325da52d69c09451069c93Craig Stout            mActionsRow.setOnScrollListener(mScrollListener);
242cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            mActionsRow.setAdapter(mActionBridgeAdapter);
243cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            mActionsRow.setOnChildSelectedListener(mChildSelectedListener);
2442e0c922430f8c285b4325da52d69c09451069c93Craig Stout
2452e0c922430f8c285b4325da52d69c09451069c93Craig Stout            final int fadeLength = rootView.getResources().getDimensionPixelSize(
2462e0c922430f8c285b4325da52d69c09451069c93Craig Stout                    R.dimen.lb_details_overview_actions_fade_size);
2472e0c922430f8c285b4325da52d69c09451069c93Craig Stout            mActionsRow.setFadingRightEdgeLength(fadeLength);
2482e0c922430f8c285b4325da52d69c09451069c93Craig Stout            mActionsRow.setFadingLeftEdgeLength(fadeLength);
24918c8048f17940359b8bce99cb46d24337bff8997Dake Gu            mDetailsDescriptionViewHolder =
25018c8048f17940359b8bce99cb46d24337bff8997Dake Gu                    detailsPresenter.onCreateViewHolder(mDetailsDescriptionFrame);
25118c8048f17940359b8bce99cb46d24337bff8997Dake Gu            mDetailsDescriptionFrame.addView(mDetailsDescriptionViewHolder.view);
252cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout
253cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            mActionBridgeAdapter.setAdapterListener(mAdapterListener);
254a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        }
255a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    }
256a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
257c62efa44831b1c60dcbdfd968735e27ac8294439Craig Stout    private static float sShadowZ;
258c62efa44831b1c60dcbdfd968735e27ac8294439Craig Stout
259a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    private final Presenter mDetailsPresenter;
26070c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn    private final ActionPresenterSelector mActionPresenterSelector;
261cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout    private OnActionClickedListener mActionClickedListener;
262cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout
263d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    private int mBackgroundColor = Color.TRANSPARENT;
264d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    private boolean mBackgroundColorSet;
265d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    private boolean mIsStyleLarge = true;
266a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
2674121f22713bbed467a977ec0d867ef53989ff374Dake Gu    private DetailsOverviewSharedElementHelper mSharedElementHelper;
2684121f22713bbed467a977ec0d867ef53989ff374Dake Gu
269a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    /**
27080d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     * Constructor for a DetailsOverviewRowPresenter.
27180d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     *
27280d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     * @param detailsPresenter The {@link Presenter} used to render the detailed
27380d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     *        description of the row.
274a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn     */
275a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    public DetailsOverviewRowPresenter(Presenter detailsPresenter) {
276d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout        setHeaderPresenter(null);
277a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        setSelectEffectEnabled(false);
278a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        mDetailsPresenter = detailsPresenter;
279e652714f2fcc876de6f168b28dd03bfc22e1cb96Tim Kilbourn        mActionPresenterSelector = new ActionPresenterSelector();
280a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    }
281a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
28270c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn    /**
28380d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     * Sets the listener for Action click events.
28470c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn     */
28570c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn    public void setOnActionClickedListener(OnActionClickedListener listener) {
286cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        mActionClickedListener = listener;
28770c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn    }
28870c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn
28970c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn    /**
29080d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     * Gets the listener for Action click events.
29170c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn     */
29270c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn    public OnActionClickedListener getOnActionClickedListener() {
293cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        return mActionClickedListener;
29470c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn    }
29570c858a5ca5b7ed9862e2edfa43912faecf42f96Tim Kilbourn
296d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    /**
29780d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     * Sets the background color.  If not set, a default from the theme will be used.
298d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout     */
299d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    public void setBackgroundColor(int color) {
300d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout        mBackgroundColor = color;
301d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout        mBackgroundColorSet = true;
302d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    }
303d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout
304d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    /**
30580d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     * Returns the background color.  If no background color was set, transparent
30680d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     * is returned.
307d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout     */
308d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    public int getBackgroundColor() {
309d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout        return mBackgroundColor;
310d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    }
311d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout
312d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    /**
31380d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     * Sets the layout style to be large or small. This affects the height of
31480d04d2265fe28800fcbc7e8cc7d6d229a7913d8Tim Kilbourn     * the overview, including the text description. The default is large.
315d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout     */
316d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    public void setStyleLarge(boolean large) {
317d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout        mIsStyleLarge = large;
318d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    }
319d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout
320d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    /**
321d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout     * Returns true if the layout style is large.
322d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout     */
323d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    public boolean isStyleLarge() {
324d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout        return mIsStyleLarge;
325d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    }
326d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout
3279de363b8db05106b03d115c266859fe200d41db7Dake Gu    /**
3284121f22713bbed467a977ec0d867ef53989ff374Dake Gu     * Set enter transition of target activity (typically a DetailActivity) to be
329d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * transiting into overview row created by this presenter.  The transition will
330d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * be cancelled if overview image is not loaded in the timeout period.
3314121f22713bbed467a977ec0d867ef53989ff374Dake Gu     * <p>
3324121f22713bbed467a977ec0d867ef53989ff374Dake Gu     * It assumes shared element passed from calling activity is an ImageView;
3334121f22713bbed467a977ec0d867ef53989ff374Dake Gu     * the shared element transits to overview image on the left of detail
3344121f22713bbed467a977ec0d867ef53989ff374Dake Gu     * overview row, while bounds of overview row grows and reveals text
3354121f22713bbed467a977ec0d867ef53989ff374Dake Gu     * and buttons on the right.
3364121f22713bbed467a977ec0d867ef53989ff374Dake Gu     * <p>
3374121f22713bbed467a977ec0d867ef53989ff374Dake Gu     * The method must be invoked in target Activity's onCreate().
3389de363b8db05106b03d115c266859fe200d41db7Dake Gu     */
3394121f22713bbed467a977ec0d867ef53989ff374Dake Gu    public final void setSharedElementEnterTransition(Activity activity,
340d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu            String sharedElementName, long timeoutMs) {
3414121f22713bbed467a977ec0d867ef53989ff374Dake Gu        if (mSharedElementHelper == null) {
3424121f22713bbed467a977ec0d867ef53989ff374Dake Gu            mSharedElementHelper = new DetailsOverviewSharedElementHelper();
3434121f22713bbed467a977ec0d867ef53989ff374Dake Gu        }
344d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu        mSharedElementHelper.setSharedElementEnterTransition(activity, sharedElementName,
345d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu                timeoutMs);
346d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu    }
347d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu
348d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu    /**
349d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * Set enter transition of target activity (typically a DetailActivity) to be
350d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * transiting into overview row created by this presenter.  The transition will
351d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * be cancelled if overview image is not loaded in a default timeout period.
352d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * <p>
353d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * It assumes shared element passed from calling activity is an ImageView;
354d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * the shared element transits to overview image on the left of detail
355d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * overview row, while bounds of overview row grows and reveals text
356d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * and buttons on the right.
357d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * <p>
358d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     * The method must be invoked in target Activity's onCreate().
359d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu     */
360d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu    public final void setSharedElementEnterTransition(Activity activity,
361d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu            String sharedElementName) {
362d391b19d1bf663ce300b0f4550e6fbaa7e12b0d4Dake Gu        setSharedElementEnterTransition(activity, sharedElementName, DEFAULT_TIMEOUT);
3639de363b8db05106b03d115c266859fe200d41db7Dake Gu    }
3649de363b8db05106b03d115c266859fe200d41db7Dake Gu
365d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    private int getDefaultBackgroundColor(Context context) {
366d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout        TypedValue outValue = new TypedValue();
367056561d81012983d2d27b8665c4aeabb427174cbTim Kilbourn        context.getTheme().resolveAttribute(R.attr.defaultBrandColor, outValue, true);
368d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout        return context.getResources().getColor(outValue.resourceId);
369d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    }
370d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout
371cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout    protected void onRowViewSelected(RowPresenter.ViewHolder vh, boolean selected) {
372cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        super.onRowViewSelected(vh, selected);
373cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        if (selected) {
374cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout            ((ViewHolder) vh).dispatchItemSelection(null);
375cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        }
376cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout    }
377cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout
378a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    @Override
379a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    protected RowPresenter.ViewHolder createRowViewHolder(ViewGroup parent) {
380a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        View v = LayoutInflater.from(parent.getContext())
381a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn            .inflate(R.layout.lb_details_overview, parent, false);
38218c8048f17940359b8bce99cb46d24337bff8997Dake Gu        ViewHolder vh = new ViewHolder(v, mDetailsPresenter);
383a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
38450ea3557b75826b3f51480715df1973472e345c4Craig Stout        initDetailsOverview(vh);
385d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout
386a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        return vh;
387a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    }
388a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
389e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout    private int getCardHeight(Context context) {
390d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout        int resId = mIsStyleLarge ? R.dimen.lb_details_overview_height_large :
391d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout            R.dimen.lb_details_overview_height_small;
392e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        return context.getResources().getDimensionPixelSize(resId);
393e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout    }
394d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout
395e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout    private void initDetailsOverview(ViewHolder vh) {
3964f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout        final View overview = vh.mOverviewView;
39750ea3557b75826b3f51480715df1973472e345c4Craig Stout        ViewGroup.LayoutParams lp = overview.getLayoutParams();
398e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        lp.height = getCardHeight(overview.getContext());
39950ea3557b75826b3f51480715df1973472e345c4Craig Stout        overview.setLayoutParams(lp);
400d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout
401c62efa44831b1c60dcbdfd968735e27ac8294439Craig Stout        if (sShadowZ == 0) {
402c62efa44831b1c60dcbdfd968735e27ac8294439Craig Stout            sShadowZ = overview.getResources().getDimensionPixelSize(
403c62efa44831b1c60dcbdfd968735e27ac8294439Craig Stout                    R.dimen.lb_details_overview_z);
404c62efa44831b1c60dcbdfd968735e27ac8294439Craig Stout        }
405c62efa44831b1c60dcbdfd968735e27ac8294439Craig Stout        ShadowHelper.getInstance().setZ(overview, sShadowZ);
406d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout    }
407d2c235afaa4119599fd8bfc9bff65c5af9a8fdc1Craig Stout
4087728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout    private static int getNonNegativeWidth(Drawable drawable) {
4097728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout        final int width = (drawable == null) ? 0 : drawable.getIntrinsicWidth();
4107728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout        return (width > 0 ? width : 0);
4117728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout    }
4127728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout
4137728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout    private static int getNonNegativeHeight(Drawable drawable) {
4147728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout        final int height = (drawable == null) ? 0 : drawable.getIntrinsicHeight();
4157728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout        return (height > 0 ? height : 0);
4167728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout    }
4177728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout
418a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    @Override
419cb13a318e577e14461eb008071dddf762847de42Dake Gu    protected void onBindRowViewHolder(RowPresenter.ViewHolder holder, Object item) {
420cb13a318e577e14461eb008071dddf762847de42Dake Gu        super.onBindRowViewHolder(holder, item);
421a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
422a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        DetailsOverviewRow row = (DetailsOverviewRow) item;
423a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        ViewHolder vh = (ViewHolder) holder;
424e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout
425e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        ViewGroup.MarginLayoutParams layoutParams =
426e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout                (ViewGroup.MarginLayoutParams) vh.mImageView.getLayoutParams();
427e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        final int cardHeight = getCardHeight(vh.mImageView.getContext());
428e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        final int verticalMargin = vh.mImageView.getResources().getDimensionPixelSize(
429e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout                R.dimen.lb_details_overview_image_margin_vertical);
430e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        final int horizontalMargin = vh.mImageView.getResources().getDimensionPixelSize(
431e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout                R.dimen.lb_details_overview_image_margin_horizontal);
4327728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout        final int drawableWidth = getNonNegativeWidth(row.getImageDrawable());
4337728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout        final int drawableHeight = getNonNegativeHeight(row.getImageDrawable());
4347728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout
435e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        boolean scaleImage = row.isImageScaleUpAllowed();
436e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        boolean useMargin = false;
437e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout
4387728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout        if (row.getImageDrawable() != null) {
4397728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            boolean landscape = false;
4407728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout
4417728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            // If large style and landscape image we always use margin.
4427728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            if (drawableWidth > drawableHeight) {
4437728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout                landscape = true;
4447728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout                if (mIsStyleLarge) {
4457728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout                    useMargin = true;
4467728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout                }
447e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            }
4487728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            // If long dimension bigger than the card height we scale down.
4497728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            if ((landscape && drawableWidth > cardHeight) ||
4507728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout                    (!landscape && drawableHeight > cardHeight)) {
451e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout                scaleImage = true;
452e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            }
4537728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            // If we're not scaling to fit the card height then we always use margin.
4547728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            if (!scaleImage) {
4557728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout                useMargin = true;
4567728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            }
4577728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            // If using margin than may need to scale down.
4587728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            if (useMargin && !scaleImage) {
4597728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout                if (landscape && drawableWidth > cardHeight - horizontalMargin) {
4607728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout                    scaleImage = true;
4617728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout                } else if (!landscape && drawableHeight > cardHeight - 2 * verticalMargin) {
4627728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout                    scaleImage = true;
4637728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout                }
4647728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            }
465e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        }
466e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout
4674f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout        final int bgColor = mBackgroundColorSet ? mBackgroundColor :
4684f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout            getDefaultBackgroundColor(vh.mOverviewView.getContext());
4694f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout
470e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        if (useMargin) {
471e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            layoutParams.leftMargin = horizontalMargin;
472e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            layoutParams.topMargin = layoutParams.bottomMargin = verticalMargin;
4734f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout            RoundedRectHelper.getInstance().setRoundedRectBackground(vh.mOverviewView, bgColor);
47472a2146f4c3e6dbb84a5f9f92e7ab42d142dab04Dake Gu            vh.mRightPanel.setBackground(null);
475836443f4a3b69eb7a88ffeb65a39e11439dee55eDake Gu            vh.mImageView.setBackground(null);
476e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        } else {
477e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            layoutParams.leftMargin = layoutParams.topMargin = layoutParams.bottomMargin = 0;
4784f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout            vh.mRightPanel.setBackgroundColor(bgColor);
4794f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout            vh.mImageView.setBackgroundColor(bgColor);
4804f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout            RoundedRectHelper.getInstance().setRoundedRectBackground(vh.mOverviewView,
4814f34a05cdf73b68c3b2eb8678f740ab15225126aCraig Stout                    Color.TRANSPARENT);
482e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        }
483e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        if (scaleImage) {
484e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            vh.mImageView.setScaleType(ImageView.ScaleType.FIT_START);
485e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            vh.mImageView.setAdjustViewBounds(true);
486e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            vh.mImageView.setMaxWidth(cardHeight);
487e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
488e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT;
489e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        } else {
490e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            vh.mImageView.setScaleType(ImageView.ScaleType.CENTER);
491e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            vh.mImageView.setAdjustViewBounds(false);
492e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
493e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout            // Limit width to the card height
4947728d53c5c50e8ed807e8f4a189e34684de04800Craig Stout            layoutParams.width = Math.min(cardHeight, drawableWidth);
495e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        }
496e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        vh.mImageView.setLayoutParams(layoutParams);
497e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout        vh.mImageView.setImageDrawable(row.getImageDrawable());
498e23ea69ec54eb70d17239ba671fcd75563780553Craig Stout
4997d1196948811bc5f1b7ec0cdc74340fca60fc8e2Craig Stout        mDetailsPresenter.onBindViewHolder(vh.mDetailsDescriptionViewHolder, row.getItem());
500a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
501e652714f2fcc876de6f168b28dd03bfc22e1cb96Tim Kilbourn        ArrayObjectAdapter aoa = new ArrayObjectAdapter(mActionPresenterSelector);
502a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        aoa.addAll(0, (Collection)row.getActions());
503cf992de2d34abb8228dc6cb39fffe97346823a37Craig Stout        vh.bind(aoa);
5044121f22713bbed467a977ec0d867ef53989ff374Dake Gu
5054121f22713bbed467a977ec0d867ef53989ff374Dake Gu        if (row.getImageDrawable() != null && mSharedElementHelper != null) {
5064121f22713bbed467a977ec0d867ef53989ff374Dake Gu            mSharedElementHelper.onBindToDrawable(vh);
5074121f22713bbed467a977ec0d867ef53989ff374Dake Gu        }
508a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    }
509a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
510a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    @Override
511cb13a318e577e14461eb008071dddf762847de42Dake Gu    protected void onUnbindRowViewHolder(RowPresenter.ViewHolder holder) {
512cb13a318e577e14461eb008071dddf762847de42Dake Gu        super.onUnbindRowViewHolder(holder);
513a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn
514a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        ViewHolder vh = (ViewHolder) holder;
515a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        if (vh.mDetailsDescriptionViewHolder != null) {
516a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn            mDetailsPresenter.onUnbindViewHolder(vh.mDetailsDescriptionViewHolder);
517a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn        }
518a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn    }
519a83005b70853ea52c5d98910762344de16b850a8Tim Kilbourn}
520