Tab switcher animation

    Bug: 5123884

    first step towards animations between browser and tab switcher

Change-Id: I1d959d42d0036f3c4498972fcc8ad434fa7f4437
diff --git a/src/com/android/browser/PhoneUi.java b/src/com/android/browser/PhoneUi.java
index 863a628..d77fcdb 100644
--- a/src/com/android/browser/PhoneUi.java
+++ b/src/com/android/browser/PhoneUi.java
@@ -16,17 +16,29 @@
 
 package com.android.browser;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
 import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
 import android.util.Log;
 import android.view.ActionMode;
 import android.view.Gravity;
 import android.view.KeyEvent;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.animation.DecelerateInterpolator;
 import android.webkit.WebView;
 import android.widget.FrameLayout;
+import android.widget.ImageView;
 
 import com.android.browser.UrlInputView.StateListener;
 
@@ -241,15 +253,72 @@
         updateUrlBarAutoShowManagerTarget();
     }
 
+    @Override
+    public boolean isWebShowing() {
+        return super.isWebShowing() && mNavScreen == null;
+    }
+
+    @Override
+    public void showWeb(boolean animate) {
+        super.showWeb(animate);
+        hideNavScreen(animate);
+    }
+
     void showNavScreen() {
-        mActiveTab.capture();
-        detachTab(mActiveTab);
+        mUiController.setBlockEvents(true);
         mNavScreen = new NavScreen(mActivity, mUiController, this);
-        // Add the custom view to its container.
+        mActiveTab.capture();
+        // Add the custom view to its container
         mCustomViewContainer.addView(mNavScreen, COVER_SCREEN_PARAMS);
-        mContentView.setVisibility(View.GONE);
+        AnimScreen ascreen = new AnimScreen(mActivity, getTitleBar(), getWebView());
+        final View animView = ascreen.mMain;
+        mCustomViewContainer.addView(animView, COVER_SCREEN_PARAMS);
         mCustomViewContainer.setVisibility(View.VISIBLE);
         mCustomViewContainer.bringToFront();
+        View target = ((NavTabView) mNavScreen.mScroller.getSelectedView()).mImage;
+        int fromLeft = 0;
+        int fromTop = getTitleBar().getHeight();
+        int fromRight = mContentView.getWidth();
+        int fromBottom = mContentView.getHeight();
+        int width = target.getWidth();
+        int height = target.getHeight();
+        int toLeft = (mContentView.getWidth() - width) / 2;
+        int toTop = fromTop + (mContentView.getHeight() - fromTop - height) / 2;
+        int toRight = toLeft + width;
+        int toBottom = toTop + height;
+        float scaleFactor = width / (float) mContentView.getWidth();
+        detachTab(mActiveTab);
+        mContentView.setVisibility(View.GONE);
+        AnimatorSet inanim = new AnimatorSet();
+        ObjectAnimator tx = ObjectAnimator.ofInt(ascreen.mContent, "left",
+                fromLeft, toLeft);
+        ObjectAnimator ty = ObjectAnimator.ofInt(ascreen.mContent, "top",
+                fromTop, toTop);
+        ObjectAnimator tr = ObjectAnimator.ofInt(ascreen.mContent, "right",
+                fromRight, toRight);
+        ObjectAnimator tb = ObjectAnimator.ofInt(ascreen.mContent, "bottom",
+                fromBottom, toBottom);
+        ObjectAnimator title = ObjectAnimator.ofFloat(ascreen.mTitle, "alpha",
+                1f, 0f);
+        ObjectAnimator content = ObjectAnimator.ofFloat(ascreen.mContent, "alpha",
+                1f, 0f);
+        ObjectAnimator sx = ObjectAnimator.ofFloat(ascreen, "scaleFactor",
+                1f, scaleFactor);
+        inanim.playTogether(tx, ty, tr, tb, title, content, sx);
+        inanim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator anim) {
+                mCustomViewContainer.removeView(animView);
+                finishAnimationIn();
+                mUiController.setBlockEvents(false);
+            }
+        });
+        inanim.setInterpolator(new DecelerateInterpolator(2f));
+        inanim.setDuration(300);
+        inanim.start();
+    }
+
+    private void finishAnimationIn() {
         // notify accessibility manager about the screen change
         mNavScreen.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
         mTabControl.setOnThumbnailUpdatedListener(mNavScreen);
@@ -257,14 +326,67 @@
 
     void hideNavScreen(boolean animate) {
         if (mNavScreen == null) return;
+        final Tab tab = mNavScreen.getSelectedTab();
+        if ((tab != null) && !animate) {
+            finishAnimateOut(tab);
+        }
+        NavTabView tabview = (NavTabView) mNavScreen.getSelectedTabView();
+        if (tabview == null) {
+            finishAnimateOut(tab);
+        }
+        mUiController.setBlockEvents(true);
+        mUiController.setActiveTab(tab);
+        mContentView.setVisibility(View.VISIBLE);
+        final AnimScreen screen = new AnimScreen(mActivity, tab.getScreenshot());
+        View target = ((NavTabView) mNavScreen.mScroller.getSelectedView()).mImage;
+        int toLeft = 0;
+        int toTop = getTitleBar().getHeight();
+        int toRight = mContentView.getWidth();
+        int width = target.getWidth();
+        int height = target.getHeight();
+        int[] pos = new int[2];
+        tabview.mImage.getLocationInWindow(pos);
+        int fromLeft = pos[0];
+        int fromTop = pos[1];
+        int fromRight = fromLeft + width;
+        int fromBottom = fromTop + height;
+        float scaleFactor = mContentView.getWidth() / (float) width;
+        int toBottom = (int) (height * scaleFactor);
+        screen.mMain.setAlpha(0f);
+        mCustomViewContainer.addView(screen.mMain, COVER_SCREEN_PARAMS);
+        AnimatorSet animSet = new AnimatorSet();
+        ObjectAnimator l = ObjectAnimator.ofInt(screen.mContent, "left",
+                fromLeft, toLeft);
+        ObjectAnimator t = ObjectAnimator.ofInt(screen.mContent, "top",
+                fromTop, toTop);
+        ObjectAnimator r = ObjectAnimator.ofInt(screen.mContent, "right",
+                fromRight, toRight);
+        ObjectAnimator b = ObjectAnimator.ofInt(screen.mContent, "bottom",
+                fromBottom, toBottom);
+        ObjectAnimator scale = ObjectAnimator.ofFloat(screen, "scaleFactor",
+                1f, scaleFactor);
+        ObjectAnimator alpha = ObjectAnimator.ofFloat(screen.mMain, "alpha", 1f, 1f);
+        ObjectAnimator otheralpha = ObjectAnimator.ofFloat(mCustomViewContainer, "alpha", 1f, 0f);
+        alpha.setStartDelay(100);
+        animSet.playTogether(l, t, r, b, scale, alpha, otheralpha);
+        animSet.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator anim) {
+                mCustomViewContainer.removeView(screen.mMain);
+                finishAnimateOut(tab);
+                mUiController.setBlockEvents(false);
+            }
+        });
+        animSet.setDuration(250);
+        animSet.start();
+    }
+
+    private void finishAnimateOut(Tab tab) {
         mTabControl.setOnThumbnailUpdatedListener(null);
-        Tab tab = mNavScreen.getSelectedTab();
         mCustomViewContainer.removeView(mNavScreen);
+        mCustomViewContainer.setAlpha(1f);
         mNavScreen = null;
         mCustomViewContainer.setVisibility(View.GONE);
-        mUiController.setActiveTab(tab);
-        // Show the content view.
-        mContentView.setVisibility(View.VISIBLE);
     }
 
     @Override
