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