PlaybackControlsPresenter.java revision e5b67be786d519377ae275ef76f3ad72187183d5
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.animation.ValueAnimator; 17import android.graphics.drawable.ClipDrawable; 18import android.graphics.drawable.ColorDrawable; 19import android.graphics.drawable.Drawable; 20import android.graphics.drawable.LayerDrawable; 21import android.support.v17.leanback.R; 22import android.view.Gravity; 23import android.view.LayoutInflater; 24import android.view.View; 25import android.view.ViewGroup; 26import android.view.ViewGroup.MarginLayoutParams; 27import android.view.animation.LinearInterpolator; 28import android.widget.FrameLayout; 29import android.widget.ProgressBar; 30import android.widget.TextView; 31 32/** 33 * A presenter for a control bar that supports "more actions", 34 * and toggling the set of controls between primary and secondary 35 * sets of {@link Actions}. 36 */ 37class PlaybackControlsPresenter extends ControlBarPresenter { 38 39 /** 40 * The data type expected by this presenter. 41 */ 42 static class BoundData extends ControlBarPresenter.BoundData { 43 /** 44 * The adapter containing secondary actions. 45 */ 46 ObjectAdapter secondaryActionsAdapter; 47 } 48 49 class ViewHolder extends ControlBarPresenter.ViewHolder { 50 ObjectAdapter mMoreActionsAdapter; 51 ObjectAdapter.DataObserver mMoreActionsObserver; 52 final FrameLayout mMoreActionsDock; 53 Presenter.ViewHolder mMoreActionsViewHolder; 54 boolean mMoreActionsShowing; 55 final TextView mCurrentTime; 56 final TextView mTotalTime; 57 final ProgressBar mProgressBar; 58 int mCurrentTimeInSeconds; 59 StringBuilder mTotalTimeStringBuilder = new StringBuilder(); 60 StringBuilder mCurrentTimeStringBuilder = new StringBuilder(); 61 int mCurrentTimeMarginStart; 62 int mTotalTimeMarginEnd; 63 64 ViewHolder(View rootView) { 65 super(rootView); 66 mMoreActionsDock = (FrameLayout) rootView.findViewById(R.id.more_actions_dock); 67 mCurrentTime = (TextView) rootView.findViewById(R.id.current_time); 68 mTotalTime = (TextView) rootView.findViewById(R.id.total_time); 69 mProgressBar = (ProgressBar) rootView.findViewById(R.id.playback_progress); 70 mMoreActionsObserver = new ObjectAdapter.DataObserver() { 71 @Override 72 public void onChanged() { 73 if (mMoreActionsShowing) { 74 showControls(mMoreActionsAdapter, mPresenter); 75 } 76 } 77 @Override 78 public void onItemRangeChanged(int positionStart, int itemCount) { 79 if (mMoreActionsShowing) { 80 for (int i = 0; i < itemCount; i++) { 81 bindControlToAction(positionStart + i, 82 mMoreActionsAdapter, mPresenter); 83 } 84 } 85 } 86 }; 87 mCurrentTimeMarginStart = 88 ((MarginLayoutParams) mCurrentTime.getLayoutParams()).getMarginStart(); 89 mTotalTimeMarginEnd = 90 ((MarginLayoutParams) mTotalTime.getLayoutParams()).getMarginEnd(); 91 } 92 93 void showMoreActions() { 94 if (mMoreActionsViewHolder == null) { 95 Action action = new PlaybackControlsRow.MoreActions(mMoreActionsDock.getContext()); 96 mMoreActionsViewHolder = mPresenter.onCreateViewHolder(mMoreActionsDock); 97 mPresenter.onBindViewHolder(mMoreActionsViewHolder, action); 98 mPresenter.setOnClickListener(mMoreActionsViewHolder, new View.OnClickListener() { 99 @Override 100 public void onClick(View v) { 101 toggleMoreActions(); 102 } 103 }); 104 } 105 mMoreActionsDock.addView(mMoreActionsViewHolder.view); 106 } 107 108 void toggleMoreActions() { 109 mMoreActionsShowing = !mMoreActionsShowing; 110 showControls(getAdapter(), mPresenter); 111 } 112 113 @Override 114 ObjectAdapter getAdapter() { 115 return mMoreActionsShowing ? mMoreActionsAdapter : mAdapter; 116 } 117 118 void setTotalTime(int totalTimeMs) { 119 if (totalTimeMs <= 0) { 120 mTotalTime.setVisibility(View.GONE); 121 mProgressBar.setVisibility(View.GONE); 122 } else { 123 mTotalTime.setVisibility(View.VISIBLE); 124 mProgressBar.setVisibility(View.VISIBLE); 125 formatTime(totalTimeMs / 1000, mTotalTimeStringBuilder); 126 mTotalTime.setText(mTotalTimeStringBuilder.toString()); 127 mProgressBar.setMax(totalTimeMs); 128 } 129 } 130 131 int getTotalTime() { 132 return mProgressBar.getMax(); 133 } 134 135 void setCurrentTime(int currentTimeMs) { 136 int seconds = currentTimeMs / 1000; 137 if (seconds != mCurrentTimeInSeconds) { 138 mCurrentTimeInSeconds = seconds; 139 formatTime(mCurrentTimeInSeconds, mCurrentTimeStringBuilder); 140 mCurrentTime.setText(mCurrentTimeStringBuilder.toString()); 141 } 142 mProgressBar.setProgress(currentTimeMs); 143 } 144 145 int getCurrentTime() { 146 return mProgressBar.getProgress(); 147 } 148 149 void setSecondaryProgress(int progressMs) { 150 mProgressBar.setSecondaryProgress(progressMs); 151 } 152 153 int getSecondaryProgress() { 154 return mProgressBar.getSecondaryProgress(); 155 } 156 } 157 158 private static void formatTime(int seconds, StringBuilder sb) { 159 int minutes = seconds / 60; 160 int hours = minutes / 60; 161 seconds -= minutes * 60; 162 minutes -= hours * 60; 163 164 sb.setLength(0); 165 if (hours > 0) { 166 sb.append(hours).append(':'); 167 if (minutes < 10) { 168 sb.append('0'); 169 } 170 } 171 sb.append(minutes).append(':'); 172 if (seconds < 10) { 173 sb.append('0'); 174 } 175 sb.append(seconds); 176 } 177 178 private boolean mMoreActionsEnabled = true; 179 180 /** 181 * Constructor for a PlaybackControlsRowPresenter. 182 * 183 * @param layoutResourceId The resource id of the layout for this presenter. 184 */ 185 public PlaybackControlsPresenter(int layoutResourceId) { 186 super(layoutResourceId); 187 } 188 189 /** 190 * Enables the display of secondary actions. 191 * A "more actions" button will be displayed. When "more actions" is selected, 192 * the primary actions are replaced with the secondary actions. 193 */ 194 public void enableSecondaryActions(boolean enable) { 195 mMoreActionsEnabled = enable; 196 } 197 198 /** 199 * Returns true if secondary actions are enabled. 200 */ 201 public boolean areMoreActionsEnabled() { 202 return mMoreActionsEnabled; 203 } 204 205 public void setProgressColor(ViewHolder vh, int color) { 206 Drawable drawable = new ClipDrawable(new ColorDrawable(color), 207 Gravity.LEFT, ClipDrawable.HORIZONTAL); 208 ((LayerDrawable) vh.mProgressBar.getProgressDrawable()) 209 .setDrawableByLayerId(android.R.id.progress, drawable); 210 } 211 212 public void setTotalTime(ViewHolder vh, int ms) { 213 vh.setTotalTime(ms); 214 } 215 216 public int getTotalTime(ViewHolder vh) { 217 return vh.getTotalTime(); 218 } 219 220 public void setCurrentTime(ViewHolder vh, int ms) { 221 vh.setCurrentTime(ms); 222 } 223 224 public int getCurrentTime(ViewHolder vh) { 225 return vh.getCurrentTime(); 226 } 227 228 public void setSecondaryProgress(ViewHolder vh, int progressMs) { 229 vh.setSecondaryProgress(progressMs); 230 } 231 232 public int getSecondaryProgress(ViewHolder vh) { 233 return vh.getSecondaryProgress(); 234 } 235 236 public void enableTimeMargins(ViewHolder vh, boolean enable) { 237 MarginLayoutParams lp; 238 lp = (MarginLayoutParams) vh.mCurrentTime.getLayoutParams(); 239 lp.setMarginStart(enable ? vh.mCurrentTimeMarginStart : 0); 240 vh.mCurrentTime.setLayoutParams(lp); 241 242 lp = (MarginLayoutParams) vh.mTotalTime.getLayoutParams(); 243 lp.setMarginEnd(enable ? vh.mTotalTimeMarginEnd : 0); 244 vh.mTotalTime.setLayoutParams(lp); 245 } 246 247 @Override 248 public Presenter.ViewHolder onCreateViewHolder(ViewGroup parent) { 249 View v = LayoutInflater.from(parent.getContext()) 250 .inflate(getLayoutResourceId(), parent, false); 251 return new ViewHolder(v); 252 } 253 254 @Override 255 public void onBindViewHolder(Presenter.ViewHolder holder, Object item) { 256 super.onBindViewHolder(holder, item); 257 258 ViewHolder vh = (ViewHolder) holder; 259 BoundData data = (BoundData) item; 260 if (vh.mMoreActionsAdapter != data.secondaryActionsAdapter) { 261 vh.mMoreActionsAdapter = data.secondaryActionsAdapter; 262 vh.mMoreActionsAdapter.registerObserver(vh.mMoreActionsObserver); 263 } 264 if (mMoreActionsEnabled) { 265 vh.showMoreActions(); 266 } 267 } 268 269 @Override 270 public void onUnbindViewHolder(Presenter.ViewHolder holder) { 271 super.onUnbindViewHolder(holder); 272 ViewHolder vh = (ViewHolder) holder; 273 vh.mMoreActionsAdapter.unregisterObserver(vh.mMoreActionsObserver); 274 vh.mMoreActionsAdapter = null; 275 } 276} 277