summaryrefslogtreecommitdiffstats
path: root/src/com/android/gallery3d/app/CommonControllerOverlay.java
diff options
context:
space:
mode:
authorTeng-Hui Zhu <ztenghui@google.com>2012-08-24 14:50:37 -0700
committerTeng-Hui Zhu <ztenghui@google.com>2012-09-11 10:36:05 -0700
commit25930913dc7129a1e6d07a88f9b79d69029d2535 (patch)
treed8d5efe785696d0ffd4b894c5f1113fc529d0680 /src/com/android/gallery3d/app/CommonControllerOverlay.java
parent1a980d945c8715de18bdbe6406599503d812185f (diff)
downloadandroid_packages_apps_Snap-25930913dc7129a1e6d07a88f9b79d69029d2535.tar.gz
android_packages_apps_Snap-25930913dc7129a1e6d07a88f9b79d69029d2535.tar.bz2
android_packages_apps_Snap-25930913dc7129a1e6d07a88f9b79d69029d2535.zip
Add the UI elements for video trim activity.
1. Refactored the classes to support both the video play and trim. Now the common code for controller overlay is in CommonControllerOverlay, which is basically the same as the original MovieControllerOverlay without animation. Because in trimming, we don't want to hide all the controller. The specific animations are implemented in the sub-classes which are TrimControllerOverlay and MovieControllerOverlay. At the same time, TrimTimeBar extended TimeBar to support the extra trimming start scrubber and end scrubber. The interface between the timebar and the controllerOverlay are kept almost the same way, except adding the trimming info when necessary. With all these, the activity of TrimVideo now relied on the TrimTimeBar and TrimControllerOverlay. Similarily, the MovieActivity relied on the TimeBar and MovieControllerOverlay. 2. Hook the TrimVideo activity with the trim menu. Note that the icons are temporary for now, still need UX input on that. bug:7093055 Change-Id: Ib9bfbc090106744a569fce4c451ddffc0a2c699b
Diffstat (limited to 'src/com/android/gallery3d/app/CommonControllerOverlay.java')
-rw-r--r--src/com/android/gallery3d/app/CommonControllerOverlay.java333
1 files changed, 333 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/app/CommonControllerOverlay.java b/src/com/android/gallery3d/app/CommonControllerOverlay.java
new file mode 100644
index 000000000..ab43dada5
--- /dev/null
+++ b/src/com/android/gallery3d/app/CommonControllerOverlay.java
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2012 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.Rect;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.android.gallery3d.R;
+
+/**
+ * The common playback controller for the Movie Player or Video Trimming.
+ */
+public abstract class CommonControllerOverlay extends FrameLayout implements
+ ControllerOverlay,
+ OnClickListener,
+ TimeBar.Listener {
+
+ protected enum State {
+ PLAYING,
+ PAUSED,
+ ENDED,
+ ERROR,
+ LOADING
+ }
+
+ private static final float ERROR_MESSAGE_RELATIVE_PADDING = 1.0f / 6;
+
+ protected Listener mListener;
+
+ protected final View mBackground;
+ protected TimeBar mTimeBar;
+
+ protected View mMainView;
+ protected final LinearLayout mLoadingView;
+ protected final TextView mErrorView;
+ protected final ImageView mPlayPauseReplayView;
+
+ protected State mState;
+
+ protected boolean mCanReplay = true;
+
+ public CommonControllerOverlay(Context context) {
+ super(context);
+
+ mState = State.LOADING;
+ // TODO: Move the following layout code into xml file.
+ LayoutParams wrapContent =
+ new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+ LayoutParams matchParent =
+ new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+
+ mBackground = new View(context);
+ mBackground.setBackgroundColor(context.getResources().getColor(R.color.darker_transparent));
+ addView(mBackground, matchParent);
+
+ // Depending on the usage, the timeBar can show a single scrubber, or
+ // multiple ones for trimming.
+ createTimeBar(context);
+ addView(mTimeBar, wrapContent);
+
+ mLoadingView = new LinearLayout(context);
+ mLoadingView.setOrientation(LinearLayout.VERTICAL);
+ mLoadingView.setGravity(Gravity.CENTER_HORIZONTAL);
+ ProgressBar spinner = new ProgressBar(context);
+ spinner.setIndeterminate(true);
+ mLoadingView.addView(spinner, wrapContent);
+ TextView loadingText = createOverlayTextView(context);
+ loadingText.setText(R.string.loading_video);
+ mLoadingView.addView(loadingText, wrapContent);
+ addView(mLoadingView, wrapContent);
+
+ mPlayPauseReplayView = new ImageView(context);
+ mPlayPauseReplayView.setImageResource(R.drawable.ic_vidcontrol_play);
+ mPlayPauseReplayView.setBackgroundResource(R.drawable.bg_vidcontrol);
+ mPlayPauseReplayView.setScaleType(ScaleType.CENTER);
+ mPlayPauseReplayView.setFocusable(true);
+ mPlayPauseReplayView.setClickable(true);
+ mPlayPauseReplayView.setOnClickListener(this);
+ addView(mPlayPauseReplayView, wrapContent);
+
+ mErrorView = createOverlayTextView(context);
+ addView(mErrorView, matchParent);
+
+ RelativeLayout.LayoutParams params =
+ new RelativeLayout.LayoutParams(
+ LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+ setLayoutParams(params);
+ hide();
+ }
+
+ abstract protected void createTimeBar(Context context);
+
+ private TextView createOverlayTextView(Context context) {
+ TextView view = new TextView(context);
+ view.setGravity(Gravity.CENTER);
+ view.setTextColor(0xFFFFFFFF);
+ view.setPadding(0, 15, 0, 15);
+ return view;
+ }
+
+ @Override
+ public void setListener(Listener listener) {
+ this.mListener = listener;
+ }
+
+ @Override
+ public void setCanReplay(boolean canReplay) {
+ this.mCanReplay = canReplay;
+ }
+
+ @Override
+ public View getView() {
+ return this;
+ }
+
+ @Override
+ public void showPlaying() {
+ mState = State.PLAYING;
+ showMainView(mPlayPauseReplayView);
+ }
+
+ @Override
+ public void showPaused() {
+ mState = State.PAUSED;
+ showMainView(mPlayPauseReplayView);
+ }
+
+ @Override
+ public void showEnded() {
+ mState = State.ENDED;
+ showMainView(mPlayPauseReplayView);
+ }
+
+ @Override
+ public void showLoading() {
+ mState = State.LOADING;
+ showMainView(mLoadingView);
+ }
+
+ @Override
+ public void showErrorMessage(String message) {
+ mState = State.ERROR;
+ int padding = (int) (getMeasuredWidth() * ERROR_MESSAGE_RELATIVE_PADDING);
+ mErrorView.setPadding(
+ padding, mErrorView.getPaddingTop(), padding, mErrorView.getPaddingBottom());
+ mErrorView.setText(message);
+ showMainView(mErrorView);
+ }
+
+ @Override
+ public void setTimes(int currentTime, int totalTime,
+ int trimStartTime, int trimEndTime) {
+ mTimeBar.setTime(currentTime, totalTime, trimStartTime, trimEndTime);
+ }
+
+ public void hide() {
+ mPlayPauseReplayView.setVisibility(View.INVISIBLE);
+ mLoadingView.setVisibility(View.INVISIBLE);
+ mBackground.setVisibility(View.INVISIBLE);
+ mTimeBar.setVisibility(View.INVISIBLE);
+ setVisibility(View.INVISIBLE);
+ setFocusable(true);
+ requestFocus();
+ }
+
+ private void showMainView(View view) {
+ mMainView = view;
+ mErrorView.setVisibility(mMainView == mErrorView ? View.VISIBLE : View.INVISIBLE);
+ mLoadingView.setVisibility(mMainView == mLoadingView ? View.VISIBLE : View.INVISIBLE);
+ mPlayPauseReplayView.setVisibility(
+ mMainView == mPlayPauseReplayView ? View.VISIBLE : View.INVISIBLE);
+ show();
+ }
+
+ @Override
+ public void show() {
+ updateViews();
+ setVisibility(View.VISIBLE);
+ setFocusable(false);
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (mListener != null) {
+ if (view == mPlayPauseReplayView) {
+ if (mState == State.ENDED) {
+ if (mCanReplay) {
+ mListener.onReplay();
+ }
+ } else if (mState == State.PAUSED || mState == State.PLAYING) {
+ mListener.onPlayPause();
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ return super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (super.onTouchEvent(event)) {
+ return true;
+ }
+ return false;
+ }
+
+ // The paddings of 4 sides which covered by system components. E.g.
+ // +-----------------+\
+ // | Action Bar | insets.top
+ // +-----------------+/
+ // | |
+ // | Content Area | insets.right = insets.left = 0
+ // | |
+ // +-----------------+\
+ // | Navigation Bar | insets.bottom
+ // +-----------------+/
+ // Please see View.fitSystemWindows() for more details.
+ private final Rect mWindowInsets = new Rect();
+
+ @Override
+ protected boolean fitSystemWindows(Rect insets) {
+ // We don't set the paddings of this View, otherwise,
+ // the content will get cropped outside window
+ mWindowInsets.set(insets);
+ return true;
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ Rect insets = mWindowInsets;
+ int pl = insets.left; // the left paddings
+ int pr = insets.right;
+ int pt = insets.top;
+ int pb = insets.bottom;
+
+ int h = bottom - top;
+ int w = right - left;
+ boolean error = mErrorView.getVisibility() == View.VISIBLE;
+
+ int y = h - pb;
+ // Put both TimeBar and Background just above the bottom system
+ // component.
+ // But extend the background to the width of the screen, since we don't
+ // care if it will be covered by a system component and it looks better.
+ mBackground.layout(0, y - mTimeBar.getBarHeight(), w, y);
+ mTimeBar.layout(pl, y - mTimeBar.getPreferredHeight(), w - pr, y);
+
+ // Needed, otherwise the framework will not re-layout in case only the
+ // padding is changed
+ mTimeBar.requestLayout();
+
+ // Put the play/pause/next/ previous button in the center of the screen
+ layoutCenteredView(mPlayPauseReplayView, 0, 0, w, h);
+
+ if (mMainView != null) {
+ layoutCenteredView(mMainView, 0, 0, w, h);
+ }
+ }
+
+ private void layoutCenteredView(View view, int l, int t, int r, int b) {
+ int cw = view.getMeasuredWidth();
+ int ch = view.getMeasuredHeight();
+ int cl = (r - l - cw) / 2;
+ int ct = (b - t - ch) / 2;
+ view.layout(cl, ct, cl + cw, ct + ch);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ measureChildren(widthMeasureSpec, heightMeasureSpec);
+ }
+
+ protected void updateViews() {
+ mBackground.setVisibility(View.VISIBLE);
+ mTimeBar.setVisibility(View.VISIBLE);
+ mPlayPauseReplayView.setImageResource(
+ mState == State.PAUSED ? R.drawable.ic_vidcontrol_play :
+ mState == State.PLAYING ? R.drawable.ic_vidcontrol_pause :
+ R.drawable.ic_vidcontrol_reload);
+ mPlayPauseReplayView.setVisibility(
+ (mState != State.LOADING && mState != State.ERROR &&
+ !(mState == State.ENDED && !mCanReplay))
+ ? View.VISIBLE : View.GONE);
+ requestLayout();
+ }
+
+ // TimeBar listener
+
+ @Override
+ public void onScrubbingStart() {
+ mListener.onSeekStart();
+ }
+
+ @Override
+ public void onScrubbingMove(int time) {
+ mListener.onSeekMove(time);
+ }
+
+ @Override
+ public void onScrubbingEnd(int time, int trimStartTime, int trimEndTime) {
+ mListener.onSeekEnd(time, trimStartTime, trimEndTime);
+ }
+}