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