PlaybackControlsRowPresenter.java revision 6b2e5b5117f1b8dfafbd81b995bb423ab0297564
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.support.v17.leanback.R;
17import android.content.Context;
18import android.graphics.Color;
19import android.util.TypedValue;
20import android.view.LayoutInflater;
21import android.view.View;
22import android.view.ViewGroup;
23import android.view.ViewGroup.LayoutParams;
24import android.view.ViewGroup.MarginLayoutParams;
25import android.widget.ImageView;
26
27/**
28 * A PlaybackControlsRowPresenter renders a {@link PlaybackControlsRow} to display a
29 * series of playback control buttons. Typically this row will be the first row in a fragment
30 * such as the {@link android.support.v17.leanback.app.PlaybackOverlayFragment
31 * PlaybackControlsFragment}.
32 */
33public class PlaybackControlsRowPresenter extends RowPresenter {
34
35    /**
36     * A ViewHolder for the PlaybackControlsRow.
37     */
38    public class ViewHolder extends RowPresenter.ViewHolder {
39        public final Presenter.ViewHolder mDescriptionViewHolder;
40        final ViewGroup mCard;
41        final ImageView mImageView;
42        final ViewGroup mDescriptionDock;
43        final ViewGroup mControlsDock;
44        final ViewGroup mSecondaryControlsDock;
45        final View mSpacer;
46        int mCardHeight;
47        int mControlsDockMarginStart;
48        int mControlsDockMarginEnd;
49        PlaybackControlsPresenter.ViewHolder mControlsVh;
50        Presenter.ViewHolder mSecondaryControlsVh;
51        PlaybackControlsPresenter.BoundData mControlsBoundData =
52                new PlaybackControlsPresenter.BoundData();
53        ControlBarPresenter.BoundData mSecondaryBoundData = new ControlBarPresenter.BoundData();
54        final PlaybackControlsRow.OnPlaybackStateChangedListener mListener =
55                new PlaybackControlsRow.OnPlaybackStateChangedListener() {
56            @Override
57            public void onCurrentTimeChanged(int ms) {
58                mPlaybackControlsPresenter.setCurrentTime(mControlsVh, ms);
59            }
60            @Override
61            public void onBufferedProgressChanged(int ms) {
62                mPlaybackControlsPresenter.setSecondaryProgress(mControlsVh, ms);
63            }
64        };
65        final OnItemViewSelectedListener mOnItemViewSelectedListener =
66                new OnItemViewSelectedListener() {
67            @Override
68            public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
69                    RowPresenter.ViewHolder rowViewHolder, Row row) {
70                if (getOnItemViewSelectedListener() != null) {
71                    getOnItemViewSelectedListener().onItemSelected(itemViewHolder, item,
72                            ViewHolder.this, getRow());
73                }
74            }
75        };
76
77        ViewHolder(View rootView, Presenter descriptionPresenter) {
78            super(rootView);
79            mCard = (ViewGroup) rootView.findViewById(R.id.controls_card);
80            mImageView = (ImageView) rootView.findViewById(R.id.image);
81            mDescriptionDock = (ViewGroup) rootView.findViewById(R.id.description_dock);
82            mControlsDock = (ViewGroup) rootView.findViewById(R.id.controls_dock);
83            mSecondaryControlsDock =
84                    (ViewGroup) rootView.findViewById(R.id.secondary_controls_dock);
85            mSpacer = rootView.findViewById(R.id.spacer);
86            mDescriptionViewHolder = descriptionPresenter == null ? null :
87                    descriptionPresenter.onCreateViewHolder(mDescriptionDock);
88            if (mDescriptionViewHolder != null) {
89                mDescriptionDock.addView(mDescriptionViewHolder.view);
90            }
91        }
92
93        Presenter getPresenter(Object item, boolean primary) {
94            ObjectAdapter adapter = primary ?
95                    ((PlaybackControlsRow) getRow()).getPrimaryActionsAdapter() :
96                            ((PlaybackControlsRow) getRow()).getSecondaryActionsAdapter();
97            if (adapter.getPresenterSelector() instanceof ControlButtonPresenterSelector) {
98                ControlButtonPresenterSelector selector =
99                        (ControlButtonPresenterSelector) adapter.getPresenterSelector();
100                return primary ? selector.getPrimaryPresenter() :
101                    selector.getSecondaryPresenter();
102            }
103            return adapter.getPresenter(item);
104        }
105    }
106
107    private int mBackgroundColor = Color.TRANSPARENT;
108    private boolean mBackgroundColorSet;
109    private int mProgressColor = Color.TRANSPARENT;
110    private boolean mProgressColorSet;
111    private boolean mSecondaryActionsHidden;
112    private Presenter mDescriptionPresenter;
113    private PlaybackControlsPresenter mPlaybackControlsPresenter;
114    private ControlBarPresenter mSecondaryControlsPresenter;
115
116    /**
117     * Constructor for a PlaybackControlsRowPresenter.
118     *
119     * @param descriptionPresenter Presenter for displaying item details.
120     */
121    public PlaybackControlsRowPresenter(Presenter descriptionPresenter) {
122        setHeaderPresenter(null);
123        setSelectEffectEnabled(false);
124
125        mDescriptionPresenter = descriptionPresenter;
126        mPlaybackControlsPresenter = new PlaybackControlsPresenter(R.layout.lb_playback_controls);
127        mSecondaryControlsPresenter = new ControlBarPresenter(R.layout.lb_control_bar);
128    }
129
130    /**
131     * Constructor for a PlaybackControlsRowPresenter.
132     */
133    public PlaybackControlsRowPresenter() {
134        this(null);
135    }
136
137    /**
138     * Sets the listener for {@link Action} click events.
139     */
140    public void setOnActionClickedListener(OnActionClickedListener listener) {
141        mPlaybackControlsPresenter.setOnActionClickedListener(listener);
142        mSecondaryControlsPresenter.setOnActionClickedListener(listener);
143    }
144
145    /**
146     * Gets the listener for {@link Action} click events.
147     */
148    public OnActionClickedListener getOnActionClickedListener() {
149        return mPlaybackControlsPresenter.getOnActionClickedListener();
150    }
151
152    /**
153     * Sets the background color.  If not set, a default from the theme will be used.
154     */
155    public void setBackgroundColor(int color) {
156        mBackgroundColor = color;
157        mBackgroundColorSet = true;
158    }
159
160    /**
161     * Returns the background color.  If no background color was set, transparent
162     * is returned.
163     */
164    public int getBackgroundColor() {
165        return mBackgroundColor;
166    }
167
168    /**
169     * Sets the primary color for the progress bar.  If not set, a default from
170     * the theme will be used.
171     */
172    public void setProgressColor(int color) {
173        mProgressColor = color;
174        mProgressColorSet = true;
175    }
176
177    /**
178     * Returns the primary color for the progress bar.  If no color was set, transparent
179     * is returned.
180     */
181    public int getProgressColor() {
182        return mProgressColor;
183    }
184
185    /**
186     * Sets the secondary actions to be hidden behind a "more actions" button.
187     * When "more actions" is selected, the primary actions are replaced with
188     * the secondary actions.
189     */
190    public void setSecondaryActionsHidden(boolean hidden) {
191        mSecondaryActionsHidden = hidden;
192    }
193
194    /**
195     * Returns true if secondary actions are hidden.
196     */
197    public boolean areSecondaryActionsHidden() {
198        return mSecondaryActionsHidden;
199    }
200
201    private int getDefaultBackgroundColor(Context context) {
202        TypedValue outValue = new TypedValue();
203        context.getTheme().resolveAttribute(R.attr.defaultBrandColor, outValue, true);
204        return context.getResources().getColor(outValue.resourceId);
205    }
206
207    private int getDefaultProgressColor(Context context) {
208        TypedValue outValue = new TypedValue();
209        context.getTheme().resolveAttribute(R.attr.playbackProgressPrimaryColor, outValue, true);
210        return context.getResources().getColor(outValue.resourceId);
211    }
212
213    @Override
214    protected RowPresenter.ViewHolder createRowViewHolder(ViewGroup parent) {
215        View v = LayoutInflater.from(parent.getContext())
216            .inflate(R.layout.lb_playback_controls_row, parent, false);
217        ViewHolder vh = new ViewHolder(v, mDescriptionPresenter);
218        initRow(vh);
219        return vh;
220    }
221
222    private void initRow(ViewHolder vh) {
223        vh.mCardHeight = vh.mCard.getLayoutParams().height;
224
225        MarginLayoutParams lp = (MarginLayoutParams) vh.mControlsDock.getLayoutParams();
226        vh.mControlsDockMarginStart = lp.getMarginStart();
227        vh.mControlsDockMarginEnd = lp.getMarginEnd();
228
229        vh.mControlsVh = (PlaybackControlsPresenter.ViewHolder)
230                mPlaybackControlsPresenter.onCreateViewHolder(vh.mControlsDock);
231        mPlaybackControlsPresenter.setProgressColor(vh.mControlsVh,
232                mProgressColorSet ? mProgressColor :
233                        getDefaultProgressColor(vh.mControlsDock.getContext()));
234        mPlaybackControlsPresenter.setOnItemViewSelectedListener(vh.mOnItemViewSelectedListener);
235        vh.mControlsDock.addView(vh.mControlsVh.view);
236
237        vh.mSecondaryControlsVh =
238                mSecondaryControlsPresenter.onCreateViewHolder(vh.mSecondaryControlsDock);
239        if (!mSecondaryActionsHidden) {
240            vh.mSecondaryControlsDock.addView(vh.mSecondaryControlsVh.view);
241        }
242        mSecondaryControlsPresenter.setOnItemViewSelectedListener(vh.mOnItemViewSelectedListener);
243    }
244
245    private void setBackground(View view) {
246        view.setBackgroundColor(mBackgroundColorSet ?
247                mBackgroundColor : getDefaultBackgroundColor(view.getContext()));
248        ShadowHelper.getInstance().setZ(view, 0f);
249    }
250
251    @Override
252    protected void onBindRowViewHolder(RowPresenter.ViewHolder holder, Object item) {
253        super.onBindRowViewHolder(holder, item);
254
255        ViewHolder vh = (ViewHolder) holder;
256        PlaybackControlsRow row = (PlaybackControlsRow) vh.getRow();
257
258        mPlaybackControlsPresenter.enableSecondaryActions(mSecondaryActionsHidden);
259
260        if (row.getItem() == null) {
261            LayoutParams lp = vh.mCard.getLayoutParams();
262            lp.height = LayoutParams.WRAP_CONTENT;
263            vh.mCard.setLayoutParams(lp);
264            vh.mDescriptionDock.setVisibility(View.GONE);
265            vh.mSpacer.setVisibility(View.GONE);
266        } else {
267            LayoutParams lp = vh.mCard.getLayoutParams();
268            lp.height = vh.mCardHeight;
269            vh.mCard.setLayoutParams(lp);
270            vh.mDescriptionDock.setVisibility(View.VISIBLE);
271            if (vh.mDescriptionViewHolder != null) {
272                mDescriptionPresenter.onBindViewHolder(vh.mDescriptionViewHolder, row.getItem());
273            }
274            vh.mSpacer.setVisibility(View.VISIBLE);
275        }
276
277        MarginLayoutParams lp = (MarginLayoutParams) vh.mControlsDock.getLayoutParams();
278        if (row.getImageDrawable() == null || row.getItem() == null) {
279            setBackground(vh.mControlsDock);
280            vh.mCard.setBackgroundColor(Color.TRANSPARENT);
281            lp.setMarginStart(0);
282            lp.setMarginEnd(0);
283            mPlaybackControlsPresenter.enableTimeMargins(vh.mControlsVh, true);
284        } else {
285            vh.mImageView.setImageDrawable(row.getImageDrawable());
286            setBackground(vh.mCard);
287            vh.mControlsDock.setBackgroundColor(Color.TRANSPARENT);
288            lp.setMarginStart(vh.mControlsDockMarginStart);
289            lp.setMarginEnd(vh.mControlsDockMarginEnd);
290            mPlaybackControlsPresenter.enableTimeMargins(vh.mControlsVh, false);
291        }
292        vh.mControlsDock.setLayoutParams(lp);
293
294        vh.mControlsBoundData.adapter = row.getPrimaryActionsAdapter();
295        vh.mControlsBoundData.secondaryActionsAdapter = row.getSecondaryActionsAdapter();
296        vh.mControlsBoundData.presenter = vh.getPresenter(
297                row.getPrimaryActionsAdapter().get(0), true);
298        mPlaybackControlsPresenter.onBindViewHolder(vh.mControlsVh, vh.mControlsBoundData);
299
300        vh.mSecondaryBoundData.adapter = row.getSecondaryActionsAdapter();
301        vh.mSecondaryBoundData.presenter = vh.getPresenter(
302                row.getSecondaryActionsAdapter().get(0), false);
303        mSecondaryControlsPresenter.onBindViewHolder(vh.mSecondaryControlsVh,
304                vh.mSecondaryBoundData);
305
306        mPlaybackControlsPresenter.setTotalTime(vh.mControlsVh, row.getTotalTime());
307        mPlaybackControlsPresenter.setCurrentTime(vh.mControlsVh, row.getCurrentTime());
308        mPlaybackControlsPresenter.setSecondaryProgress(vh.mControlsVh, row.getBufferedProgress());
309        row.setOnPlaybackStateChangedListener(vh.mListener);
310    }
311
312    @Override
313    protected void onUnbindRowViewHolder(RowPresenter.ViewHolder holder) {
314        ViewHolder vh = (ViewHolder) holder;
315        PlaybackControlsRow row = (PlaybackControlsRow) vh.getRow();
316
317        if (vh.mDescriptionViewHolder != null) {
318            mDescriptionPresenter.onUnbindViewHolder(vh.mDescriptionViewHolder);
319        }
320        mPlaybackControlsPresenter.onUnbindViewHolder(vh.mControlsVh);
321        mSecondaryControlsPresenter.onUnbindViewHolder(vh.mSecondaryControlsVh);
322        row.setOnPlaybackStateChangedListener(null);
323
324        super.onUnbindRowViewHolder(holder);
325    }
326}
327