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