OSDN Git Service

Add bottom bar UI for photo page
authorBobby Georgescu <georgescu@google.com>
Tue, 18 Sep 2012 01:12:11 +0000 (18:12 -0700)
committerAndroid (Google) Code Review <android-gerrit@google.com>
Wed, 19 Sep 2012 23:52:51 +0000 (16:52 -0700)
Bug: 7050303
Bug: 7170148
Pulled the handling of the display of the edit (FX) button
out into a separate file and put in the groundwork for
supporting multiple buttons within a container along the
bottom of the screen and managing their display as well as
animating them in and out. Also added a button for launching
the panorama viewer when appropriate

Change-Id: Iee3083e0693ef3c1f55264b922f02b9a702d2103

res/layout/photopage_bottom_controls.xml [new file with mode: 0644]
src/com/android/gallery3d/app/PhotoPage.java
src/com/android/gallery3d/app/PhotoPageBottomControls.java [new file with mode: 0644]

diff --git a/res/layout/photopage_bottom_controls.xml b/res/layout/photopage_bottom_controls.xml
new file mode 100644 (file)
index 0000000..a8fca2d
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/photopage_bottom_controls"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentLeft="true"
+        android:orientation="horizontal"
+        android:visibility="gone">
+        <ImageButton
+                android:id="@+id/photopage_bottom_control_edit"
+                android:src="@drawable/photoeditor_artistic"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:visibility="gone"/>
+        <ImageButton
+                android:id="@+id/photopage_bottom_control_panorama"
+                android:src="@android:drawable/ic_dialog_map"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:visibility="gone"/>
+</LinearLayout>
index 0d61f2f..8e06794 100644 (file)
@@ -29,10 +29,7 @@ import android.nfc.NfcAdapter;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
-import android.view.View;
-import android.view.View.OnClickListener;
 import android.view.animation.AccelerateInterpolator;
-import android.widget.ImageView;
 import android.widget.RelativeLayout;
 import android.widget.Toast;
 
@@ -79,7 +76,8 @@ import com.android.gallery3d.util.LightCycleHelper;
 import com.android.gallery3d.util.MediaSetUtils;
 
 public class PhotoPage extends ActivityState implements
-        PhotoView.Listener, OrientationManager.Listener, AppBridge.Server {
+        PhotoView.Listener, OrientationManager.Listener, AppBridge.Server,
+        PhotoPageBottomControls.Delegate {
     private static final String TAG = "PhotoPage";
 
     private static final int MSG_HIDE_BARS = 1;
@@ -90,7 +88,7 @@ public class PhotoPage extends ActivityState implements
     private static final int MSG_UNFREEZE_GLROOT = 6;
     private static final int MSG_WANT_BARS = 7;
     private static final int MSG_REFRESH_GRID_BUTTON = 8;
-    private static final int MSG_REFRESH_EDIT_BUTTON = 9;
+    private static final int MSG_REFRESH_BOTTOM_CONTROLS = 9;
 
     private static final int HIDE_BARS_TIMEOUT = 3500;
     private static final int UNFREEZE_GLROOT_TIMEOUT = 250;
@@ -140,6 +138,7 @@ public class PhotoPage extends ActivityState implements
     private volatile boolean mActionBarAllowed = true;
     private GalleryActionBar mActionBar;
     private boolean mIsMenuVisible;
+    private PhotoPageBottomControls mBottomControls;
     private MediaItem mCurrentPhoto = null;
     private MenuExecutor mMenuExecutor;
     private boolean mIsActive;
@@ -257,8 +256,8 @@ public class PhotoPage extends ActivityState implements
                         setGridButtonVisibility(mPhotoView.getFilmMode());
                         break;
                     }
-                    case MSG_REFRESH_EDIT_BUTTON: {
-                        refreshEditButton();
+                    case MSG_REFRESH_BOTTOM_CONTROLS: {
+                        if (mBottomControls != null) mBottomControls.refresh();
                         break;
                     }
                     case MSG_LOCK_ORIENTATION: {
@@ -407,48 +406,42 @@ public class PhotoPage extends ActivityState implements
         }
 
         mPhotoView.setFilmMode(mStartInFilmstrip && mMediaSet.getMediaItemCount() > 1);
-        setupEditButton();
+        if (mSecureAlbum == null) {
+            RelativeLayout galleryRoot = (RelativeLayout) ((Activity) mActivity)
+                        .findViewById(mAppBridge != null ? R.id.content : R.id.gallery_root);
+            if (galleryRoot != null) {
+                mBottomControls = new PhotoPageBottomControls(this, mActivity, galleryRoot);
+            }
+        }
     }
 
-    private ImageView mEditButton;
-    private void setupEditButton() {
-        if (mSecureAlbum != null) return;
-        RelativeLayout galleryRoot = (RelativeLayout) ((Activity) mActivity)
-                .findViewById(mAppBridge != null ? R.id.content : R.id.gallery_root);
-        if (galleryRoot == null) return;
-
-        mEditButton = new ImageView(mActivity);
-        mEditButton.setImageResource(R.drawable.photoeditor_artistic);
-        mEditButton.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View arg0) {
-                launchPhotoEditor();
-            }
-        });
-        RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
-                RelativeLayout.LayoutParams.WRAP_CONTENT,
-                RelativeLayout.LayoutParams.WRAP_CONTENT);
-        lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
-        galleryRoot.addView(mEditButton, lp);
-        refreshEditButton();
+    public boolean canDisplayBottomControls() {
+        return mShowBars && !mPhotoView.getFilmMode();
     }
 
