13bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu/* 23bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Copyright (C) 2017 The Android Open Source Project 33bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * 43bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Licensed under the Apache License, Version 2.0 (the "License"); 53bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * you may not use this file except in compliance with the License. 63bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * You may obtain a copy of the License at 73bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * 83bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * http://www.apache.org/licenses/LICENSE-2.0 93bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * 103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Unless required by applicable law or agreed to in writing, software 113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * distributed under the License is distributed on an "AS IS" BASIS, 123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * See the License for the specific language governing permissions and 143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * limitations under the License. 153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gupackage android.support.v17.leanback.widget; 173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 183bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.content.Context; 193bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.graphics.Bitmap; 203bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.graphics.Color; 213bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.os.Build; 223bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.support.annotation.ColorInt; 233bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.support.v17.leanback.R; 243bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.support.v17.leanback.widget.ControlBarPresenter.OnControlClickedListener; 253bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.support.v17.leanback.widget.ControlBarPresenter.OnControlSelectedListener; 263bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.util.TypedValue; 273bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.view.KeyEvent; 283bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.view.LayoutInflater; 293bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.view.View; 303bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.view.ViewGroup; 313bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.widget.ImageView; 323bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.widget.TextView; 333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 343bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport java.util.Arrays; 353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu/** 373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * A PlaybackTransportRowPresenter renders a {@link PlaybackControlsRow} to display a 383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * series of playback control buttons. Typically this row will be the first row in a fragment 393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * such as the {@link android.support.v17.leanback.app.PlaybackSupportFragment}. 403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * 413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <p>The detailed description is rendered using a {@link Presenter} passed in 423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * {@link #setDescriptionPresenter(Presenter)}. This can be an instance of 433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * {@link AbstractDetailsDescriptionPresenter}. The application can access the 443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * detailed description ViewHolder from {@link ViewHolder#getDescriptionViewHolder()}. 453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * </p> 463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gupublic class PlaybackTransportRowPresenter extends PlaybackRowPresenter { 483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu static class BoundData extends PlaybackControlsPresenter.BoundData { 503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ViewHolder mRowViewHolder; 513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * A ViewHolder for the PlaybackControlsRow supporting seek UI. 553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public class ViewHolder extends PlaybackRowPresenter.ViewHolder implements PlaybackSeekUi { 573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final Presenter.ViewHolder mDescriptionViewHolder; 583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final ImageView mImageView; 593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final ViewGroup mDescriptionDock; 603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final ViewGroup mControlsDock; 613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final ViewGroup mSecondaryControlsDock; 623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final TextView mTotalTime; 633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final TextView mCurrentTime; 643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final SeekBar mProgressBar; 653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final ThumbsBar mThumbsBar; 663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu long mTotalTimeInMs = Long.MIN_VALUE; 673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu long mCurrentTimeInMs = Long.MIN_VALUE; 683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu long mSecondaryProgressInMs; 693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final StringBuilder mTempBuilder = new StringBuilder(); 703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ControlBarPresenter.ViewHolder mControlsVh; 713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ControlBarPresenter.ViewHolder mSecondaryControlsVh; 723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu BoundData mControlsBoundData = new BoundData(); 733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu BoundData mSecondaryBoundData = new BoundData(); 743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu Presenter.ViewHolder mSelectedViewHolder; 753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu Object mSelectedItem; 763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu PlaybackControlsRow.PlayPauseAction mPlayPauseAction; 773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu int mThumbHeroIndex = -1; 783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu Client mSeekClient; 803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu boolean mInSeek; 813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu PlaybackSeekDataProvider mSeekDataProvider; 823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu long[] mPositions; 833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu int mPositionsLength; 843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final PlaybackControlsRow.OnPlaybackProgressCallback mListener = 863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu new PlaybackControlsRow.OnPlaybackProgressCallback() { 873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void onCurrentPositionChanged(PlaybackControlsRow row, long ms) { 893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu setCurrentPosition(ms); 903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void onDurationChanged(PlaybackControlsRow row, long ms) { 943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu setTotalTime(ms); 953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void onBufferedPositionChanged(PlaybackControlsRow row, long ms) { 993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu setBufferedPosition(ms); 1003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu }; 1023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 1033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu void updateProgressInSeek(boolean forward) { 1043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu long newPos; 1053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu long pos = mCurrentTimeInMs; 1063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mPositionsLength > 0) { 1073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu int index = Arrays.binarySearch(mPositions, 0, mPositionsLength, pos); 1083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu int thumbHeroIndex; 1093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (forward) { 1103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (index >= 0) { 1113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu // found it, seek to neighbour key position at higher side 1123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (index < mPositionsLength - 1) { 1133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu newPos = mPositions[index + 1]; 1143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu thumbHeroIndex = index + 1; 1153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } else { 1163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu newPos = mTotalTimeInMs; 1173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu thumbHeroIndex = index; 1183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } else { 1203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu // not found, seek to neighbour key position at higher side. 1213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu int insertIndex = -1 - index; 1223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (insertIndex <= mPositionsLength - 1) { 1233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu newPos = mPositions[insertIndex]; 1243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu thumbHeroIndex = insertIndex; 1253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } else { 1263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu newPos = mTotalTimeInMs; 1273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu thumbHeroIndex = insertIndex > 0 ? insertIndex - 1 : 0; 1283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } else { 1313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (index >= 0) { 1323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu // found it, seek to neighbour key position at lower side. 1333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (index > 0) { 1343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu newPos = mPositions[index - 1]; 1353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu thumbHeroIndex = index - 1; 1363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } else { 1373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu newPos = 0; 1383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu thumbHeroIndex = 0; 1393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } else { 1413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu // not found, seek to neighbour key position at lower side. 1423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu int insertIndex = -1 - index; 1433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (insertIndex > 0) { 1443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu newPos = mPositions[insertIndex - 1]; 1453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu thumbHeroIndex = insertIndex - 1; 1463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } else { 1473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu newPos = 0; 1483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu thumbHeroIndex = 0; 1493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu updateThumbsInSeek(thumbHeroIndex, forward); 1533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } else { 1543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu long interval = (long) (mTotalTimeInMs * getDefaultSeekIncrement()); 1553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu newPos = pos + (forward ? interval : -interval); 1563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (newPos > mTotalTimeInMs) { 1573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu newPos = mTotalTimeInMs; 1583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } else if (newPos < 0) { 1593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu newPos = 0; 1603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu double ratio = (double) newPos / mTotalTimeInMs; // Range: [0, 1] 1633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mProgressBar.setProgress((int) (ratio * Integer.MAX_VALUE)); // Could safely cast to int 1643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSeekClient.onSeekPositionChanged(newPos); 1653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 1673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu void updateThumbsInSeek(int thumbHeroIndex, boolean forward) { 1683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mThumbHeroIndex == thumbHeroIndex) { 1693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return; 1703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 1723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final int totalNum = mThumbsBar.getChildCount(); 1733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (totalNum < 0 || (totalNum & 1) == 0) { 1743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu throw new RuntimeException(); 1753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final int heroChildIndex = totalNum / 2; 1773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final int start = Math.max(thumbHeroIndex - (totalNum / 2), 0); 1783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final int end = Math.min(thumbHeroIndex + (totalNum / 2), mPositionsLength - 1); 1793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final int newRequestStart; 1803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final int newRequestEnd; 1813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 1823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mThumbHeroIndex < 0) { 1833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu // first time 1843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu newRequestStart = start; 1853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu newRequestEnd = end; 1863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } else { 1873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu forward = thumbHeroIndex > mThumbHeroIndex; 1883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final int oldStart = Math.max(mThumbHeroIndex - (totalNum / 2), 0); 1893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final int oldEnd = Math.min(mThumbHeroIndex + (totalNum / 2), 1903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPositionsLength - 1); 1913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (forward) { 1923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu newRequestStart = Math.max(oldEnd + 1, start); 1933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu newRequestEnd = end; 1943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu // overlapping area directly assign bitmap from previous result 1953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu for (int i = start; i <= newRequestStart - 1; i++) { 1963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mThumbsBar.setThumbBitmap(heroChildIndex + (i - thumbHeroIndex), 1973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mThumbsBar.getThumbBitmap(heroChildIndex + (i - mThumbHeroIndex))); 1983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } else { 2003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu newRequestEnd = Math.min(oldStart - 1, end); 2013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu newRequestStart = start; 2023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu // overlapping area directly assign bitmap from previous result in backward 2033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu for (int i = end; i >= newRequestEnd + 1; i--) { 2043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mThumbsBar.setThumbBitmap(heroChildIndex + (i - thumbHeroIndex), 2053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mThumbsBar.getThumbBitmap(heroChildIndex + (i - mThumbHeroIndex))); 2063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu // processing new requests with mThumbHeroIndex updated 2103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mThumbHeroIndex = thumbHeroIndex; 2113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (forward) { 2123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu for (int i = newRequestStart; i <= newRequestEnd; i++) { 2133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSeekDataProvider.getThumbnail(i, mThumbResult); 2143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } else { 2163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu for (int i = newRequestEnd; i >= newRequestStart; i--) { 2173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSeekDataProvider.getThumbnail(i, mThumbResult); 2183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu // set thumb bitmaps outside (start , end) to null 2213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu for (int childIndex = 0; childIndex < heroChildIndex - mThumbHeroIndex + start; 2223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu childIndex++) { 2233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mThumbsBar.setThumbBitmap(childIndex, null); 2243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu for (int childIndex = heroChildIndex + end - mThumbHeroIndex + 1; 2263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu childIndex < totalNum; childIndex++) { 2273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mThumbsBar.setThumbBitmap(childIndex, null); 2283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 2313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu PlaybackSeekDataProvider.ResultCallback mThumbResult = 2323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu new PlaybackSeekDataProvider.ResultCallback() { 2333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 2343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void onThumbnailLoaded(Bitmap bitmap, int index) { 2353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu int childIndex = index - (mThumbHeroIndex - mThumbsBar.getChildCount() / 2); 2363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (childIndex < 0 || childIndex >= mThumbsBar.getChildCount()) { 2373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return; 2383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mThumbsBar.setThumbBitmap(childIndex, bitmap); 2403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu }; 2423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 2433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu boolean onForward() { 2443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (!startSeek()) { 2453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return false; 2463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu updateProgressInSeek(true); 2483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return true; 2493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 2513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu boolean onBackward() { 2523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (!startSeek()) { 2533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return false; 2543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu updateProgressInSeek(false); 2563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return true; 2573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 2593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Constructor of ViewHolder of PlaybackTransportRowPresenter 2603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * @param rootView Root view of the ViewHolder. 2613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * @param descriptionPresenter The presenter that will be used to create description 2623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * ViewHolder. The description view will be added into tree. 2633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 2643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public ViewHolder(View rootView, Presenter descriptionPresenter) { 2653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu super(rootView); 2663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mImageView = (ImageView) rootView.findViewById(R.id.image); 2673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mDescriptionDock = (ViewGroup) rootView.findViewById(R.id.description_dock); 2683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mCurrentTime = (TextView) rootView.findViewById(R.id.current_time); 2693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mTotalTime = (TextView) rootView.findViewById(R.id.total_time); 2703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mProgressBar = (SeekBar) rootView.findViewById(R.id.playback_progress); 2713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mProgressBar.setOnClickListener(new View.OnClickListener() { 2723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 2733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void onClick(View view) { 2743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu onProgressBarClicked(ViewHolder.this); 2753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu }); 2773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mProgressBar.setOnKeyListener(new View.OnKeyListener() { 2783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 2793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 2803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public boolean onKey(View view, int keyCode, KeyEvent keyEvent) { 2813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu // when in seek only allow this keys 2823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu switch (keyCode) { 2833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu case KeyEvent.KEYCODE_DPAD_UP: 2843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu case KeyEvent.KEYCODE_DPAD_DOWN: 2853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu // eat DPAD UP/DOWN in seek mode 2863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return mInSeek; 2873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu case KeyEvent.KEYCODE_DPAD_LEFT: 2883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu case KeyEvent.KEYCODE_MINUS: 2893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu case KeyEvent.KEYCODE_MEDIA_REWIND: 2903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) { 2913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu onBackward(); 2923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return true; 2943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu case KeyEvent.KEYCODE_DPAD_RIGHT: 2953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu case KeyEvent.KEYCODE_PLUS: 2963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 2973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) { 2983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu onForward(); 2993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return true; 3013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu case KeyEvent.KEYCODE_DPAD_CENTER: 3023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu case KeyEvent.KEYCODE_ENTER: 3033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (!mInSeek) { 3043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return false; 3053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (keyEvent.getAction() == KeyEvent.ACTION_UP) { 3073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu stopSeek(false); 3083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return true; 3103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu case KeyEvent.KEYCODE_BACK: 3113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu case KeyEvent.KEYCODE_ESCAPE: 3123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (!mInSeek) { 3133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return false; 3143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (keyEvent.getAction() == KeyEvent.ACTION_UP) { 3163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu // SeekBar does not support cancel in accessibility mode, so always 3173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu // "confirm" if accessibility is on. 3183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu stopSeek(Build.VERSION.SDK_INT >= 21 3193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ? !mProgressBar.isAccessibilityFocused() : true); 3203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return true; 3223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return false; 3243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu }); 3263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mProgressBar.setAccessibilitySeekListener(new SeekBar.AccessibilitySeekListener() { 3273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 3283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public boolean onAccessibilitySeekForward() { 3293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return onForward(); 3303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 3323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 3333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public boolean onAccessibilitySeekBackward() { 3343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return onBackward(); 3353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu }); 3373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mProgressBar.setMax(Integer.MAX_VALUE); //current progress will be a fraction of this 3383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mControlsDock = (ViewGroup) rootView.findViewById(R.id.controls_dock); 3393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSecondaryControlsDock = 3403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu (ViewGroup) rootView.findViewById(R.id.secondary_controls_dock); 3413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mDescriptionViewHolder = descriptionPresenter == null ? null : 3423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu descriptionPresenter.onCreateViewHolder(mDescriptionDock); 3433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mDescriptionViewHolder != null) { 3443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mDescriptionDock.addView(mDescriptionViewHolder.view); 3453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mThumbsBar = (ThumbsBar) rootView.findViewById(R.id.thumbs_row); 3473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 3493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 3503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * @return The ViewHolder for description. 3513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 3523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public final Presenter.ViewHolder getDescriptionViewHolder() { 3533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return mDescriptionViewHolder; 3543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 3563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 3573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void setPlaybackSeekUiClient(Client client) { 3583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSeekClient = client; 3593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 3613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu boolean startSeek() { 3623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mInSeek) { 3633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return true; 3643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mSeekClient == null || !mSeekClient.isSeekEnabled() 3663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu || mTotalTimeInMs <= 0) { 3673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return false; 3683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mInSeek = true; 3703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSeekClient.onSeekStarted(); 3713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSeekDataProvider = mSeekClient.getPlaybackSeekDataProvider(); 3723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPositions = mSeekDataProvider != null ? mSeekDataProvider.getSeekPositions() : null; 3733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mPositions != null) { 3743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu int pos = Arrays.binarySearch(mPositions, mTotalTimeInMs); 3753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (pos >= 0) { 3763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPositionsLength = pos + 1; 3773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } else { 3783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPositionsLength = -1 - pos; 3793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } else { 3813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPositionsLength = 0; 3823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mControlsVh.view.setVisibility(View.INVISIBLE); 3843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSecondaryControlsVh.view.setVisibility(View.INVISIBLE); 3853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mDescriptionViewHolder.view.setVisibility(View.INVISIBLE); 3863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mThumbsBar.setVisibility(View.VISIBLE); 3873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return true; 3883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 3903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu void stopSeek(boolean cancelled) { 3913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (!mInSeek) { 3923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return; 3933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mInSeek = false; 3953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSeekClient.onSeekFinished(cancelled); 3963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mSeekDataProvider != null) { 3973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSeekDataProvider.reset(); 3983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mThumbHeroIndex = -1; 4003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mThumbsBar.clearThumbBitmaps(); 4013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSeekDataProvider = null; 4023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPositions = null; 4033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPositionsLength = 0; 4043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mControlsVh.view.setVisibility(View.VISIBLE); 4053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSecondaryControlsVh.view.setVisibility(View.VISIBLE); 4063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mDescriptionViewHolder.view.setVisibility(View.VISIBLE); 4073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mThumbsBar.setVisibility(View.INVISIBLE); 4083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 4093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 4103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu void dispatchItemSelection() { 4113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (!isSelected()) { 4123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return; 4133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 4143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mSelectedViewHolder == null) { 4153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (getOnItemViewSelectedListener() != null) { 4163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu getOnItemViewSelectedListener().onItemSelected(null, null, 4173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ViewHolder.this, getRow()); 4183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 4193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } else { 4203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (getOnItemViewSelectedListener() != null) { 4213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu getOnItemViewSelectedListener().onItemSelected(mSelectedViewHolder, 4223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSelectedItem, ViewHolder.this, getRow()); 4233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 4243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 4253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu }; 4263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 4273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu Presenter getPresenter(boolean primary) { 4283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ObjectAdapter adapter = primary 4293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ? ((PlaybackControlsRow) getRow()).getPrimaryActionsAdapter() 4303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu : ((PlaybackControlsRow) getRow()).getSecondaryActionsAdapter(); 4313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (adapter == null) { 4323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return null; 4333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 4343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (adapter.getPresenterSelector() instanceof ControlButtonPresenterSelector) { 4353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ControlButtonPresenterSelector selector = 4363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu (ControlButtonPresenterSelector) adapter.getPresenterSelector(); 4373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return selector.getSecondaryPresenter(); 4383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 4393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return adapter.getPresenter(adapter.size() > 0 ? adapter.get(0) : null); 4403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 4413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 4423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 4433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Returns the TextView that showing total time label. This method might be used in 4443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * {@link #onSetDurationLabel}. 4453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * @return The TextView that showing total time label. 4463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 4473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public final TextView getDurationView() { 4483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return mTotalTime; 4493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 4503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 4513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 4523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Called to update total time label. Default implementation updates the TextView 4533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * {@link #getDurationView()}. Subclass might override. 4543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * @param totalTimeMs Total duration of the media in milliseconds. 4553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 4563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu protected void onSetDurationLabel(long totalTimeMs) { 4573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mTotalTime != null) { 4583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu formatTime(totalTimeMs, mTempBuilder); 4593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mTotalTime.setText(mTempBuilder.toString()); 4603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 4613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 4623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 4633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu void setTotalTime(long totalTimeMs) { 4643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mTotalTimeInMs != totalTimeMs) { 4653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mTotalTimeInMs = totalTimeMs; 4663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu onSetDurationLabel(totalTimeMs); 4673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 4683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 4693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 4703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 4713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Returns the TextView that showing current position label. This method might be used in 4723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * {@link #onSetCurrentPositionLabel}. 4733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * @return The TextView that showing current position label. 4743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 4753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public final TextView getCurrentPositionView() { 4763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return mCurrentTime; 4773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 4783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 4793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 4803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Called to update current time label. Default implementation updates the TextView 4813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * {@link #getCurrentPositionView}. Subclass might override. 4823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * @param currentTimeMs Current playback position in milliseconds. 4833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 4843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu protected void onSetCurrentPositionLabel(long currentTimeMs) { 4853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mCurrentTime != null) { 4863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu formatTime(currentTimeMs, mTempBuilder); 4873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mCurrentTime.setText(mTempBuilder.toString()); 4883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 4893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 4903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 4913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu void setCurrentPosition(long currentTimeMs) { 4923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (currentTimeMs != mCurrentTimeInMs) { 4933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mCurrentTimeInMs = currentTimeMs; 4943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu onSetCurrentPositionLabel(currentTimeMs); 4953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 4963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (!mInSeek) { 4973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu int progressRatio = 0; 4983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mTotalTimeInMs > 0) { 4993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu // Use ratio to represent current progres 5003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu double ratio = (double) mCurrentTimeInMs / mTotalTimeInMs; // Range: [0, 1] 5013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu progressRatio = (int) (ratio * Integer.MAX_VALUE); // Could safely cast to int 5023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 5033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mProgressBar.setProgress((int) progressRatio); 5043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 5053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 5063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 5073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu void setBufferedPosition(long progressMs) { 5083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSecondaryProgressInMs = progressMs; 5093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu // Solve the progress bar by using ratio 5103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu double ratio = (double) progressMs / mTotalTimeInMs; // Range: [0, 1] 5113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu double progressRatio = ratio * Integer.MAX_VALUE; // Could safely cast to int 5123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mProgressBar.setSecondaryProgress((int) progressRatio); 5133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 5143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 5153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 5163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu static void formatTime(long ms, StringBuilder sb) { 5173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu sb.setLength(0); 5183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (ms < 0) { 5193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu sb.append("--"); 5203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return; 5213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 5223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu long seconds = ms / 1000; 5233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu long minutes = seconds / 60; 5243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu long hours = minutes / 60; 5253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu seconds -= minutes * 60; 5263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu minutes -= hours * 60; 5273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 5283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (hours > 0) { 5293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu sb.append(hours).append(':'); 5303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (minutes < 10) { 5313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu sb.append('0'); 5323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 5333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 5343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu sb.append(minutes).append(':'); 5353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (seconds < 10) { 5363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu sb.append('0'); 5373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 5383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu sb.append(seconds); 5393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 5403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 5413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu float mDefaultSeekIncrement = 0.01f; 5423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu int mProgressColor = Color.TRANSPARENT; 5433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu boolean mProgressColorSet; 5443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu Presenter mDescriptionPresenter; 5453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ControlBarPresenter mPlaybackControlsPresenter; 5463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ControlBarPresenter mSecondaryControlsPresenter; 5473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu OnActionClickedListener mOnActionClickedListener; 5483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 5493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu private final OnControlSelectedListener mOnControlSelectedListener = 5503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu new OnControlSelectedListener() { 5513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 5523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void onControlSelected(Presenter.ViewHolder itemViewHolder, Object item, 5533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ControlBarPresenter.BoundData data) { 5543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ViewHolder vh = ((BoundData) data).mRowViewHolder; 5553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (vh.mSelectedViewHolder != itemViewHolder || vh.mSelectedItem != item) { 5563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.mSelectedViewHolder = itemViewHolder; 5573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.mSelectedItem = item; 5583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.dispatchItemSelection(); 5593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 5603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 5613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu }; 5623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 5633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu private final OnControlClickedListener mOnControlClickedListener = 5643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu new OnControlClickedListener() { 5653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 5663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void onControlClicked(Presenter.ViewHolder itemViewHolder, Object item, 5673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ControlBarPresenter.BoundData data) { 5683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ViewHolder vh = ((BoundData) data).mRowViewHolder; 5693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (vh.getOnItemViewClickedListener() != null) { 5703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.getOnItemViewClickedListener().onItemClicked(itemViewHolder, item, 5713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh, vh.getRow()); 5723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 5733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mOnActionClickedListener != null && item instanceof Action) { 5743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mOnActionClickedListener.onActionClicked((Action) item); 5753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 5763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 5773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu }; 5783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 5793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public PlaybackTransportRowPresenter() { 5803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu setHeaderPresenter(null); 5813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu setSelectEffectEnabled(false); 5823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 5833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPlaybackControlsPresenter = new ControlBarPresenter(R.layout.lb_control_bar); 5843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPlaybackControlsPresenter.setDefaultFocusToMiddle(false); 5853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSecondaryControlsPresenter = new ControlBarPresenter(R.layout.lb_control_bar); 5863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSecondaryControlsPresenter.setDefaultFocusToMiddle(false); 5873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 5883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPlaybackControlsPresenter.setOnControlSelectedListener(mOnControlSelectedListener); 5893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSecondaryControlsPresenter.setOnControlSelectedListener(mOnControlSelectedListener); 5903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPlaybackControlsPresenter.setOnControlClickedListener(mOnControlClickedListener); 5913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSecondaryControlsPresenter.setOnControlClickedListener(mOnControlClickedListener); 5923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 5933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 5943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 5953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * @param descriptionPresenter Presenter for displaying item details. 5963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 5973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void setDescriptionPresenter(Presenter descriptionPresenter) { 5983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mDescriptionPresenter = descriptionPresenter; 5993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 6003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 6013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 6023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Sets the listener for {@link Action} click events. 6033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 6043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void setOnActionClickedListener(OnActionClickedListener listener) { 6053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mOnActionClickedListener = listener; 6063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 6073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 6083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 6093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Returns the listener for {@link Action} click events. 6103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 6113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public OnActionClickedListener getOnActionClickedListener() { 6123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return mOnActionClickedListener; 6133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 6143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 6153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 6163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Sets the primary color for the progress bar. If not set, a default from 6173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * the theme will be used. 6183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 6193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void setProgressColor(@ColorInt int color) { 6203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mProgressColor = color; 6213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mProgressColorSet = true; 6223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 6233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 6243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 6253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Returns the primary color for the progress bar. If no color was set, transparent 6263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * is returned. 6273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 6283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @ColorInt 6293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public int getProgressColor() { 6303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return mProgressColor; 6313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 6323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 6333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 6343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void onReappear(RowPresenter.ViewHolder rowViewHolder) { 6353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ViewHolder vh = (ViewHolder) rowViewHolder; 6363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (vh.view.hasFocus()) { 6373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.mProgressBar.requestFocus(); 6383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 6393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 6403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 6413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu private int getDefaultProgressColor(Context context) { 6423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu TypedValue outValue = new TypedValue(); 6433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (context.getTheme() 6443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu .resolveAttribute(R.attr.playbackProgressPrimaryColor, outValue, true)) { 6453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return context.getResources().getColor(outValue.resourceId); 6463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 6473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return context.getResources().getColor(R.color.lb_playback_progress_color_no_theme); 6483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 6493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 6503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 6513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu protected RowPresenter.ViewHolder createRowViewHolder(ViewGroup parent) { 6523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu View v = LayoutInflater.from(parent.getContext()).inflate( 6533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu R.layout.lb_playback_transport_controls_row, parent, false); 6543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ViewHolder vh = new ViewHolder(v, mDescriptionPresenter); 6553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu initRow(vh); 6563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return vh; 6573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 6583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 6593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu private void initRow(final ViewHolder vh) { 6603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.mControlsVh = (ControlBarPresenter.ViewHolder) mPlaybackControlsPresenter 6613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu .onCreateViewHolder(vh.mControlsDock); 6623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.mProgressBar.setProgressColor(mProgressColorSet ? mProgressColor 6633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu : getDefaultProgressColor(vh.mControlsDock.getContext())); 6643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.mControlsDock.addView(vh.mControlsVh.view); 6653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 6663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.mSecondaryControlsVh = (ControlBarPresenter.ViewHolder) mSecondaryControlsPresenter 6673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu .onCreateViewHolder(vh.mSecondaryControlsDock); 6683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.mSecondaryControlsDock.addView(vh.mSecondaryControlsVh.view); 6693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ((PlaybackTransportRowView) vh.view).setOnUnhandledKeyListener( 6703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu new PlaybackTransportRowView.OnUnhandledKeyListener() { 6713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 6723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public boolean onUnhandledKey(KeyEvent event) { 6733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (vh.getOnKeyListener() != null) { 6743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (vh.getOnKeyListener().onKey(vh.view, event.getKeyCode(), event)) { 6753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return true; 6763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 6773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 6783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return false; 6793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 6803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu }); 6813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 6823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 6833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 6843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu protected void onBindRowViewHolder(RowPresenter.ViewHolder holder, Object item) { 6853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu super.onBindRowViewHolder(holder, item); 6863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 6873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ViewHolder vh = (ViewHolder) holder; 6883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu PlaybackControlsRow row = (PlaybackControlsRow) vh.getRow(); 6893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 6903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (row.getItem() == null) { 6913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.mDescriptionDock.setVisibility(View.GONE); 6923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } else { 6933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.mDescriptionDock.setVisibility(View.VISIBLE); 6943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (vh.mDescriptionViewHolder != null) { 6953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mDescriptionPresenter.onBindViewHolder(vh.mDescriptionViewHolder, row.getItem()); 6963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 6973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 6983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 6993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (row.getImageDrawable() == null) { 7003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.mImageView.setVisibility(View.GONE); 7013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } else { 7023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.mImageView.setVisibility(View.VISIBLE); 7033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 7043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.mImageView.setImageDrawable(row.getImageDrawable()); 7053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 7063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.mControlsBoundData.adapter = row.getPrimaryActionsAdapter(); 7073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.mControlsBoundData.presenter = vh.getPresenter(true); 7083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.mControlsBoundData.mRowViewHolder = vh; 7093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPlaybackControlsPresenter.onBindViewHolder(vh.mControlsVh, vh.mControlsBoundData); 7103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 7113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.mSecondaryBoundData.adapter = row.getSecondaryActionsAdapter(); 7123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.mSecondaryBoundData.presenter = vh.getPresenter(false); 7133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.mSecondaryBoundData.mRowViewHolder = vh; 7143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSecondaryControlsPresenter.onBindViewHolder(vh.mSecondaryControlsVh, 7153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.mSecondaryBoundData); 7163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 7173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.setTotalTime(row.getDuration()); 7183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.setCurrentPosition(row.getCurrentPosition()); 7193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.setBufferedPosition(row.getBufferedPosition()); 7203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu row.setOnPlaybackProgressChangedListener(vh.mListener); 7213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 7223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 7233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 7243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu protected void onUnbindRowViewHolder(RowPresenter.ViewHolder holder) { 7253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ViewHolder vh = (ViewHolder) holder; 7263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu PlaybackControlsRow row = (PlaybackControlsRow) vh.getRow(); 7273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 7283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (vh.mDescriptionViewHolder != null) { 7293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mDescriptionPresenter.onUnbindViewHolder(vh.mDescriptionViewHolder); 7303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 7313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPlaybackControlsPresenter.onUnbindViewHolder(vh.mControlsVh); 7323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSecondaryControlsPresenter.onUnbindViewHolder(vh.mSecondaryControlsVh); 7333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu row.setOnPlaybackProgressChangedListener(null); 7343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 7353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu super.onUnbindRowViewHolder(holder); 7363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 7373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 7383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 7393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Client of progress bar is clicked, default implementation delegate click to 7403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * PlayPauseAction. 7413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * 7423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * @param vh ViewHolder of PlaybackTransportRowPresenter 7433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 7443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu protected void onProgressBarClicked(ViewHolder vh) { 7453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (vh != null) { 7463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (vh.mPlayPauseAction == null) { 7473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.mPlayPauseAction = new PlaybackControlsRow.PlayPauseAction(vh.view.getContext()); 7483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 7493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (vh.getOnItemViewClickedListener() != null) { 7503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh.getOnItemViewClickedListener().onItemClicked(vh, vh.mPlayPauseAction, 7513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu vh, vh.getRow()); 7523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 7533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mOnActionClickedListener != null) { 7543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mOnActionClickedListener.onActionClicked(vh.mPlayPauseAction); 7553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 7563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 7573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 7583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 7593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 7603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Set default seek increment if {@link PlaybackSeekDataProvider} is null. 7613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * @param ratio float value between 0(inclusive) and 1(inclusive). 7623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 7633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void setDefaultSeekIncrement(float ratio) { 7643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mDefaultSeekIncrement = ratio; 7653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 7663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 7673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 7683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Get default seek increment if {@link PlaybackSeekDataProvider} is null. 7693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * @return float value between 0(inclusive) and 1(inclusive). 7703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 7713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public float getDefaultSeekIncrement() { 7723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return mDefaultSeekIncrement; 7733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 7743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 7753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 7763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu protected void onRowViewSelected(RowPresenter.ViewHolder vh, boolean selected) { 7773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu super.onRowViewSelected(vh, selected); 7783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (selected) { 7793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ((ViewHolder) vh).dispatchItemSelection(); 7803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 7813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 7823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 7833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 7843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu protected void onRowViewAttachedToWindow(RowPresenter.ViewHolder vh) { 7853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu super.onRowViewAttachedToWindow(vh); 7863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mDescriptionPresenter != null) { 7873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mDescriptionPresenter.onViewAttachedToWindow( 7883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ((ViewHolder) vh).mDescriptionViewHolder); 7893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 7903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 7913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 7923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 7933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu protected void onRowViewDetachedFromWindow(RowPresenter.ViewHolder vh) { 7943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu super.onRowViewDetachedFromWindow(vh); 7953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mDescriptionPresenter != null) { 7963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mDescriptionPresenter.onViewDetachedFromWindow( 7973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu ((ViewHolder) vh).mDescriptionViewHolder); 7983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 7993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 8003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 8013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu} 802