summaryrefslogtreecommitdiffstats
path: root/src/com/android/gallery3d/app/MovieControllerOverlay.java
diff options
context:
space:
mode:
authorChih-Chung Chang <chihchung@google.com>2011-10-14 16:09:09 +0800
committerChih-Chung Chang <chihchung@google.com>2011-10-18 12:11:13 +0800
commit6645e87b4889a96cc977cc3b35ed9d43b33de328 (patch)
treebfd87f07430c0f448ba5c487f9ef707dab8667ec /src/com/android/gallery3d/app/MovieControllerOverlay.java
parent903bb336e915b6c7ce560dd8a2c2722ae5fa3bf5 (diff)
downloadandroid_packages_apps_Snap-6645e87b4889a96cc977cc3b35ed9d43b33de328.tar.gz
android_packages_apps_Snap-6645e87b4889a96cc977cc3b35ed9d43b33de328.tar.bz2
android_packages_apps_Snap-6645e87b4889a96cc977cc3b35ed9d43b33de328.zip
Fix 5393669: New Player Control UI.
Change-Id: I1aa310eee3b7715dbefea6b2f24e6f32481db49c
Diffstat (limited to 'src/com/android/gallery3d/app/MovieControllerOverlay.java')
-rw-r--r--src/com/android/gallery3d/app/MovieControllerOverlay.java390
1 files changed, 390 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/app/MovieControllerOverlay.java b/src/com/android/gallery3d/app/MovieControllerOverlay.java
new file mode 100644
index 000000000..752213e4b
--- /dev/null
+++ b/src/com/android/gallery3d/app/MovieControllerOverlay.java
@@ -0,0 +1,390 @@
+/*
+ * 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 com.android.gallery3d.common.Utils;
+import com.android.gallery3d.R;
+
+import android.content.Context;
+import android.os.Handler;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.animation.Animation;
+import android.view.animation.Animation.AnimationListener;
+import android.view.animation.AnimationUtils;
+import android.widget.FrameLayout;
+import android.widget.ImageButton;
+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;
+
+/**
+ * The playback controller for the Movie Player.
+ */
+public class MovieControllerOverlay extends FrameLayout implements
+ ControllerOverlay,
+ OnClickListener,
+ AnimationListener,
+ TimeBar.Listener {
+
+ private enum State {
+ PLAYING,
+ PAUSED,
+ ENDED,
+ ERROR,
+ LOADING
+ }
+
+ private static final float ERROR_MESSAGE_RELATIVE_PADDING = 1.0f / 6;
+
+ private Listener listener;
+
+ private final View background;
+ private final TimeBar timeBar;
+
+ private View mainView;
+ private final LinearLayout loadingView;
+ private final TextView errorView;
+ private final ImageView playPauseReplayView;
+
+ private final Handler handler;
+ private final Runnable startHidingRunnable;
+ private final Animation hideAnimation;
+
+ private State state;
+
+ private boolean hidden;
+
+ private boolean canReplay = true;
+
+ public MovieControllerOverlay(Context context) {
+ super(context);
+
+ state = State.LOADING;
+
+ LayoutParams wrapContent =
+ new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+ LayoutParams matchParent =
+ new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+
+ LayoutInflater inflater = LayoutInflater.from(context);
+
+ background = new View(context);
+ background.setBackgroundColor(context.getResources().getColor(R.color.darker_transparent));
+ addView(background, matchParent);
+
+ timeBar = new TimeBar(context, this);
+ addView(timeBar, wrapContent);
+
+ loadingView = new LinearLayout(context);
+ loadingView.setOrientation(LinearLayout.VERTICAL);
+ loadingView.setGravity(Gravity.CENTER_HORIZONTAL);
+ ProgressBar spinner = new ProgressBar(context);
+ spinner.setIndeterminate(true);
+ loadingView.addView(spinner, wrapContent);
+ addView(loadingView, wrapContent);
+
+ playPauseReplayView = new ImageView(context);
+ playPauseReplayView.setImageResource(R.drawable.ic_vidcontrol_play);
+ playPauseReplayView.setBackgroundResource(R.drawable.bg_vidcontrol);
+ playPauseReplayView.setScaleType(ScaleType.CENTER);
+ playPauseReplayView.setFocusable(true);
+ playPauseReplayView.setClickable(true);
+ playPauseReplayView.setOnClickListener(this);
+ addView(playPauseReplayView, wrapContent);
+
+ errorView = new TextView(context);
+ errorView.setGravity(Gravity.CENTER);
+ errorView.setBackgroundColor(0xCC000000);
+ errorView.setTextColor(0xFFFFFFFF);
+ addView(errorView, matchParent);
+
+ handler = new Handler();
+ startHidingRunnable = new Runnable() {
+ public void run() {
+ startHiding();
+ }
+ };
+
+ hideAnimation = AnimationUtils.loadAnimation(context, R.anim.player_out);
+ hideAnimation.setAnimationListener(this);
+
+ RelativeLayout.LayoutParams params =
+ new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+ setLayoutParams(params);
+ hide();
+ }
+
+ public void setListener(Listener listener) {
+ this.listener = listener;
+ }
+
+ public void setCanReplay(boolean canReplay) {
+ this.canReplay = canReplay;
+ }
+
+ public View getView() {
+ return this;
+ }
+
+ public void showPlaying() {
+ state = State.PLAYING;
+ showMainView(playPauseReplayView);
+ }
+
+ public void showPaused() {
+ state = State.PAUSED;
+ showMainView(playPauseReplayView);
+ }
+
+ public void showEnded() {
+ state = State.ENDED;
+ showMainView(playPauseReplayView);
+ }
+
+ public void showLoading() {
+ state = State.LOADING;
+ showMainView(loadingView);
+ }
+
+ public void showErrorMessage(String message) {
+ state = State.ERROR;
+ int padding = (int) (getMeasuredWidth() * ERROR_MESSAGE_RELATIVE_PADDING);
+ errorView.setPadding(padding, 10, padding, 10);
+ errorView.setText(message);
+ showMainView(errorView);
+ }
+
+ public void resetTime() {
+ timeBar.resetTime();
+ }
+
+ public void setTimes(int currentTime, int totalTime) {
+ timeBar.setTime(currentTime, totalTime);
+ }
+
+ public void hide() {
+ boolean wasHidden = hidden;
+ hidden = true;
+ playPauseReplayView.setVisibility(View.INVISIBLE);
+ loadingView.setVisibility(View.INVISIBLE);
+ background.setVisibility(View.INVISIBLE);
+ timeBar.setVisibility(View.INVISIBLE);
+ setVisibility(View.INVISIBLE);
+ setFocusable(true);
+ requestFocus();
+ if (listener != null && wasHidden != hidden) {
+ listener.onHidden();
+ }
+ }
+
+ private void showMainView(View view) {
+ mainView = view;
+ errorView.setVisibility(mainView == errorView ? View.VISIBLE : View.INVISIBLE);
+ loadingView.setVisibility(mainView == loadingView ? View.VISIBLE : View.INVISIBLE);
+ playPauseReplayView.setVisibility(
+ mainView == playPauseReplayView ? View.VISIBLE : View.INVISIBLE);
+ show();
+ }
+
+ public void show() {
+ boolean wasHidden = hidden;
+ hidden = false;
+ updateViews();
+ setVisibility(View.VISIBLE);
+ setFocusable(false);
+ if (listener != null && wasHidden != hidden) {
+ listener.onShown();
+ }
+ maybeStartHiding();
+ }
+
+ private void maybeStartHiding() {
+ cancelHiding();
+ if (state == State.PLAYING) {
+ handler.postDelayed(startHidingRunnable, 2500);
+ }
+ }
+
+ private void startHiding() {
+ startHideAnimation(timeBar);
+ startHideAnimation(playPauseReplayView);
+ }
+
+ private void startHideAnimation(View view) {
+ if (view.getVisibility() == View.VISIBLE) {
+ view.startAnimation(hideAnimation);
+ }
+ }
+
+ private void cancelHiding() {
+ handler.removeCallbacks(startHidingRunnable);
+ background.setAnimation(null);
+ timeBar.setAnimation(null);
+ playPauseReplayView.setAnimation(null);
+ }
+
+ public void onAnimationStart(Animation animation) {
+ // Do nothing.
+ }
+
+ public void onAnimationRepeat(Animation animation) {
+ // Do nothing.
+ }
+
+ public void onAnimationEnd(Animation animation) {
+ hide();
+ }
+
+ public void onClick(View view) {
+ if (listener != null) {
+ if (view == playPauseReplayView) {
+ if (state == State.ENDED) {
+ if (canReplay) {
+ listener.onReplay();
+ }
+ } else if (state == State.PAUSED || state == State.PLAYING) {
+ listener.onPlayPause();
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (hidden) {
+ show();
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (super.onTouchEvent(event)) {
+ return true;
+ }
+
+ if (hidden) {
+ show();
+ return true;
+ }
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ cancelHiding();
+ if (state == State.PLAYING || state == State.PAUSED) {
+ listener.onPlayPause();
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ maybeStartHiding();
+ break;
+ }
+ return true;
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ int bw;
+ int bh;
+ int y;
+ int h = b - t;
+ int w = r - l;
+ boolean error = errorView.getVisibility() == View.VISIBLE;
+
+ bw = timeBar.getBarHeight();
+ bh = bw;
+ y = b - bh;
+
+ background.layout(l, y, r, b);
+
+ timeBar.layout(l, b - timeBar.getPreferredHeight(), r, b);
+ // Needed, otherwise the framework will not re-layout in case only the padding is changed
+ timeBar.requestLayout();
+
+ // play pause / next / previous buttons
+ int cx = l + w / 2; // center x
+ int playbackButtonsCenterline = t + h / 2;
+ bw = playPauseReplayView.getMeasuredWidth();
+ bh = playPauseReplayView.getMeasuredHeight();
+ playPauseReplayView.layout(
+ cx - bw / 2, playbackButtonsCenterline - bh / 2, cx + bw / 2,
+ playbackButtonsCenterline + bh / 2);
+
+ // Space available on each side of the error message for the next and previous buttons
+ int errorMessagePadding = (int) (w * ERROR_MESSAGE_RELATIVE_PADDING);
+
+ if (mainView != null) {
+ layoutCenteredView(mainView, l, t, r, b);
+ }
+ }
+
+ 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);
+ }
+
+ private void updateViews() {
+ if (hidden) {
+ return;
+ }
+ background.setVisibility(View.VISIBLE);
+ timeBar.setVisibility(View.VISIBLE);
+ playPauseReplayView.setImageResource(
+ state == State.PAUSED ? R.drawable.ic_vidcontrol_play :
+ state == State.PLAYING ? R.drawable.ic_vidcontrol_pause :
+ R.drawable.ic_vidcontrol_reload);
+ playPauseReplayView.setVisibility(
+ (state != State.LOADING && state != State.ERROR &&
+ !(state == State.ENDED && !canReplay))
+ ? View.VISIBLE : View.GONE);
+ requestLayout();
+ }
+
+ // TimeBar listener
+
+ public void onScrubbingStart() {
+ cancelHiding();
+ listener.onSeekStart();
+ }
+
+ public void onScrubbingMove(int time) {
+ cancelHiding();
+ listener.onSeekMove(time);
+ }
+
+ public void onScrubbingEnd(int time) {
+ maybeStartHiding();
+ listener.onSeekEnd(time);
+ }
+
+}