@@ -285,15 +407,62 @@
         return true;
     }
 
-    @Override
-    public boolean isWebShowing() {
-        return super.isWebShowing() && mNavScreen == null;
-    }
+    static class AnimScreen {
 
-    @Override
-    public void showWeb(boolean animate) {
-        super.showWeb(animate);
-        hideNavScreen(animate);
+        private View mMain;
+        private ImageView mTitle;
+        private ImageView mContent;
+        private float mScale;
+
+        public AnimScreen(Context ctx, TitleBar tbar, WebView web) {
+            mMain = LayoutInflater.from(ctx).inflate(R.layout.anim_screen,
+                    null);
+            mContent = (ImageView) mMain.findViewById(R.id.content);
+            mContent.setTop(tbar.getHeight());
+
+            mTitle = (ImageView) mMain.findViewById(R.id.title);
+            Bitmap bm1 = Bitmap.createBitmap(tbar.getWidth(), tbar.getHeight(),
+                    Bitmap.Config.RGB_565);
+            Canvas c1 = new Canvas(bm1);
+            tbar.draw(c1);
+            mTitle.setImageBitmap(bm1);
+            int h = web.getHeight() - tbar.getHeight();
+            Bitmap bm2 = Bitmap.createBitmap(web.getWidth(), h,
+                    Bitmap.Config.RGB_565);
+            Canvas c2 = new Canvas(bm2);
+            int tx = web.getScrollX();
+            int ty = web.getScrollY();
+            c2.translate(-tx, -ty - tbar.getHeight());
+            web.draw(c2);
+            mContent.setImageBitmap(bm2);
+            mContent.setScaleType(ImageView.ScaleType.MATRIX);
+            mContent.setImageMatrix(new Matrix());
+            mScale = 1.0f;
+            setScaleFactor(getScaleFactor());
+        }
+
+        public AnimScreen(Context ctx, Bitmap image) {
+            mMain = LayoutInflater.from(ctx).inflate(R.layout.anim_screen,
+                    null);
+            mContent = (ImageView) mMain.findViewById(R.id.content);
+            mContent.setImageBitmap(image);
+            mContent.setScaleType(ImageView.ScaleType.MATRIX);
+            mContent.setImageMatrix(new Matrix());
+            mScale = 1.0f;
+            setScaleFactor(getScaleFactor());
+        }
+
+        public void setScaleFactor(float sf) {
+            mScale = sf;
+            Matrix m = new Matrix();
+            m.postScale(sf,sf);
+            mContent.setImageMatrix(m);
+        }
+
+        public float getScaleFactor() {
+            return mScale;
+        }
+
     }
 
 }