summaryrefslogtreecommitdiffstats
path: root/src/com/android/gallery3d/app/TimeBar.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/gallery3d/app/TimeBar.java')
-rwxr-xr-x[-rw-r--r--]src/com/android/gallery3d/app/TimeBar.java373
1 files changed, 346 insertions, 27 deletions
diff --git a/src/com/android/gallery3d/app/TimeBar.java b/src/com/android/gallery3d/app/TimeBar.java
index 246346a56..2870c489c 100644..100755
--- a/src/com/android/gallery3d/app/TimeBar.java
+++ b/src/com/android/gallery3d/app/TimeBar.java
@@ -22,13 +22,17 @@ import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
+import android.text.TextUtils;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import com.android.gallery3d.R;
import com.android.gallery3d.common.Utils;
+import java.util.Locale;
+
/**
* The time bar view, which includes the current and total time, the progress
* bar, and the scrubber.
@@ -51,6 +55,10 @@ public class TimeBar extends View {
private static final int TEXT_SIZE_IN_DP = 14;
+ private static final String TAG = "Gallery3D/TimeBar";
+ private static final boolean LOG = false;
+ public static final int UNKNOWN = -1;
+
protected final Listener mListener;
// the bars we use for displaying the progress
@@ -71,6 +79,7 @@ public class TimeBar extends View {
protected boolean mScrubbing;
protected boolean mShowTimes;
protected boolean mShowScrubber;
+ private boolean mEnableScrubbing;
protected int mTotalTime;
protected int mCurrentTime;
@@ -78,6 +87,11 @@ public class TimeBar extends View {
protected final Rect mTimeBounds;
protected int mVPaddingInPx;
+ private int mLastShowTime = UNKNOWN;
+
+ private ITimeBarSecondaryProgressExt mSecondaryProgressExt = new TimeBarSecondaryProgressExtImpl();
+ private ITimeBarInfoExt mInfoExt = new TimeBarInfoExtImpl();
+ private ITimeBarLayoutExt mLayoutExt = new TimeBarLayoutExtImpl();
public TimeBar(Context context, Listener listener) {
super(context);
@@ -108,21 +122,53 @@ public class TimeBar extends View {
mScrubberPadding = (int) (metrics.density * SCRUBBER_PADDING_IN_DP);
mVPaddingInPx = (int) (metrics.density * V_PADDING_IN_DP);
+ mLayoutExt.init(mScrubberPadding, mVPaddingInPx);
+ mInfoExt.init(textSizeInPx);
+ mSecondaryProgressExt.init();
}
private void update() {
mPlayedBar.set(mProgressBar);
if (mTotalTime > 0) {
- mPlayedBar.right =
- mPlayedBar.left + (int) ((mProgressBar.width() * (long) mCurrentTime) / mTotalTime);
+ if (View.LAYOUT_DIRECTION_RTL == TextUtils
+ .getLayoutDirectionFromLocale(Locale.getDefault())) {
+ // The progress bar should be reversed in RTL.
+ mPlayedBar.left = mPlayedBar.right
+ - (int) ((mProgressBar.width() * (long) mCurrentTime) / mTotalTime);
+ } else {
+ mPlayedBar.right = mPlayedBar.left
+ + (int) ((mProgressBar.width() * (long) mCurrentTime) / mTotalTime);
+ }
+ /*
+ * M: if duration is not accurate, here just adjust playedBar we
+ * also show the accurate position text to final user.
+ */
+ if (mPlayedBar.right > mProgressBar.right) {
+ mPlayedBar.right = mProgressBar.right;
+ }
} else {
- mPlayedBar.right = mProgressBar.left;
+ if (View.LAYOUT_DIRECTION_RTL == TextUtils
+ .getLayoutDirectionFromLocale(Locale.getDefault())) {
+ // The progress bar should be reversed in RTL.
+ mPlayedBar.left = mProgressBar.right;
+ } else {
+ mPlayedBar.right = mProgressBar.left;
+ }
}
if (!mScrubbing) {
- mScrubberLeft = mPlayedBar.right - mScrubber.getWidth() / 2;
+ if (View.LAYOUT_DIRECTION_RTL == TextUtils.getLayoutDirectionFromLocale(
+ Locale.getDefault())) {
+ // The progress bar should be reversed in RTL.
+ mScrubberLeft = mPlayedBar.left - mScrubber.getWidth() / 2;
+ } else {
+ mScrubberLeft = mPlayedBar.right - mScrubber.getWidth() / 2;
+ }
}
+ // update text bounds when layout changed or time changed
+ updateBounds();
+ mInfoExt.updateVisibleText(this, mProgressBar, mTimeBounds);
invalidate();
}
@@ -130,14 +176,16 @@ public class TimeBar extends View {
* @return the preferred height of this view, including invisible padding
*/
public int getPreferredHeight() {
- return mTimeBounds.height() + mVPaddingInPx + mScrubberPadding;
+ int preferredHeight = mTimeBounds.height() + mVPaddingInPx + mScrubberPadding;
+ return mLayoutExt.getPreferredHeight(preferredHeight, mTimeBounds);
}
/**
* @return the height of the time bar, excluding invisible padding
*/
public int getBarHeight() {
- return mTimeBounds.height() + mVPaddingInPx;
+ int barHeight = mTimeBounds.height() + mVPaddingInPx;
+ return mLayoutExt.getBarHeight(barHeight, mTimeBounds);
}
public void setTime(int currentTime, int totalTime,
@@ -146,7 +194,10 @@ public class TimeBar extends View {
return;
}
mCurrentTime = currentTime;
- mTotalTime = totalTime;
+ mTotalTime = Math.abs(totalTime);
+ if (totalTime <= 0) { /// M: disable scrubbing before mediaplayer ready.
+ setScrubbing(false);
+ }
update();
}
@@ -165,9 +216,17 @@ public class TimeBar extends View {
}
private int getScrubberTime() {
- return (int) ((long) (mScrubberLeft + mScrubber.getWidth() / 2 - mProgressBar.left)
- * mTotalTime / mProgressBar.width());
- }
+ if (View.LAYOUT_DIRECTION_RTL == TextUtils
+ .getLayoutDirectionFromLocale(Locale.getDefault())) {
+ // The progress bar's scrubber time should be reversed in RTL.
+ return (int) ((long) (mProgressBar.width() - (mScrubberLeft
+ + mScrubber.getWidth() / 2 - mProgressBar.left))
+ * mTotalTime / mProgressBar.width());
+ } else {
+ return (int) ((long) (mScrubberLeft + mScrubber.getWidth() / 2 - mProgressBar.left)
+ * mTotalTime / mProgressBar.width());
+ }
+ }
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
@@ -180,7 +239,8 @@ public class TimeBar extends View {
if (mShowTimes) {
margin += mTimeBounds.width();
}
- int progressY = (h + mScrubberPadding) / 2;
+ margin = mLayoutExt.getProgressMargin(margin);
+ int progressY = (h + mScrubberPadding) / 2 + mLayoutExt.getProgressOffset(mTimeBounds);
mScrubberTop = progressY - mScrubber.getHeight() / 2 + 1;
mProgressBar.set(
getPaddingLeft() + margin, progressY,
@@ -191,8 +251,10 @@ public class TimeBar extends View {
@Override
protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
// draw progress bars
canvas.drawRect(mProgressBar, mProgressPaint);
+ mSecondaryProgressExt.draw(canvas, mProgressBar);
canvas.drawRect(mPlayedBar, mPlayedPaint);
// draw scrubber and timers
@@ -200,22 +262,44 @@ public class TimeBar extends View {
canvas.drawBitmap(mScrubber, mScrubberLeft, mScrubberTop, null);
}
if (mShowTimes) {
- canvas.drawText(
- stringForTime(mCurrentTime),
- mTimeBounds.width() / 2 + getPaddingLeft(),
- mTimeBounds.height() + mVPaddingInPx / 2 + mScrubberPadding + 1,
- mTimeTextPaint);
- canvas.drawText(
- stringForTime(mTotalTime),
- getWidth() - getPaddingRight() - mTimeBounds.width() / 2,
- mTimeBounds.height() + mVPaddingInPx / 2 + mScrubberPadding + 1,
- mTimeTextPaint);
+ if (View.LAYOUT_DIRECTION_RTL == TextUtils
+ .getLayoutDirectionFromLocale(Locale.getDefault())) {
+ // The progress bar's time should be reversed in RTL.
+ canvas.drawText(
+ stringForTime(mCurrentTime),
+ getWidth() - getPaddingRight() - mTimeBounds.width() / 2,
+ mTimeBounds.height() + mVPaddingInPx / 2 + mScrubberPadding + 1,
+ mTimeTextPaint);
+ canvas.drawText(
+ stringForTime(mTotalTime),
+ mTimeBounds.width() / 2 + getPaddingLeft(),
+ mTimeBounds.height() + mVPaddingInPx / 2 + mScrubberPadding + 1,
+ mTimeTextPaint);
+ } else {
+ canvas.drawText(
+ stringForTime(mCurrentTime),
+ mTimeBounds.width() / 2 + getPaddingLeft(),
+ mTimeBounds.height() + mVPaddingInPx / 2 + mScrubberPadding + 1,
+ mTimeTextPaint);
+ canvas.drawText(
+ stringForTime(mTotalTime),
+ getWidth() - getPaddingRight() - mTimeBounds.width() / 2,
+ mTimeBounds.height() + mVPaddingInPx / 2 + mScrubberPadding + 1,
+ mTimeTextPaint);
+ }
}
+ mInfoExt.draw(canvas, mLayoutExt.getInfoBounds(this, mTimeBounds));
}
@Override
public boolean onTouchEvent(MotionEvent event) {
- if (mShowScrubber) {
+ if (LOG) {
+ Log.v(TAG, "onTouchEvent() showScrubber=" + mShowScrubber
+ + ", enableScrubbing=" + mEnableScrubbing + ", totalTime="
+ + mTotalTime + ", scrubbing=" + mScrubbing + ", event="
+ + event);
+ }
+ if (mShowScrubber && mEnableScrubbing) {
int x = (int) event.getX();
int y = (int) event.getY();
@@ -233,15 +317,19 @@ public class TimeBar extends View {
clampScrubber();
mCurrentTime = getScrubberTime();
mListener.onScrubbingMove(mCurrentTime);
+ update();
invalidate();
return true;
}
case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP: {
- mListener.onScrubbingEnd(getScrubberTime(), 0, 0);
- mScrubbing = false;
- return true;
- }
+ case MotionEvent.ACTION_UP:
+ if (mScrubbing) {
+ mListener.onScrubbingEnd(getScrubberTime(), 0, 0);
+ mScrubbing = false;
+ update();
+ return true;
+ }
+ break;
}
}
return false;
@@ -263,4 +351,235 @@ public class TimeBar extends View {
mShowScrubber = canSeek;
}
+ private void updateBounds() {
+ int showTime = mTotalTime > mCurrentTime ? mTotalTime : mCurrentTime;
+ if (mLastShowTime == showTime) {
+ // do not need to recompute the bounds.
+ return;
+ }
+ String durationText = stringForTime(showTime);
+ int length = durationText.length();
+ mTimeTextPaint.getTextBounds(durationText, 0, length, mTimeBounds);
+ mLastShowTime = showTime;
+ if (LOG) {
+ Log.v(TAG, "updateBounds() durationText=" + durationText + ", timeBounds="
+ + mTimeBounds);
+ }
+ }
+
+ public void setScrubbing(boolean enable) {
+ if (LOG) {
+ Log.v(TAG, "setScrubbing(" + enable + ") scrubbing=" + mScrubbing);
+ }
+ mEnableScrubbing = enable;
+ if (mScrubbing) { // if it is scrubbing, change it to false
+ mListener.onScrubbingEnd(getScrubberTime(), 0, 0);
+ mScrubbing = false;
+ }
+ }
+
+ public boolean getScrubbing() {
+ if (LOG) {
+ Log.v(TAG, "mEnableScrubbing=" + mEnableScrubbing);
+ }
+ return mEnableScrubbing;
+ }
+
+ public void setInfo(String info) {
+ if (LOG) {
+ Log.v(TAG, "setInfo(" + info + ")");
+ }
+ mInfoExt.setInfo(info);
+ mInfoExt.updateVisibleText(this, mProgressBar, mTimeBounds);
+ invalidate();
+ }
+
+ public void setSecondaryProgress(int percent) {
+ if (LOG) {
+ Log.v(TAG, "setSecondaryProgress(" + percent + ")");
+ }
+ mSecondaryProgressExt.setSecondaryProgress(mProgressBar, percent);
+ invalidate();
+ }
+}
+
+interface ITimeBarInfoExt {
+ void init(float textSizeInPx);
+
+ void setInfo(String info);
+
+ void draw(Canvas canvas, Rect infoBounds);
+
+ void updateVisibleText(View parent, Rect progressBar, Rect timeBounds);
+}
+
+interface ITimeBarSecondaryProgressExt {
+ void init();
+
+ void setSecondaryProgress(Rect progressBar, int percent);
+
+ void draw(Canvas canvas, Rect progressBounds);
+}
+
+interface ITimeBarLayoutExt {
+ void init(int scrubberPadding, int vPaddingInPx);
+
+ int getPreferredHeight(int originalPreferredHeight, Rect timeBounds);
+
+ int getBarHeight(int originalBarHeight, Rect timeBounds);
+
+ int getProgressMargin(int originalMargin);
+
+ int getProgressOffset(Rect timeBounds);
+
+ int getTimeOffset();
+
+ Rect getInfoBounds(View parent, Rect timeBounds);
+}
+
+class TimeBarInfoExtImpl implements ITimeBarInfoExt {
+ private static final String TAG = "TimeBarInfoExtensionImpl";
+ private static final boolean LOG = false;
+ private static final String ELLIPSE = "...";
+
+ private Paint mInfoPaint;
+ private Rect mInfoBounds;
+ private String mInfoText;
+ private String mVisibleText;
+ private int mEllipseLength;
+
+ @Override
+ public void init(float textSizeInPx) {
+ mInfoPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mInfoPaint.setColor(0xFFCECECE);
+ mInfoPaint.setTextSize(textSizeInPx);
+ mInfoPaint.setTextAlign(Paint.Align.CENTER);
+
+ mEllipseLength = (int) Math.ceil(mInfoPaint.measureText(ELLIPSE));
+ }
+
+ @Override
+ public void draw(Canvas canvas, Rect infoBounds) {
+ if (mInfoText != null && mVisibleText != null) {
+ canvas.drawText(mVisibleText, infoBounds.centerX(), infoBounds.centerY(), mInfoPaint);
+ }
+ }
+
+ @Override
+ public void setInfo(String info) {
+ mInfoText = info;
+ }
+
+ public void updateVisibleText(View parent, Rect progressBar, Rect timeBounds) {
+ if (mInfoText == null) {
+ mVisibleText = null;
+ return;
+ }
+ float tw = mInfoPaint.measureText(mInfoText);
+ float space = progressBar.width() - timeBounds.width() * 2 - parent.getPaddingLeft()
+ - parent.getPaddingRight();
+ if (tw > 0 && space > 0 && tw > space) {
+ // we need to cut the info text for visible
+ float originalNum = mInfoText.length();
+ int realNum = (int) ((space - mEllipseLength) * originalNum / tw);
+ if (LOG) {
+ Log.v(TAG, "updateVisibleText() infoText=" + mInfoText + " text width=" + tw
+ + ", space=" + space + ", originalNum=" + originalNum + ", realNum="
+ + realNum
+ + ", getPaddingLeft()=" + parent.getPaddingLeft() + ", getPaddingRight()="
+ + parent.getPaddingRight()
+ + ", progressBar=" + progressBar + ", timeBounds=" + timeBounds);
+ }
+ mVisibleText = mInfoText.substring(0, realNum) + ELLIPSE;
+ } else {
+ mVisibleText = mInfoText;
+ }
+ if (LOG) {
+ Log.v(TAG, "updateVisibleText() infoText=" + mInfoText + ", visibleText="
+ + mVisibleText
+ + ", text width=" + tw + ", space=" + space);
+ }
+ }
+}
+
+class TimeBarSecondaryProgressExtImpl implements ITimeBarSecondaryProgressExt {
+ private static final String TAG = "TimeBarSecondaryProgressExtensionImpl";
+ private static final boolean LOG = false;
+
+ private int mBufferPercent;
+ private Rect mSecondaryBar;
+ private Paint mSecondaryPaint;
+
+ @Override
+ public void init() {
+ mSecondaryBar = new Rect();
+ mSecondaryPaint = new Paint();
+ mSecondaryPaint.setColor(0xFF5CA0C5);
+ }
+
+ @Override
+ public void draw(Canvas canvas, Rect progressBounds) {
+ if (mBufferPercent >= 0) {
+ mSecondaryBar.set(progressBounds);
+ mSecondaryBar.right = mSecondaryBar.left
+ + (int) (mBufferPercent * progressBounds.width() / 100);
+ canvas.drawRect(mSecondaryBar, mSecondaryPaint);
+ }
+ if (LOG) {
+ Log.v(TAG, "draw() bufferPercent=" + mBufferPercent + ", secondaryBar="
+ + mSecondaryBar);
+ }
+ }
+
+ @Override
+ public void setSecondaryProgress(Rect progressBar, int percent) {
+ mBufferPercent = percent;
+ }
+}
+
+class TimeBarLayoutExtImpl implements ITimeBarLayoutExt {
+ private static final String TAG = "TimeBarLayoutExtensionImpl";
+ private static final boolean LOG = false;
+
+ private int mTextPadding;
+ private int mVPaddingInPx;
+
+ @Override
+ public void init(int scrubberPadding, int vPaddingInPx) {
+ mTextPadding = scrubberPadding / 2;
+ mVPaddingInPx = vPaddingInPx;
+ }
+
+ @Override
+ public int getPreferredHeight(int originalPreferredHeight, Rect timeBounds) {
+ return originalPreferredHeight + timeBounds.height() + mTextPadding;
+ }
+
+ @Override
+ public int getBarHeight(int originalBarHeight, Rect timeBounds) {
+ return originalBarHeight + timeBounds.height() + mTextPadding;
+ }
+
+ @Override
+ public int getProgressMargin(int originalMargin) {
+ return 0;
+ }
+
+ @Override
+ public int getProgressOffset(Rect timeBounds) {
+ return (timeBounds.height() + mTextPadding) / 2;
+ }
+
+ @Override
+ public int getTimeOffset() {
+ return mTextPadding - mVPaddingInPx / 2;
+ }
+
+ @Override
+ public Rect getInfoBounds(View parent, Rect timeBounds) {
+ Rect bounds = new Rect(parent.getPaddingLeft(), 0,
+ parent.getWidth() - parent.getPaddingRight(),
+ (timeBounds.height() + mTextPadding * 3 + 1) * 2);
+ return bounds;
+ }
}