-    private void cleanupEditButton() {
-        if (mEditButton == null) return;
-        RelativeLayout galleryRoot = (RelativeLayout) ((Activity) mActivity)
-                .findViewById(mAppBridge != null ? R.id.content : R.id.gallery_root);
-        if (galleryRoot == null) return;
-        galleryRoot.removeView(mEditButton);
-        mEditButton = null;
+    public boolean canDisplayBottomControl(int control) {
+        if (mCurrentPhoto == null) return false;
+        switch(control) {
+            case R.id.photopage_bottom_control_edit:
+                return mCurrentPhoto.getMediaType() == MediaObject.MEDIA_TYPE_IMAGE;
+            case R.id.photopage_bottom_control_panorama:
+                return (mCurrentPhoto.getSupportedOperations()
+                        & MediaItem.SUPPORT_VIEW_PANORAMA) != 0;
+            default:
+                return false;
+        }
     }
 
-    private void refreshEditButton() {
-        if (mEditButton == null) return;
-        if (mShowBars && mCurrentPhoto != null && !mPhotoView.getFilmMode()
-                && mCurrentPhoto.getMediaType() == MediaObject.MEDIA_TYPE_IMAGE) {
-            mEditButton.setVisibility(View.VISIBLE);
-        } else {
-            mEditButton.setVisibility(View.GONE);
+    public void onBottomControlClicked(int control) {
+        switch(control) {
+            case R.id.photopage_bottom_control_edit:
+                launchPhotoEditor();
+                return;
+            case R.id.photopage_bottom_control_panorama:
+                LightCycleHelper.viewPanorama(mActivity, mCurrentPhoto.getContentUri());
+                return;
+            default:
+                return;
         }
     }
 
@@ -498,7 +491,7 @@ public class PhotoPage extends ActivityState implements
         if (mCurrentPhoto == null) return;
         updateMenuOperations();
         updateTitle();
-        refreshEditButton();
+        if (mBottomControls != null) mBottomControls.refresh();
         if (mShowDetails) {
             mDetailsHelper.reloadDetails();
         }
@@ -564,7 +557,7 @@ public class PhotoPage extends ActivityState implements
         mActionBar.show();
         mActivity.getGLRoot().setLightsOutMode(false);
         refreshHidingMessage();
-        refreshEditButton();
+        if (mBottomControls != null) mBottomControls.refresh();
     }
 
     private void hideBars() {
@@ -573,7 +566,7 @@ public class PhotoPage extends ActivityState implements
         mActionBar.hide();
         mActivity.getGLRoot().setLightsOutMode(true);
         mHandler.removeMessages(MSG_HIDE_BARS);
-        refreshEditButton();
+        if (mBottomControls != null) mBottomControls.refresh();
     }
 
     private void refreshHidingMessage() {
@@ -1087,7 +1080,7 @@ public class PhotoPage extends ActivityState implements
 
     public void onFilmModeChanged(boolean enabled) {
         mHandler.sendEmptyMessage(MSG_REFRESH_GRID_BUTTON);
-        mHandler.sendEmptyMessage(MSG_REFRESH_EDIT_BUTTON);
+        mHandler.sendEmptyMessage(MSG_REFRESH_BOTTOM_CONTROLS);
         if (enabled) {
             mHandler.removeMessages(MSG_HIDE_BARS);
         } else {
@@ -1165,7 +1158,7 @@ public class PhotoPage extends ActivityState implements
         }
         mOrientationManager.removeListener(this);
         mActivity.getGLRoot().setOrientationSource(null);
-        cleanupEditButton();
+        if (mBottomControls != null) mBottomControls.cleanup();
 
         // Remove all pending messages.
         mHandler.removeCallbacksAndMessages(null);
diff --git a/src/com/android/gallery3d/app/PhotoPageBottomControls.java b/src/com/android/gallery3d/app/PhotoPageBottomControls.java
new file mode 100644 (file)
index 0000000..8ba4818
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * 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.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+import android.view.animation.ScaleAnimation;
+import android.widget.RelativeLayout;
+
+import com.android.gallery3d.R;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class PhotoPageBottomControls implements OnClickListener {
+    public interface Delegate {
+        public boolean canDisplayBottomControls();
+        public boolean canDisplayBottomControl(int control);
+        public void onBottomControlClicked(int control);
+    }
+
+    private Delegate mDelegate;
+    private ViewGroup mParentLayout;
+    private ViewGroup mContainer;
+
+    private boolean mContainerVisible = false;
+    private Map<View, Boolean> mControlsVisible = new HashMap<View, Boolean>();
+
+    private Animation mContainerAnimIn = new AlphaAnimation(0f, 1f);
+    private Animation mContainerAnimOut = new AlphaAnimation(1f, 0f);
+    private static final int CONTAINER_ANIM_DURATION_MS = 200;
+
+    private static final int CONTROL_ANIM_DURATION_MS = 150;
+    private static Animation getControlAnimForVisibility(boolean visible) {
+        Animation anim = visible ? new ScaleAnimation(0, 1, 1, 1)
+                : new ScaleAnimation(1, 0, 1, 1);
+        anim.setDuration(CONTROL_ANIM_DURATION_MS);
+        return anim;
+    }
+
+    public PhotoPageBottomControls(Delegate delegate, Context context, RelativeLayout layout) {
+        mDelegate = delegate;
+        mParentLayout = layout;
+
+        LayoutInflater inflater = (LayoutInflater) context
+                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        mContainer = (ViewGroup) inflater
+                .inflate(R.layout.photopage_bottom_controls, mParentLayout, false);
+        mParentLayout.addView(mContainer);
+
+        for (int i = mContainer.getChildCount() - 1; i >= 0; i--) {
+            View child = mContainer.getChildAt(i);
+            child.setOnClickListener(this);
+            mControlsVisible.put(child, false);
+        }
+
+        mContainerAnimIn.setDuration(CONTAINER_ANIM_DURATION_MS);
+        mContainerAnimOut.setDuration(CONTAINER_ANIM_DURATION_MS);
+
+        refresh();
+    }
+
+    private void hide() {
+        mContainer.clearAnimation();
+        mContainerAnimOut.reset();
+        mContainer.startAnimation(mContainerAnimOut);
+        mContainer.setVisibility(View.INVISIBLE);
+    }
+
+    private void show() {
+        mContainer.clearAnimation();
+        mContainerAnimIn.reset();
+        mContainer.startAnimation(mContainerAnimIn);
+        mContainer.setVisibility(View.VISIBLE);
+    }
+
+    public void refresh() {
+        boolean visible = mDelegate.canDisplayBottomControls();
+        boolean containerVisibilityChanged = (visible != mContainerVisible);
+        if (containerVisibilityChanged) {
+            if (visible) {
+                show();
+            } else {
+                hide();
+            }
+            mContainerVisible = visible;
+        }
+        if (!mContainerVisible) {
+            return;
+        }
+        for (View control : mControlsVisible.keySet()) {
+            Boolean prevVisibility = mControlsVisible.get(control);
+            boolean curVisibility = mDelegate.canDisplayBottomControl(control.getId());
+            if (prevVisibility.booleanValue() != curVisibility) {
+                if (!containerVisibilityChanged) {
+                    control.clearAnimation();
+                    control.startAnimation(getControlAnimForVisibility(curVisibility));
+                }
+                control.setVisibility(curVisibility ? View.VISIBLE : View.INVISIBLE);
+                mControlsVisible.put(control, curVisibility);
+            }
+        }
+    }
+
+    public void cleanup() {
+        mParentLayout.removeView(mContainer);
+        mControlsVisible.clear();
+    }
+
+    @Override
+    public void onClick(View view) {
+        if (mContainerVisible && mControlsVisible.get(view).booleanValue()) {
+            mDelegate.onBottomControlClicked(view.getId());
+        }
+    }
+}