Home | History | Annotate | Download | only in browser
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.browser;
     18 
     19 import android.animation.Animator;
     20 import android.animation.Animator.AnimatorListener;
     21 import android.animation.ObjectAnimator;
     22 import android.content.Context;
     23 import android.content.res.Resources;
     24 import android.view.Gravity;
     25 import android.view.LayoutInflater;
     26 import android.view.View;
     27 import android.view.ViewGroup;
     28 import android.view.ViewStub;
     29 import android.view.animation.Animation;
     30 import android.view.animation.Animation.AnimationListener;
     31 import android.view.animation.AnimationUtils;
     32 import android.view.animation.DecelerateInterpolator;
     33 import android.webkit.WebView;
     34 import android.widget.AbsoluteLayout;
     35 import android.widget.FrameLayout;
     36 import android.widget.RelativeLayout;
     37 
     38 
     39 /**
     40  * Base class for a title bar used by the browser.
     41  */
     42 public class TitleBar extends RelativeLayout {
     43 
     44     private static final int PROGRESS_MAX = 100;
     45     private static final float ANIM_TITLEBAR_DECELERATE = 2.5f;
     46 
     47     private UiController mUiController;
     48     private BaseUi mBaseUi;
     49     private FrameLayout mParent;
     50     private PageProgressView mProgress;
     51 
     52     private AutologinBar mAutoLogin;
     53     private NavigationBarBase mNavBar;
     54     private boolean mUseQuickControls;
     55     private SnapshotBar mSnapshotBar;
     56 
     57     //state
     58     private boolean mShowing;
     59     private boolean mInLoad;
     60     private boolean mSkipTitleBarAnimations;
     61     private Animator mTitleBarAnimator;
     62 
     63     public TitleBar(Context context, UiController controller, BaseUi ui,
     64             FrameLayout parent) {
     65         super(context, null);
     66         mUiController = controller;
     67         mBaseUi = ui;
     68         mParent = parent;
     69         initLayout(context);
     70     }
     71 
     72     private void initLayout(Context context) {
     73         LayoutInflater factory = LayoutInflater.from(context);
     74         factory.inflate(R.layout.title_bar, this);
     75         mProgress = (PageProgressView) findViewById(R.id.progress);
     76         mNavBar = (NavigationBarBase) findViewById(R.id.taburlbar);
     77         mNavBar.setTitleBar(this);
     78     }
     79 
     80     private void inflateAutoLoginBar() {
     81         if (mAutoLogin != null) {
     82             return;
     83         }
     84 
     85         ViewStub stub = (ViewStub) findViewById(R.id.autologin_stub);
     86         mAutoLogin = (AutologinBar) stub.inflate();
     87         mAutoLogin.setTitleBar(this);
     88     }
     89 
     90     private void inflateSnapshotBar() {
     91         if (mSnapshotBar != null) {
     92             return;
     93         }
     94 
     95         ViewStub stub = (ViewStub) findViewById(R.id.snapshotbar_stub);
     96         mSnapshotBar = (SnapshotBar) stub.inflate();
     97         mSnapshotBar.setTitleBar(this);
     98     }
     99 
    100     public BaseUi getUi() {
    101         return mBaseUi;
    102     }
    103 
    104     public UiController getUiController() {
    105         return mUiController;
    106     }
    107 
    108     public void setUseQuickControls(boolean use) {
    109         mUseQuickControls = use;
    110         setLayoutParams(makeLayoutParams());
    111     }
    112 
    113     void setShowProgressOnly(boolean progress) {
    114         if (progress && !wantsToBeVisible()) {
    115             mNavBar.setVisibility(View.GONE);
    116         } else {
    117             mNavBar.setVisibility(View.VISIBLE);
    118         }
    119     }
    120 
    121     void setSkipTitleBarAnimations(boolean skip) {
    122         mSkipTitleBarAnimations = skip;
    123     }
    124 
    125     void setupTitleBarAnimator(Animator animator) {
    126         Resources res = mContext.getResources();
    127         int duration = res.getInteger(R.integer.titlebar_animation_duration);
    128         animator.setInterpolator(new DecelerateInterpolator(
    129                 ANIM_TITLEBAR_DECELERATE));
    130         animator.setDuration(duration);
    131     }
    132 
    133     void show() {
    134         if (mUseQuickControls) {
    135             mParent.addView(this);
    136         } else {
    137             if (!mSkipTitleBarAnimations) {
    138                 cancelTitleBarAnimation(false);
    139                 int visibleHeight = getVisibleTitleHeight();
    140                 float startPos = (-getEmbeddedHeight() + visibleHeight);
    141                 if (getTranslationY() != 0) {
    142                     startPos = Math.max(startPos, getTranslationY());
    143                 }
    144                 mTitleBarAnimator = ObjectAnimator.ofFloat(this,
    145                         "translationY",
    146                         startPos, 0);
    147                 setupTitleBarAnimator(mTitleBarAnimator);
    148                 mTitleBarAnimator.start();
    149             }
    150             mBaseUi.setTitleGravity(Gravity.TOP);
    151         }
    152         mShowing = true;
    153     }
    154 
    155     void hide() {
    156         if (mUseQuickControls) {
    157             mParent.removeView(this);
    158         } else {
    159             if (!mSkipTitleBarAnimations) {
    160                 cancelTitleBarAnimation(false);
    161                 int visibleHeight = getVisibleTitleHeight();
    162                 mTitleBarAnimator = ObjectAnimator.ofFloat(this,
    163                         "translationY", getTranslationY(),
    164                         (-getEmbeddedHeight() + visibleHeight));
    165                 mTitleBarAnimator.addListener(mHideTileBarAnimatorListener);
    166                 setupTitleBarAnimator(mTitleBarAnimator);
    167                 mTitleBarAnimator.start();
    168             } else {
    169                 mBaseUi.setTitleGravity(Gravity.NO_GRAVITY);
    170             }
    171         }
    172         mShowing = false;
    173     }
    174 
    175     boolean isShowing() {
    176         return mShowing;
    177     }
    178 
    179     void cancelTitleBarAnimation(boolean reset) {
    180         if (mTitleBarAnimator != null) {
    181             mTitleBarAnimator.cancel();
    182             mTitleBarAnimator = null;
    183         }
    184         if (reset) {
    185             setTranslationY(0);
    186         }
    187     }
    188 
    189     private AnimatorListener mHideTileBarAnimatorListener = new AnimatorListener() {
    190 
    191         boolean mWasCanceled;
    192         @Override
    193         public void onAnimationStart(Animator animation) {
    194             mWasCanceled = false;
    195         }
    196 
    197         @Override
    198         public void onAnimationRepeat(Animator animation) {
    199         }
    200 
    201         @Override
    202         public void onAnimationEnd(Animator animation) {
    203             if (!mWasCanceled) {
    204                 setTranslationY(0);
    205             }
    206             mBaseUi.setTitleGravity(Gravity.NO_GRAVITY);
    207         }
    208 
    209         @Override
    210         public void onAnimationCancel(Animator animation) {
    211             mWasCanceled = true;
    212         }
    213     };
    214 
    215     private int getVisibleTitleHeight() {
    216         Tab tab = mBaseUi.getActiveTab();
    217         WebView webview = tab != null ? tab.getWebView() : null;
    218         return webview != null ? webview.getVisibleTitleHeight() : 0;
    219     }
    220 
    221     /**
    222      * Update the progress, from 0 to 100.
    223      */
    224     public void setProgress(int newProgress) {
    225         if (newProgress >= PROGRESS_MAX) {
    226             mProgress.setProgress(PageProgressView.MAX_PROGRESS);
    227             mProgress.setVisibility(View.GONE);
    228             mInLoad = false;
    229             mNavBar.onProgressStopped();
    230             // check if needs to be hidden
    231             if (!isEditingUrl() && !wantsToBeVisible()) {
    232                 hide();
    233                 if (mUseQuickControls) {
    234                     setShowProgressOnly(false);
    235                 }
    236             }
    237         } else {
    238             if (!mInLoad) {
    239                 mProgress.setVisibility(View.VISIBLE);
    240                 mInLoad = true;
    241                 mNavBar.onProgressStarted();
    242             }
    243             mProgress.setProgress(newProgress * PageProgressView.MAX_PROGRESS
    244                     / PROGRESS_MAX);
    245             if (!mShowing) {
    246                 if (mUseQuickControls && !isEditingUrl()) {
    247                     setShowProgressOnly(true);
    248                 }
    249                 show();
    250             }
    251         }
    252     }
    253 
    254     public int getEmbeddedHeight() {
    255         int height = mNavBar.getHeight();
    256         if (mAutoLogin != null && mAutoLogin.getVisibility() == View.VISIBLE) {
    257             height += mAutoLogin.getHeight();
    258         }
    259         return height;
    260     }
    261 
    262     public void updateAutoLogin(Tab tab, boolean animate) {
    263         if (mAutoLogin == null) {
    264             if  (tab.getDeviceAccountLogin() == null) {
    265                 return;
    266             }
    267             inflateAutoLoginBar();
    268         }
    269         mAutoLogin.updateAutoLogin(tab, animate);
    270     }
    271 
    272     public void showAutoLogin(boolean animate) {
    273         if (mUseQuickControls) {
    274             mBaseUi.showTitleBar();
    275         }
    276         if (mAutoLogin == null) {
    277             inflateAutoLoginBar();
    278         }
    279         mAutoLogin.setVisibility(View.VISIBLE);
    280         if (animate) {
    281             mAutoLogin.startAnimation(AnimationUtils.loadAnimation(
    282                     getContext(), R.anim.autologin_enter));
    283         }
    284     }
    285 
    286     public void hideAutoLogin(boolean animate) {
    287         if (mUseQuickControls) {
    288             mBaseUi.hideTitleBar();
    289             mAutoLogin.setVisibility(View.GONE);
    290             mBaseUi.refreshWebView();
    291         } else {
    292             if (animate) {
    293                 Animation anim = AnimationUtils.loadAnimation(getContext(),
    294                         R.anim.autologin_exit);
    295                 anim.setAnimationListener(new AnimationListener() {
    296                     @Override
    297                     public void onAnimationEnd(Animation a) {
    298                         mAutoLogin.setVisibility(View.GONE);
    299                         mBaseUi.refreshWebView();
    300                     }
    301 
    302                     @Override
    303                     public void onAnimationStart(Animation a) {
    304                     }
    305 
    306                     @Override
    307                     public void onAnimationRepeat(Animation a) {
    308                     }
    309                 });
    310                 mAutoLogin.startAnimation(anim);
    311             } else if (mAutoLogin.getAnimation() == null) {
    312                 mAutoLogin.setVisibility(View.GONE);
    313                 mBaseUi.refreshWebView();
    314             }
    315         }
    316     }
    317 
    318     public boolean wantsToBeVisible() {
    319         return inAutoLogin()
    320             || (mSnapshotBar != null && mSnapshotBar.getVisibility() == View.VISIBLE
    321                     && mSnapshotBar.isAnimating());
    322     }
    323 
    324     private boolean inAutoLogin() {
    325         return mAutoLogin != null && mAutoLogin.getVisibility() == View.VISIBLE;
    326     }
    327 
    328     public boolean isEditingUrl() {
    329         return mNavBar.isEditingUrl();
    330     }
    331 
    332     public WebView getCurrentWebView() {
    333         Tab t = mBaseUi.getActiveTab();
    334         if (t != null) {
    335             return t.getWebView();
    336         } else {
    337             return null;
    338         }
    339     }
    340 
    341     public PageProgressView getProgressView() {
    342         return mProgress;
    343     }
    344 
    345     public NavigationBarBase getNavigationBar() {
    346         return mNavBar;
    347     }
    348 
    349     public boolean useQuickControls() {
    350         return mUseQuickControls;
    351     }
    352 
    353     public boolean isInLoad() {
    354         return mInLoad;
    355     }
    356 
    357     private ViewGroup.LayoutParams makeLayoutParams() {
    358         if (mUseQuickControls) {
    359             return new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
    360                     LayoutParams.WRAP_CONTENT);
    361         } else {
    362             return new AbsoluteLayout.LayoutParams(
    363                     LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT,
    364                     0, 0);
    365         }
    366     }
    367 
    368     @Override
    369     public View focusSearch(View focused, int dir) {
    370         if (FOCUS_DOWN == dir && hasFocus()) {
    371             return getCurrentWebView();
    372         }
    373         return super.focusSearch(focused, dir);
    374     }
    375 
    376     public void onTabDataChanged(Tab tab) {
    377         if (mSnapshotBar != null) {
    378             mSnapshotBar.onTabDataChanged(tab);
    379         }
    380 
    381         if (tab.isSnapshot()) {
    382             inflateSnapshotBar();
    383             mSnapshotBar.setVisibility(VISIBLE);
    384             mNavBar.setVisibility(GONE);
    385         } else {
    386             if (mSnapshotBar != null) {
    387                 mSnapshotBar.setVisibility(GONE);
    388             }
    389             mNavBar.setVisibility(VISIBLE);
    390         }
    391     }
    392 
    393 }
    394