DetailsOverviewRowPresenter.java revision 2e0c922430f8c285b4325da52d69c09451069c93
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 * DetailsOverviewRowPresenter renders {@link DetailsOverviewRow} to display an
32 * overview of an item. Typically this row will be the first row in a fragment
33 * such as {@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    public static class ViewHolder extends RowPresenter.ViewHolder {
46        final ImageView mImageView;
47        final FrameLayout mDetailsDescriptionFrame;
48        final HorizontalGridView mActionsRow;
49        final View mMoreActionsView;
50        Presenter.ViewHolder mDetailsDescriptionViewHolder;
51
52        class ScrollListener implements RecyclerView.OnScrollListener {
53            ObjectAdapter mAdapter;
54            boolean mShowMoreRight;
55            boolean mShowMoreLeft;
56
57            void bind(ObjectAdapter adapter) {
58                mAdapter = adapter;
59
60                mMoreActionsView.setAlpha(0f);
61                mShowMoreRight = false;
62                showMoreRight(true);
63
64                mShowMoreLeft = true;
65                showMoreLeft(false);
66            }
67
68            @Override
69            public void onScrollStateChanged(int newState) {
70            }
71
72            @Override
73            public void onScrolled(int dx, int dy) {
74                View view;
75                int position;
76
77                view = mActionsRow.getChildAt(mActionsRow.getChildCount() - 1);
78                position = mActionsRow.getChildViewHolder(view).getPosition();
79                if (position < (mAdapter.size() - 1) || view.getRight() > mActionsRow.getWidth()) {
80                    showMoreRight(true);
81                } else {
82                    showMoreRight(false);
83                }
84
85                view = mActionsRow.getChildAt(0);
86                position = mActionsRow.getChildViewHolder(view).getPosition();
87                if (position != 0 || view.getLeft() < 0) {
88                    showMoreLeft(true);
89                } else {
90                    showMoreLeft(false);
91                }
92            }
93
94            private void showMoreLeft(boolean show) {
95                if (show != mShowMoreLeft) {
96                    mActionsRow.setFadingLeftEdge(show);
97                    mShowMoreLeft = show;
98                }
99            }
100
101            private void showMoreRight(boolean show) {
102                if (show != mShowMoreRight) {
103                    mMoreActionsView.animate().alpha(show ? 1f : 0).setDuration(
104                            MORE_ACTIONS_FADE_MS).start();
105                    mActionsRow.setFadingRightEdge(show);
106                    mShowMoreRight = show;
107                }
108            }
109        }
110
111        final ScrollListener mScrollListener = new ScrollListener();
112
113        public ViewHolder(View rootView) {
114            super(rootView);
115            mImageView = (ImageView) rootView.findViewById(R.id.details_overview_image);
116            mDetailsDescriptionFrame =
117                    (FrameLayout) rootView.findViewById(R.id.details_overview_description);
118            mActionsRow =
119                    (HorizontalGridView) rootView.findViewById(R.id.details_overview_actions);
120            mActionsRow.setOnScrollListener(mScrollListener);
121
122            final int fadeLength = rootView.getResources().getDimensionPixelSize(
123                    R.dimen.lb_details_overview_actions_fade_size);
124            mActionsRow.setFadingRightEdgeLength(fadeLength);
125            mActionsRow.setFadingRightEdgeOffset(-fadeLength);
126            mActionsRow.setFadingLeftEdgeLength(fadeLength);
127            mActionsRow.setFadingLeftEdgeOffset(-fadeLength);
128
129            mMoreActionsView = rootView.findViewById(R.id.details_overview_actions_more);
130        }
131    }
132
133    private final Presenter mDetailsPresenter;
134    private final ActionPresenterSelector mActionPresenterSelector;
135    private final ItemBridgeAdapter mActionBridgeAdapter;
136    private int mBackgroundColor = Color.TRANSPARENT;
137    private boolean mBackgroundColorSet;
138    private boolean mIsStyleLarge = true;
139
140    /**
141     * Constructor that uses the given {@link Presenter} to render the detailed
142     * description for the row.
143     */
144    public DetailsOverviewRowPresenter(Presenter detailsPresenter) {
145        setHeaderPresenter(null);
146        setSelectEffectEnabled(false);
147        mDetailsPresenter = detailsPresenter;
148        mActionPresenterSelector = new ActionPresenterSelector();
149        mActionBridgeAdapter = new ItemBridgeAdapter();
150    }
151
152    /**
153     * Sets the listener for action click events.
154     */
155    public void setOnActionClickedListener(OnActionClickedListener listener) {
156        mActionPresenterSelector.setOnActionClickedListener(listener);
157    }
158
159    /**
160     * Gets the listener for action click events.
161     */
162    public OnActionClickedListener getOnActionClickedListener() {
163        return mActionPresenterSelector.getOnActionClickedListener();
164    }
165
166    /**
167     * Sets the background color.  If not set a default from the theme will be used.
168     */
169    public void setBackgroundColor(int color) {
170        mBackgroundColor = color;
171        mBackgroundColorSet = true;
172    }
173
174    /**
175     * Returns the background color.  If no background color was set, returns transparent.
176     */
177    public int getBackgroundColor() {
178        return mBackgroundColor;
179    }
180
181    /**
182     * Sets the layout style to be large or small.
183     * The default is large.
184     */
185    public void setStyleLarge(boolean large) {
186        mIsStyleLarge = large;
187    }
188
189    /**
190     * Returns true if the layout style is large.
191     */
192    public boolean isStyleLarge() {
193        return mIsStyleLarge;
194    }
195
196    private int getDefaultBackgroundColor(Context context) {
197        TypedValue outValue = new TypedValue();
198        context.getTheme().resolveAttribute(android.R.attr.colorBackground, outValue, true);
199        return context.getResources().getColor(outValue.resourceId);
200    }
201
202    @Override
203    protected RowPresenter.ViewHolder createRowViewHolder(ViewGroup parent) {
204        View v = LayoutInflater.from(parent.getContext())
205            .inflate(R.layout.lb_details_overview, parent, false);
206        ViewHolder vh = new ViewHolder(v);
207
208        vh.mDetailsDescriptionViewHolder =
209            mDetailsPresenter.onCreateViewHolder(vh.mDetailsDescriptionFrame);
210        vh.mDetailsDescriptionFrame.addView(vh.mDetailsDescriptionViewHolder.view);
211
212        initDetailsOverview(v.findViewById(R.id.details_overview));
213
214        return vh;
215    }
216
217    private void initDetailsOverview(View view) {
218        int resId = mIsStyleLarge ? R.dimen.lb_details_overview_height_large :
219            R.dimen.lb_details_overview_height_small;
220
221        ViewGroup.LayoutParams lp = view.getLayoutParams();
222        lp.height = view.getResources().getDimensionPixelSize(resId);
223        view.setLayoutParams(lp);
224
225        view.setBackgroundColor(mBackgroundColorSet ?
226                mBackgroundColor : getDefaultBackgroundColor(view.getContext()));
227
228    }
229
230    @Override
231    protected void onBindRowViewHolder(RowPresenter.ViewHolder holder, Object item) {
232        super.onBindRowViewHolder(holder, item);
233
234        DetailsOverviewRow row = (DetailsOverviewRow) item;
235        ViewHolder vh = (ViewHolder) holder;
236        if (row.getImageDrawable() != null) {
237            vh.mImageView.setImageDrawable(row.getImageDrawable());
238        }
239        if (vh.mDetailsDescriptionViewHolder == null) {
240        }
241        mDetailsPresenter.onBindViewHolder(vh.mDetailsDescriptionViewHolder, row);
242
243        mActionBridgeAdapter.clear();
244        ArrayObjectAdapter aoa = new ArrayObjectAdapter(mActionPresenterSelector);
245        aoa.addAll(0, (Collection)row.getActions());
246        vh.mScrollListener.bind(aoa);
247
248        mActionBridgeAdapter.setAdapter(aoa);
249        vh.mActionsRow.setAdapter(mActionBridgeAdapter);
250    }
251
252    @Override
253    protected void onUnbindRowViewHolder(RowPresenter.ViewHolder holder) {
254        super.onUnbindRowViewHolder(holder);
255
256        ViewHolder vh = (ViewHolder) holder;
257        if (vh.mDetailsDescriptionViewHolder != null) {
258            mDetailsPresenter.onUnbindViewHolder(vh.mDetailsDescriptionViewHolder);
259        }
260
261        vh.mActionsRow.setAdapter(null);
262    }
263}
264