PlaybackControlsRow.java revision 386b06a44a1f46327f045dbb3ae1bebadbcbfed7
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.util.TypedValue; 18import android.content.Context; 19import android.content.res.TypedArray; 20import android.graphics.Bitmap; 21import android.graphics.BitmapFactory; 22import android.graphics.Canvas; 23import android.graphics.Color; 24import android.graphics.Paint; 25import android.graphics.PorterDuff; 26import android.graphics.PorterDuffColorFilter; 27import android.graphics.drawable.BitmapDrawable; 28import android.graphics.drawable.Drawable; 29 30/** 31 * A row of playback controls to be displayed by a {@link PlaybackControlsRowPresenter}. 32 * 33 * This row consists of some optional item detail, a series of primary actions, 34 * and an optional series of secondary actions. 35 * 36 * Controls are specified via an {@link ObjectAdapter} containing one or more 37 * {@link Action}s. 38 * 39 * Adapters should have their {@link PresenterSelector} set to an instance of 40 * {@link ControlButtonPresenterSelector}. 41 * 42 */ 43public class PlaybackControlsRow extends Row { 44 45 /** 46 * Base class for an action comprised of a series of icons. 47 */ 48 public static abstract class MultiAction extends Action { 49 private int mIndex; 50 private Drawable[] mDrawables; 51 52 /** 53 * Constructor 54 * @param id The id of the Action. 55 */ 56 public MultiAction(int id) { 57 super(id); 58 } 59 60 /** 61 * Sets the array of drawables. The size of the array defines the range 62 * of valid indices for this action. 63 */ 64 public void setDrawables(Drawable[] drawables) { 65 mDrawables = drawables; 66 setIndex(0); 67 } 68 69 /** 70 * Returns the number of drawables. 71 */ 72 public int getNumberOfDrawables() { 73 return mDrawables.length; 74 } 75 76 /** 77 * Returns the drawable at the given index. 78 */ 79 public Drawable getDrawable(int index) { 80 return mDrawables[index]; 81 } 82 83 /** 84 * Increments the index, wrapping to zero once the end is reached. 85 */ 86 public void nextIndex() { 87 setIndex(mIndex < mDrawables.length - 1 ? mIndex + 1 : 0); 88 } 89 90 /** 91 * Sets the current index. 92 */ 93 public void setIndex(int index) { 94 mIndex = index; 95 setIcon(mDrawables[mIndex]); 96 } 97 98 /** 99 * Gets the current index. 100 */ 101 public int getIndex() { 102 return mIndex; 103 } 104 } 105 106 /** 107 * An action displaying icons for play and pause. 108 */ 109 public static class PlayPauseAction extends MultiAction { 110 /** 111 * Action index for the play icon. 112 */ 113 public static int PLAY = 0; 114 115 /** 116 * Action index for the pause icon. 117 */ 118 public static int PAUSE = 1; 119 120 /** 121 * Constructor 122 * @param context Context used for loading resources. 123 */ 124 public PlayPauseAction(Context context) { 125 super(R.id.lb_control_play_pause); 126 Drawable[] drawables = new Drawable[2]; 127 drawables[PLAY] = getStyledDrawable(context, 128 R.styleable.lbPlaybackControlsActionIcons_play); 129 drawables[PAUSE] = getStyledDrawable(context, 130 R.styleable.lbPlaybackControlsActionIcons_pause); 131 setDrawables(drawables); 132 } 133 } 134 135 /** 136 * An action displaying an icon for fast forward. 137 */ 138 public static class FastForwardAction extends Action { 139 /** 140 * Constructor 141 * @param context Context used for loading resources. 142 */ 143 public FastForwardAction(Context context) { 144 super(R.id.lb_control_fast_forward); 145 setIcon(getStyledDrawable(context, 146 R.styleable.lbPlaybackControlsActionIcons_fast_forward)); 147 } 148 } 149 150 /** 151 * An action displaying an icon for rewind. 152 */ 153 public static class RewindAction extends Action { 154 /** 155 * Constructor 156 * @param context Context used for loading resources. 157 */ 158 public RewindAction(Context context) { 159 super(R.id.lb_control_fast_rewind); 160 setIcon(getStyledDrawable(context, 161 R.styleable.lbPlaybackControlsActionIcons_rewind)); 162 } 163 } 164 165 /** 166 * An action displaying an icon for skip next. 167 */ 168 public static class SkipNextAction extends Action { 169 /** 170 * Constructor 171 * @param context Context used for loading resources. 172 */ 173 public SkipNextAction(Context context) { 174 super(R.id.lb_control_skip_next); 175 setIcon(getStyledDrawable(context, 176 R.styleable.lbPlaybackControlsActionIcons_skip_next)); 177 } 178 } 179 180 /** 181 * An action displaying an icon for skip previous. 182 */ 183 public static class SkipPreviousAction extends Action { 184 /** 185 * Constructor 186 * @param context Context used for loading resources. 187 */ 188 public SkipPreviousAction(Context context) { 189 super(R.id.lb_control_skip_previous); 190 setIcon(getStyledDrawable(context, 191 R.styleable.lbPlaybackControlsActionIcons_skip_previous)); 192 } 193 } 194 195 /** 196 * An action displaying an icon for "more actions". 197 */ 198 public static class MoreActions extends Action { 199 /** 200 * Constructor 201 * @param context Context used for loading resources. 202 */ 203 public MoreActions(Context context) { 204 super(R.id.lb_control_more_actions); 205 setIcon(context.getResources().getDrawable(R.drawable.lb_ic_more)); 206 } 207 } 208 209 /** 210 * A base class for displaying a thumbs action. 211 */ 212 public static abstract class ThumbsAction extends MultiAction { 213 /** 214 * Action index for the solid thumb icon. 215 */ 216 public static int SOLID = 0; 217 218 /** 219 * Action index for the outline thumb icon. 220 */ 221 public static int OUTLINE = 1; 222 223 /** 224 * Constructor 225 * @param context Context used for loading resources. 226 */ 227 public ThumbsAction(int id, Context context, int solidIconIndex, int outlineIconIndex) { 228 super(id); 229 Drawable[] drawables = new Drawable[2]; 230 drawables[SOLID] = getStyledDrawable(context, solidIconIndex); 231 drawables[OUTLINE] = getStyledDrawable(context, outlineIconIndex); 232 setDrawables(drawables); 233 } 234 } 235 236 /** 237 * An action displaying an icon for thumbs up. 238 */ 239 public static class ThumbsUpAction extends ThumbsAction { 240 public ThumbsUpAction(Context context) { 241 super(R.id.lb_control_thumbs_up, context, 242 R.styleable.lbPlaybackControlsActionIcons_thumb_up, 243 R.styleable.lbPlaybackControlsActionIcons_thumb_up_outline); 244 } 245 } 246 247 /** 248 * An action displaying an icon for thumbs down. 249 */ 250 public static class ThumbsDownAction extends ThumbsAction { 251 public ThumbsDownAction(Context context) { 252 super(R.id.lb_control_thumbs_down, context, 253 R.styleable.lbPlaybackControlsActionIcons_thumb_down, 254 R.styleable.lbPlaybackControlsActionIcons_thumb_down_outline); 255 } 256 } 257 258 /** 259 * An action for displaying three repeat states: none, one, or all. 260 */ 261 public static class RepeatAction extends MultiAction { 262 /** 263 * Action index for the repeat-none icon. 264 */ 265 public static int NONE = 0; 266 267 /** 268 * Action index for the repeat-all icon. 269 */ 270 public static int ALL = 1; 271 272 /** 273 * Action index for the repeat-one icon. 274 */ 275 public static int ONE = 2; 276 277 /** 278 * Constructor 279 * @param context Context used for loading resources. 280 */ 281 public RepeatAction(Context context) { 282 this(context, getColorFromTheme(context, 283 R.attr.playbackControlsIconHighlightColor)); 284 } 285 286 /** 287 * Constructor 288 * @param context Context used for loading resources 289 * @param highlightColor Color to display the repeat-all and repeat0one icons. 290 */ 291 public RepeatAction(Context context, int highlightColor) { 292 this(context, highlightColor, highlightColor); 293 } 294 295 /** 296 * Constructor 297 * @param context Context used for loading resources 298 * @param repeatAllColor Color to display the repeat-all icon. 299 * @param repeatOneColor Color to display the repeat-one icon. 300 */ 301 public RepeatAction(Context context, int repeatAllColor, int repeatOneColor) { 302 super(R.id.lb_control_repeat); 303 Drawable[] drawables = new Drawable[3]; 304 BitmapDrawable repeatDrawable = (BitmapDrawable) getStyledDrawable(context, 305 R.styleable.lbPlaybackControlsActionIcons_repeat); 306 BitmapDrawable repeatOneDrawable = (BitmapDrawable) getStyledDrawable(context, 307 R.styleable.lbPlaybackControlsActionIcons_repeat_one); 308 drawables[NONE] = repeatDrawable; 309 drawables[ALL] = new BitmapDrawable(context.getResources(), 310 createBitmap(repeatDrawable.getBitmap(), repeatAllColor)); 311 drawables[ONE] = new BitmapDrawable(context.getResources(), 312 createBitmap(repeatOneDrawable.getBitmap(), repeatOneColor)); 313 setDrawables(drawables); 314 } 315 } 316 317 /** 318 * An action for displaying a shuffle icon. 319 */ 320 public static class ShuffleAction extends MultiAction { 321 public static int OFF = 0; 322 public static int ON = 1; 323 324 /** 325 * Constructor 326 * @param context Context used for loading resources. 327 */ 328 public ShuffleAction(Context context) { 329 this(context, getColorFromTheme(context, 330 R.attr.playbackControlsIconHighlightColor)); 331 } 332 333 /** 334 * Constructor 335 * @param context Context used for loading resources. 336 * @param highlightColor Color for the highlighted icon state. 337 */ 338 public ShuffleAction(Context context, int highlightColor) { 339 super(R.id.lb_control_shuffle); 340 BitmapDrawable uncoloredDrawable = (BitmapDrawable) getStyledDrawable(context, 341 R.styleable.lbPlaybackControlsActionIcons_shuffle); 342 Drawable[] drawables = new Drawable[2]; 343 drawables[OFF] = uncoloredDrawable; 344 drawables[ON] = new BitmapDrawable(context.getResources(), 345 createBitmap(uncoloredDrawable.getBitmap(), highlightColor)); 346 setDrawables(drawables); 347 } 348 } 349 350 /** 351 * An action for displaying a HQ (High Quality) icon. 352 */ 353 public static class HighQualityAction extends MultiAction { 354 public static int OFF = 0; 355 public static int ON = 1; 356 357 /** 358 * Constructor 359 * @param context Context used for loading resources. 360 */ 361 public HighQualityAction(Context context) { 362 this(context, getColorFromTheme(context, 363 R.attr.playbackControlsIconHighlightColor)); 364 } 365 366 /** 367 * Constructor 368 * @param context Context used for loading resources. 369 * @param highlightColor Color for the highlighted icon state. 370 */ 371 public HighQualityAction(Context context, int highlightColor) { 372 super(R.id.lb_control_high_quality); 373 BitmapDrawable uncoloredDrawable = (BitmapDrawable) getStyledDrawable(context, 374 R.styleable.lbPlaybackControlsActionIcons_high_quality); 375 Drawable[] drawables = new Drawable[2]; 376 drawables[OFF] = uncoloredDrawable; 377 drawables[ON] = new BitmapDrawable(context.getResources(), 378 createBitmap(uncoloredDrawable.getBitmap(), highlightColor)); 379 setDrawables(drawables); 380 } 381 } 382 383 /** 384 * An action for displaying a CC (Closed Captioning) icon. 385 */ 386 public static class ClosedCaptioningAction extends MultiAction { 387 public static int OFF = 0; 388 public static int ON = 1; 389 390 /** 391 * Constructor 392 * @param context Context used for loading resources. 393 */ 394 public ClosedCaptioningAction(Context context) { 395 this(context, getColorFromTheme(context, 396 R.attr.playbackControlsIconHighlightColor)); 397 } 398 399 /** 400 * Constructor 401 * @param context Context used for loading resources. 402 * @param highlightColor Color for the highlighted icon state. 403 */ 404 public ClosedCaptioningAction(Context context, int highlightColor) { 405 super(R.id.lb_control_high_quality); 406 BitmapDrawable uncoloredDrawable = (BitmapDrawable) getStyledDrawable(context, 407 R.styleable.lbPlaybackControlsActionIcons_closed_captioning); 408 Drawable[] drawables = new Drawable[2]; 409 drawables[OFF] = uncoloredDrawable; 410 drawables[ON] = new BitmapDrawable(context.getResources(), 411 createBitmap(uncoloredDrawable.getBitmap(), highlightColor)); 412 setDrawables(drawables); 413 } 414 } 415 416 private static Bitmap createBitmap(Bitmap bitmap, int color) { 417 Bitmap dst = bitmap.copy(bitmap.getConfig(), true); 418 Canvas canvas = new Canvas(dst); 419 Paint paint = new Paint(); 420 paint.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP)); 421 canvas.drawBitmap(bitmap, 0, 0, paint); 422 return dst; 423 } 424 425 private static int getColorFromTheme(Context context, int attributeResId) { 426 TypedValue outValue = new TypedValue(); 427 context.getTheme().resolveAttribute(attributeResId, outValue, true); 428 return outValue.data; 429 } 430 431 private static Drawable getStyledDrawable(Context context, int index) { 432 TypedValue outValue = new TypedValue(); 433 context.getTheme().resolveAttribute( 434 R.attr.playbackControlsActionIcons, outValue, false); 435 TypedArray array = context.getTheme().obtainStyledAttributes(outValue.data, 436 R.styleable.lbPlaybackControlsActionIcons); 437 Drawable drawable = array.getDrawable(index); 438 array.recycle(); 439 return drawable; 440 } 441 442 private Object mItem; 443 private Drawable mImageDrawable; 444 private ObjectAdapter mPrimaryActionsAdapter; 445 private ObjectAdapter mSecondaryActionsAdapter; 446 private int mTotalTimeMs; 447 private int mCurrentTimeMs; 448 private int mBufferedProgressMs; 449 private OnPlaybackStateChangedListener mListener; 450 451 /** 452 * Constructor for a PlaybackControlsRow that displays some details from 453 * the given item. 454 * 455 * @param item The main item for the row. 456 */ 457 public PlaybackControlsRow(Object item) { 458 mItem = item; 459 } 460 461 /** 462 * Constructor for a PlaybackControlsRow that has no item details. 463 */ 464 public PlaybackControlsRow() { 465 } 466 467 /** 468 * Gets the main item for the details page. 469 */ 470 public final Object getItem() { 471 return mItem; 472 } 473 474 /** 475 * Sets a {link @Drawable} image for this row. 476 * 477 * @param drawable The drawable to set. 478 */ 479 public final void setImageDrawable(Drawable drawable) { 480 mImageDrawable = drawable; 481 } 482 483 /** 484 * Sets a {@link Bitmap} for this row. 485 * 486 * @param context The context to retrieve display metrics from. 487 * @param bm The bitmap to set. 488 */ 489 public final void setImageBitmap(Context context, Bitmap bm) { 490 mImageDrawable = new BitmapDrawable(context.getResources(), bm); 491 } 492 493 /** 494 * Gets the image {@link Drawable} of this row. 495 * 496 * @return The overview's image drawable, or null if no drawable has been 497 * assigned. 498 */ 499 public final Drawable getImageDrawable() { 500 return mImageDrawable; 501 } 502 503 /** 504 * Sets the primary actions {@link ObjectAdapter}. 505 */ 506 public final void setPrimaryActionsAdapter(ObjectAdapter adapter) { 507 mPrimaryActionsAdapter = adapter; 508 } 509 510 /** 511 * Sets the secondary actions {@link ObjectAdapter}. 512 */ 513 public final void setSecondaryActionsAdapter(ObjectAdapter adapter) { 514 mSecondaryActionsAdapter = adapter; 515 } 516 517 /** 518 * Returns the primary actions {@link ObjectAdapter}. 519 */ 520 public final ObjectAdapter getPrimaryActionsAdapter() { 521 return mPrimaryActionsAdapter; 522 } 523 524 /** 525 * Returns the secondary actions {@link ObjectAdapter}. 526 */ 527 public final ObjectAdapter getSecondaryActionsAdapter() { 528 return mSecondaryActionsAdapter; 529 } 530 531 /** 532 * Sets the total time in milliseconds for the playback controls row. 533 */ 534 public void setTotalTime(int ms) { 535 mTotalTimeMs = ms; 536 } 537 538 /** 539 * Returns the total time in milliseconds for the playback controls row. 540 */ 541 public int getTotalTime() { 542 return mTotalTimeMs; 543 } 544 545 /** 546 * Sets the current time in milliseconds for the playback controls row. 547 */ 548 public void setCurrentTime(int ms) { 549 if (mCurrentTimeMs != ms) { 550 mCurrentTimeMs = ms; 551 currentTimeChanged(); 552 } 553 } 554 555 /** 556 * Returns the current time in milliseconds for the playback controls row. 557 */ 558 public int getCurrentTime() { 559 return mCurrentTimeMs; 560 } 561 562 /** 563 * Sets the buffered progress for the playback controls row. 564 */ 565 public void setBufferedProgress(int ms) { 566 if (mBufferedProgressMs != ms) { 567 mBufferedProgressMs = ms; 568 bufferedProgressChanged(); 569 } 570 } 571 572 /** 573 * Returns the buffered progress for the playback controls row. 574 */ 575 public int getBufferedProgress() { 576 return mBufferedProgressMs; 577 } 578 579 interface OnPlaybackStateChangedListener { 580 public void onCurrentTimeChanged(int currentTimeMs); 581 public void onBufferedProgressChanged(int bufferedProgressMs); 582 } 583 584 /** 585 * Sets a listener to be called when the playback state changes. 586 */ 587 public void setOnPlaybackStateChangedListener(OnPlaybackStateChangedListener listener) { 588 mListener = listener; 589 } 590 591 /** 592 * Returns the playback state listener. 593 */ 594 public OnPlaybackStateChangedListener getOnPlaybackStateChangedListener() { 595 return mListener; 596 } 597 598 private void currentTimeChanged() { 599 if (mListener != null) { 600 mListener.onCurrentTimeChanged(mCurrentTimeMs); 601 } 602 } 603 604 private void bufferedProgressChanged() { 605 if (mListener != null) { 606 mListener.onBufferedProgressChanged(mBufferedProgressMs); 607 } 608 } 609} 610