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