diff options
Diffstat (limited to 'src/com/android/gallery3d/app/TimeBar.java')
-rw-r--r-- | src/com/android/gallery3d/app/TimeBar.java | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/app/TimeBar.java b/src/com/android/gallery3d/app/TimeBar.java new file mode 100644 index 000000000..246346a56 --- /dev/null +++ b/src/com/android/gallery3d/app/TimeBar.java @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.app; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.util.DisplayMetrics; +import android.view.MotionEvent; +import android.view.View; + +import com.android.gallery3d.R; +import com.android.gallery3d.common.Utils; + +/** + * The time bar view, which includes the current and total time, the progress + * bar, and the scrubber. + */ +public class TimeBar extends View { + + public interface Listener { + void onScrubbingStart(); + + void onScrubbingMove(int time); + + void onScrubbingEnd(int time, int start, int end); + } + + // Padding around the scrubber to increase its touch target + private static final int SCRUBBER_PADDING_IN_DP = 10; + + // The total padding, top plus bottom + private static final int V_PADDING_IN_DP = 30; + + private static final int TEXT_SIZE_IN_DP = 14; + + protected final Listener mListener; + + // the bars we use for displaying the progress + protected final Rect mProgressBar; + protected final Rect mPlayedBar; + + protected final Paint mProgressPaint; + protected final Paint mPlayedPaint; + protected final Paint mTimeTextPaint; + + protected final Bitmap mScrubber; + protected int mScrubberPadding; // adds some touch tolerance around the + // scrubber + + protected int mScrubberLeft; + protected int mScrubberTop; + protected int mScrubberCorrection; + protected boolean mScrubbing; + protected boolean mShowTimes; + protected boolean mShowScrubber; + + protected int mTotalTime; + protected int mCurrentTime; + + protected final Rect mTimeBounds; + + protected int mVPaddingInPx; + + public TimeBar(Context context, Listener listener) { + super(context); + mListener = Utils.checkNotNull(listener); + + mShowTimes = true; + mShowScrubber = true; + + mProgressBar = new Rect(); + mPlayedBar = new Rect(); + + mProgressPaint = new Paint(); + mProgressPaint.setColor(0xFF808080); + mPlayedPaint = new Paint(); + mPlayedPaint.setColor(0xFFFFFFFF); + + DisplayMetrics metrics = context.getResources().getDisplayMetrics(); + float textSizeInPx = metrics.density * TEXT_SIZE_IN_DP; + mTimeTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mTimeTextPaint.setColor(0xFFCECECE); + mTimeTextPaint.setTextSize(textSizeInPx); + mTimeTextPaint.setTextAlign(Paint.Align.CENTER); + + mTimeBounds = new Rect(); + mTimeTextPaint.getTextBounds("0:00:00", 0, 7, mTimeBounds); + + mScrubber = BitmapFactory.decodeResource(getResources(), R.drawable.scrubber_knob); + mScrubberPadding = (int) (metrics.density * SCRUBBER_PADDING_IN_DP); + + mVPaddingInPx = (int) (metrics.density * V_PADDING_IN_DP); + } + + private void update() { + mPlayedBar.set(mProgressBar); + + if (mTotalTime > 0) { + mPlayedBar.right = + mPlayedBar.left + (int) ((mProgressBar.width() * (long) mCurrentTime) / mTotalTime); + } else { + mPlayedBar.right = mProgressBar.left; + } + + if (!mScrubbing) { + mScrubberLeft = mPlayedBar.right - mScrubber.getWidth() / 2; + } + invalidate(); + } + + /** + * @return the preferred height of this view, including invisible padding + */ + public int getPreferredHeight() { + return mTimeBounds.height() + mVPaddingInPx + mScrubberPadding; + } + + /** + * @return the height of the time bar, excluding invisible padding + */ + public int getBarHeight() { + return mTimeBounds.height() + mVPaddingInPx; + } + + public void setTime(int currentTime, int totalTime, + int trimStartTime, int trimEndTime) { + if (mCurrentTime == currentTime && mTotalTime == totalTime) { + return; + } + mCurrentTime = currentTime; + mTotalTime = totalTime; + update(); + } + + private boolean inScrubber(float x, float y) { + int scrubberRight = mScrubberLeft + mScrubber.getWidth(); + int scrubberBottom = mScrubberTop + mScrubber.getHeight(); + return mScrubberLeft - mScrubberPadding < x && x < scrubberRight + mScrubberPadding + && mScrubberTop - mScrubberPadding < y && y < scrubberBottom + mScrubberPadding; + } + + private void clampScrubber() { + int half = mScrubber.getWidth() / 2; + int max = mProgressBar.right - half; + int min = mProgressBar.left - half; + mScrubberLeft = Math.min(max, Math.max(min, mScrubberLeft)); + } + + private int getScrubberTime() { + 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) { + int w = r - l; + int h = b - t; + if (!mShowTimes && !mShowScrubber) { + mProgressBar.set(0, 0, w, h); + } else { + int margin = mScrubber.getWidth() / 3; + if (mShowTimes) { + margin += mTimeBounds.width(); + } + int progressY = (h + mScrubberPadding) / 2; + mScrubberTop = progressY - mScrubber.getHeight() / 2 + 1; + mProgressBar.set( + getPaddingLeft() + margin, progressY, + w - getPaddingRight() - margin, progressY + 4); + } + update(); + } + + @Override + protected void onDraw(Canvas canvas) { + // draw progress bars + canvas.drawRect(mProgressBar, mProgressPaint); + canvas.drawRect(mPlayedBar, mPlayedPaint); + + // draw scrubber and timers + if (mShowScrubber) { + 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); + } + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (mShowScrubber) { + int x = (int) event.getX(); + int y = (int) event.getY(); + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: { + mScrubberCorrection = inScrubber(x, y) + ? x - mScrubberLeft + : mScrubber.getWidth() / 2; + mScrubbing = true; + mListener.onScrubbingStart(); + } + // fall-through + case MotionEvent.ACTION_MOVE: { + mScrubberLeft = x - mScrubberCorrection; + clampScrubber(); + mCurrentTime = getScrubberTime(); + mListener.onScrubbingMove(mCurrentTime); + invalidate(); + return true; + } + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: { + mListener.onScrubbingEnd(getScrubberTime(), 0, 0); + mScrubbing = false; + return true; + } + } + } + return false; + } + + protected String stringForTime(long millis) { + int totalSeconds = (int) millis / 1000; + int seconds = totalSeconds % 60; + int minutes = (totalSeconds / 60) % 60; + int hours = totalSeconds / 3600; + if (hours > 0) { + return String.format("%d:%02d:%02d", hours, minutes, seconds).toString(); + } else { + return String.format("%02d:%02d", minutes, seconds).toString(); + } + } + + public void setSeekable(boolean canSeek) { + mShowScrubber = canSeek; + } + +} |