DetailsOverviewRowPresenter.java revision 69e74bd8956577d9a3414b81ec661fd5fee42e19
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        ShadowHelper.getInstance().setZ(overview, 0f);
247
248        // Max width to make a square
249        ImageView image = (ImageView) vh.view.findViewById(R.id.details_overview_image);
250        image.setMaxWidth(lp.height);
251    }
252
253    @Override
254    protected void onBindRowViewHolder(RowPresenter.ViewHolder holder, Object item) {
255        super.onBindRowViewHolder(holder, item);
256
257        DetailsOverviewRow row = (DetailsOverviewRow) item;
258        ViewHolder vh = (ViewHolder) holder;
259        if (row.getImageDrawable() != null) {
260            vh.mImageView.setImageDrawable(row.getImageDrawable());
261        }
262        if (vh.mDetailsDescriptionViewHolder == null) {
263        }
264        mDetailsPresenter.onBindViewHolder(vh.mDetailsDescriptionViewHolder, row);
265
266        mActionBridgeAdapter.clear();
267        ArrayObjectAdapter aoa = new ArrayObjectAdapter(mActionPresenterSelector);
268        aoa.addAll(0, (Collection)row.getActions());
269
270        mActionBridgeAdapter.setAdapter(aoa);
271        vh.mActionsRow.setAdapter(mActionBridgeAdapter);
272
273        vh.bind(mActionBridgeAdapter);
274    }
275
276    @Override
277    protected void onUnbindRowViewHolder(RowPresenter.ViewHolder holder) {
278        super.onUnbindRowViewHolder(holder);
279
280        ViewHolder vh = (ViewHolder) holder;
281        if (vh.mDetailsDescriptionViewHolder != null) {
282            mDetailsPresenter.onUnbindViewHolder(vh.mDetailsDescriptionViewHolder);
283        }
284
285        vh.mActionsRow.setAdapter(null);
286    }
287}
288