DetailsOverviewRowPresenter.java revision 80d04d2265fe28800fcbc7e8cc7d6d229a7913d8
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 * in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the License
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 * or implied. See the License for the specific language governing permissions and limitations under
12 * the License.
13 */
14package android.support.v17.leanback.widget;
15
16import android.content.Context;
17import android.graphics.Color;
18import android.support.v17.leanback.R;
19import android.support.v7.widget.RecyclerView;
20import android.util.Log;
21import android.util.TypedValue;
22import android.view.LayoutInflater;
23import android.view.View;
24import android.view.ViewGroup;
25import android.widget.FrameLayout;
26import android.widget.ImageView;
27
28import java.util.Collection;
29
30/**
31 * A DetailsOverviewRowPresenter renders a {@link DetailsOverviewRow} to display an
32 * overview of an item. Typically this row will be the first row in a fragment
33 * such as the {@link android.support.v17.leanback.app.DetailsFragment
34 * DetailsFragment}.
35 *
36 * <p>The detailed description is rendered using a {@link Presenter}.
37 */
38public class DetailsOverviewRowPresenter extends RowPresenter {
39
40    private static final String TAG = "DetailsOverviewRowPresenter";
41    private static final boolean DEBUG = false;
42
43    private static final int MORE_ACTIONS_FADE_MS = 100;
44
45    /**
46     * A ViewHolder for the DetailsOverviewRow.
47     */
48    public static class ViewHolder extends RowPresenter.ViewHolder {
49        final ImageView mImageView;
50        final FrameLayout mDetailsDescriptionFrame;
51        final HorizontalGridView mActionsRow;
52        Presenter.ViewHolder mDetailsDescriptionViewHolder;
53        int mNumItems;
54        boolean mShowMoreRight;
55        boolean mShowMoreLeft;
56
57        void bind(ItemBridgeAdapter bridgeAdapter) {
58            mNumItems = bridgeAdapter.getItemCount();
59            bridgeAdapter.setAdapterListener(mAdapterListener);
60
61            mShowMoreRight = false;
62            mShowMoreLeft = true;
63            showMoreLeft(false);
64        }
65
66        final ItemBridgeAdapter.AdapterListener mAdapterListener =
67                new ItemBridgeAdapter.AdapterListener() {
68
69            @Override
70            public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder viewHolder) {
71                checkFirstAndLastPosition(false);
72            }
73            @Override
74            public void onDetachedFromWindow(ItemBridgeAdapter.ViewHolder viewHolder) {
75                checkFirstAndLastPosition(false);
76            }
77        };
78
79        final RecyclerView.OnScrollListener mScrollListener =
80                new RecyclerView.OnScrollListener() {
81
82            @Override
83            public void onScrollStateChanged(int newState) {
84            }
85            @Override
86            public void onScrolled(int dx, int dy) {
87                checkFirstAndLastPosition(true);
88            }
89        };
90
91        private int getViewCenter(View view) {
92            return (view.getRight() - view.getLeft()) / 2;
93        }
94
95        private void checkFirstAndLastPosition(boolean fromScroll) {
96            RecyclerView.ViewHolder viewHolder;
97
98            viewHolder = mActionsRow.findViewHolderForPosition(mNumItems - 1);
99            boolean showRight = (viewHolder == null ||
100                    viewHolder.itemView.getRight() > mActionsRow.getWidth());
101
102            viewHolder = mActionsRow.findViewHolderForPosition(0);
103            boolean showLeft = (viewHolder == null || viewHolder.itemView.getLeft() < 0);
104
105            if (DEBUG) Log.v(TAG, "checkFirstAndLast fromScroll " + fromScroll +
106                    " showRight " + showRight + " showLeft " + showLeft);
107
108            showMoreRight(showRight);
109            showMoreLeft(showLeft);
110        }
111
112        private void showMoreLeft(boolean show) {
113            if (show != mShowMoreLeft) {
114                mActionsRow.setFadingLeftEdge(show);
115                mShowMoreLeft = show;
116            }
117        }
118
119        private void showMoreRight(boolean show) {
120            if (show != mShowMoreRight) {
121                mActionsRow.setFadingRightEdge(show);
122                mShowMoreRight = show;
123            }
124        }
125
126        /**
127         * Constructor for the ViewHolder.
128         *
129         * @param rootView The root View that this view holder will be attached
130         *        to.
131         */
132        public ViewHolder(View rootView) {
133            super(rootView);
134            mImageView = (ImageView) rootView.findViewById(R.id.details_overview_image);
135            mDetailsDescriptionFrame =
136                    (FrameLayout) rootView.findViewById(R.id.details_overview_description);
137            mActionsRow =
138                    (HorizontalGridView) rootView.findViewById(R.id.details_overview_actions);
139            mActionsRow.setOnScrollListener(mScrollListener);
140
141            final int fadeLength = rootView.getResources().getDimensionPixelSize(
142                    R.dimen.lb_details_overview_actions_fade_size);
143            mActionsRow.setFadingRightEdgeLength(fadeLength);
144            mActionsRow.setFadingLeftEdgeLength(fadeLength);
145        }
146    }
147
148    private final Presenter mDetailsPresenter;
149    private final ActionPresenterSelector mActionPresenterSelector;
150    private final ItemBridgeAdapter mActionBridgeAdapter;
151    private int mBackgroundColor = Color.TRANSPARENT;
152    private boolean mBackgroundColorSet;
153    private boolean mIsStyleLarge = true;
154
155    /**
156     * Constructor for a DetailsOverviewRowPresenter.
157     *
158     * @param detailsPresenter The {@link Presenter} used to render the detailed
159     *        description of the row.
160     */
161    public DetailsOverviewRowPresenter(Presenter detailsPresenter) {
162        setHeaderPresenter(null);
163        setSelectEffectEnabled(false);
164        mDetailsPresenter = detailsPresenter;
165        mActionPresenterSelector = new ActionPresenterSelector();
166        mActionBridgeAdapter = new ItemBridgeAdapter();
167    }
168
169    /**
170     * Sets the listener for Action click events.
171     */
172    public void setOnActionClickedListener(OnActionClickedListener listener) {
173        mActionPresenterSelector.setOnActionClickedListener(listener);
174    }
175
176    /**
177     * Gets the listener for Action click events.
178     */
179    public OnActionClickedListener getOnActionClickedListener() {
180        return mActionPresenterSelector.getOnActionClickedListener();
181    }
182
183    /**
184     * Sets the background color.  If not set, a default from the theme will be used.
185     */
186    public void setBackgroundColor(int color) {
187        mBackgroundColor = color;
188        mBackgroundColorSet = true;
189    }
190
191    /**
192     * Returns the background color.  If no background color was set, transparent
193     * is returned.
194     */
195    public int getBackgroundColor() {
196        return mBackgroundColor;
197    }
198
199    /**
200     * Sets the layout style to be large or small. This affects the height of
201     * the overview, including the text description. The default is large.
202     */
203    public void setStyleLarge(boolean large) {
204        mIsStyleLarge = large;
205    }
206
207    /**
208     * Returns true if the layout style is large.
209     */
210    public boolean isStyleLarge() {
211        return mIsStyleLarge;
212    }
213
214    private int getDefaultBackgroundColor(Context context) {
215        TypedValue outValue = new TypedValue();
216        context.getTheme().resolveAttribute(R.attr.defaultBrandColor, outValue, true);
217        return context.getResources().getColor(outValue.resourceId);
218    }
219
220    @Override
221    protected RowPresenter.ViewHolder createRowViewHolder(ViewGroup parent) {
222        View v = LayoutInflater.from(parent.getContext())
223            .inflate(R.layout.lb_details_overview, parent, false);
224        ViewHolder vh = new ViewHolder(v);
225
226        vh.mDetailsDescriptionViewHolder =
227            mDetailsPresenter.onCreateViewHolder(vh.mDetailsDescriptionFrame);
228        vh.mDetailsDescriptionFrame.addView(vh.mDetailsDescriptionViewHolder.view);
229
230        initDetailsOverview(vh);
231
232        return vh;
233    }
234
235    private void initDetailsOverview(ViewHolder vh) {
236        int resId = mIsStyleLarge ? R.dimen.lb_details_overview_height_large :
237            R.dimen.lb_details_overview_height_small;
238
239        View overview = vh.view.findViewById(R.id.details_overview);
240        ViewGroup.LayoutParams lp = overview.getLayoutParams();
241        lp.height = overview.getResources().getDimensionPixelSize(resId);
242        overview.setLayoutParams(lp);
243
244        overview.setBackgroundColor(mBackgroundColorSet ?
245                mBackgroundColor : getDefaultBackgroundColor(overview.getContext()));
246
247        // Max width to make a square
248        ImageView image = (ImageView) vh.view.findViewById(R.id.details_overview_image);
249        image.setMaxWidth(lp.height);
250    }
251
252    @Override
253    protected void onBindRowViewHolder(RowPresenter.ViewHolder holder, Object item) {
254        super.onBindRowViewHolder(holder, item);
255
256        DetailsOverviewRow row = (DetailsOverviewRow) item;
257        ViewHolder vh = (ViewHolder) holder;
258        if (row.getImageDrawable() != null) {
259            vh.mImageView.setImageDrawable(row.getImageDrawable());
260        }
261        if (vh.mDetailsDescriptionViewHolder == null) {
262        }
263        mDetailsPresenter.onBindViewHolder(vh.mDetailsDescriptionViewHolder, row);
264
265        mActionBridgeAdapter.clear();
266        ArrayObjectAdapter aoa = new ArrayObjectAdapter(mActionPresenterSelector);
267        aoa.addAll(0, (Collection)row.getActions());
268
269        mActionBridgeAdapter.setAdapter(aoa);
270        vh.mActionsRow.setAdapter(mActionBridgeAdapter);
271
272        vh.bind(mActionBridgeAdapter);
273    }
274
275    @Override
276    protected void onUnbindRowViewHolder(RowPresenter.ViewHolder holder) {
277        super.onUnbindRowViewHolder(holder);
278
279        ViewHolder vh = (ViewHolder) holder;
280        if (vh.mDetailsDescriptionViewHolder != null) {
281            mDetailsPresenter.onUnbindViewHolder(vh.mDetailsDescriptionViewHolder);
282        }
283
284        vh.mActionsRow.setAdapter(null);
285    }
286}
287