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