• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Configuration;
24 import android.content.res.Resources;
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.FrameLayout;
35 import android.widget.RelativeLayout;
36 
37 
38 /**
39  * Base class for a title bar used by the browser.
40  */
41 public class TitleBar extends RelativeLayout {
42 
43     private static final int PROGRESS_MAX = 100;
44     private static final float ANIM_TITLEBAR_DECELERATE = 2.5f;
45 
46     private UiController mUiController;
47     private BaseUi mBaseUi;
48     private FrameLayout mContentView;
49     private PageProgressView mProgress;
50 
51     private AutologinBar mAutoLogin;
52     private NavigationBarBase mNavBar;
53     private boolean mUseQuickControls;
54     private SnapshotBar mSnapshotBar;
55 
56     //state
57     private boolean mShowing;
58     private boolean mInLoad;
59     private boolean mSkipTitleBarAnimations;
60     private Animator mTitleBarAnimator;
61     private boolean mIsFixedTitleBar;
62 
TitleBar(Context context, UiController controller, BaseUi ui, FrameLayout contentView)63     public TitleBar(Context context, UiController controller, BaseUi ui,
64             FrameLayout contentView) {
65         super(context, null);
66         mUiController = controller;
67         mBaseUi = ui;
68         mContentView = contentView;
69         initLayout(context);
70         setFixedTitleBar();
71     }
72 
initLayout(Context context)73     private void initLayout(Context context) {
74         LayoutInflater factory = LayoutInflater.from(context);
75         factory.inflate(R.layout.title_bar, this);
76         mProgress = (PageProgressView) findViewById(R.id.progress);
77         mNavBar = (NavigationBarBase) findViewById(R.id.taburlbar);
78         mNavBar.setTitleBar(this);
79     }
80 
inflateAutoLoginBar()81     private void inflateAutoLoginBar() {
82         if (mAutoLogin != null) {
83             return;
84         }
85 
86         ViewStub stub = (ViewStub) findViewById(R.id.autologin_stub);
87         mAutoLogin = (AutologinBar) stub.inflate();
88         mAutoLogin.setTitleBar(this);
89     }
90 
inflateSnapshotBar()91     private void inflateSnapshotBar() {
92         if (mSnapshotBar != null) {
93             return;
94         }
95 
96         ViewStub stub = (ViewStub) findViewById(R.id.snapshotbar_stub);
97         mSnapshotBar = (SnapshotBar) stub.inflate();
98         mSnapshotBar.setTitleBar(this);
99     }
100 
101     @Override
onConfigurationChanged(Configuration config)102     protected void onConfigurationChanged(Configuration config) {
103         super.onConfigurationChanged(config);
104         setFixedTitleBar();
105     }
106 
107     @Override
onMeasure(int widthMeasureSpec, int heightMeasureSpec)108     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
109         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
110         if (mIsFixedTitleBar) {
111             int margin = getMeasuredHeight() - calculateEmbeddedHeight();
112             mBaseUi.setContentViewMarginTop(-margin);
113         } else {
114             mBaseUi.setContentViewMarginTop(0);
115         }
116     }
117 
setFixedTitleBar()118     private void setFixedTitleBar() {
119         boolean isFixed = !mUseQuickControls
120                 && !mContext.getResources().getBoolean(R.bool.hide_title);
121         // If getParent() returns null, we are initializing
122         ViewGroup parent = (ViewGroup)getParent();
123         if (mIsFixedTitleBar == isFixed && parent != null) return;
124         mIsFixedTitleBar = isFixed;
125         setSkipTitleBarAnimations(true);
126         show();
127         setSkipTitleBarAnimations(false);
128         if (parent != null) {
129             parent.removeView(this);
130         }
131         if (mIsFixedTitleBar) {
132             mBaseUi.addFixedTitleBar(this);
133         } else {
134             mContentView.addView(this, makeLayoutParams());
135             mBaseUi.setContentViewMarginTop(0);
136         }
137     }
138 
getUi()139     public BaseUi getUi() {
140         return mBaseUi;
141     }
142 
getUiController()143     public UiController getUiController() {
144         return mUiController;
145     }
146 
setUseQuickControls(boolean use)147     public void setUseQuickControls(boolean use) {
148         mUseQuickControls = use;
149         setFixedTitleBar();
150         if (use) {
151             this.setVisibility(View.GONE);
152         } else {
153             this.setVisibility(View.VISIBLE);
154         }
155     }
156 
setShowProgressOnly(boolean progress)157     void setShowProgressOnly(boolean progress) {
158         if (progress && !wantsToBeVisible()) {
159             mNavBar.setVisibility(View.GONE);
160         } else {
161             mNavBar.setVisibility(View.VISIBLE);
162         }
163     }
164 
setSkipTitleBarAnimations(boolean skip)165     void setSkipTitleBarAnimations(boolean skip) {
166         mSkipTitleBarAnimations = skip;
167     }
168 
setupTitleBarAnimator(Animator animator)169     void setupTitleBarAnimator(Animator animator) {
170         Resources res = mContext.getResources();
171         int duration = res.getInteger(R.integer.titlebar_animation_duration);
172         animator.setInterpolator(new DecelerateInterpolator(
173                 ANIM_TITLEBAR_DECELERATE));
174         animator.setDuration(duration);
175     }
176 
show()177     void show() {
178         cancelTitleBarAnimation(false);
179         if (mUseQuickControls || mSkipTitleBarAnimations) {
180             this.setVisibility(View.VISIBLE);
181             this.setTranslationY(0);
182         } else {
183             int visibleHeight = getVisibleTitleHeight();
184             float startPos = (-getEmbeddedHeight() + visibleHeight);
185             if (getTranslationY() != 0) {
186                 startPos = Math.max(startPos, getTranslationY());
187             }
188             mTitleBarAnimator = ObjectAnimator.ofFloat(this,
189                     "translationY",
190                     startPos, 0);
191             setupTitleBarAnimator(mTitleBarAnimator);
192             mTitleBarAnimator.start();
193         }
194         mShowing = true;
195     }
196 
hide()197     void hide() {
198         if (mUseQuickControls) {
199             this.setVisibility(View.GONE);
200         } else {
201             if (mIsFixedTitleBar) return;
202             if (!mSkipTitleBarAnimations) {
203                 cancelTitleBarAnimation(false);
204                 int visibleHeight = getVisibleTitleHeight();
205                 mTitleBarAnimator = ObjectAnimator.ofFloat(this,
206                         "translationY", getTranslationY(),
207                         (-getEmbeddedHeight() + visibleHeight));
208                 mTitleBarAnimator.addListener(mHideTileBarAnimatorListener);
209                 setupTitleBarAnimator(mTitleBarAnimator);
210                 mTitleBarAnimator.start();
211             } else {
212                 onScrollChanged();
213             }
214         }
215         mShowing = false;
216     }
217 
isShowing()218     boolean isShowing() {
219         return mShowing;
220     }
221 
cancelTitleBarAnimation(boolean reset)222     void cancelTitleBarAnimation(boolean reset) {
223         if (mTitleBarAnimator != null) {
224             mTitleBarAnimator.cancel();
225             mTitleBarAnimator = null;
226         }
227         if (reset) {
228             setTranslationY(0);
229         }
230     }
231 
232     private AnimatorListener mHideTileBarAnimatorListener = new AnimatorListener() {
233 
234         @Override
235         public void onAnimationStart(Animator animation) {
236         }
237 
238         @Override
239         public void onAnimationRepeat(Animator animation) {
240         }
241 
242         @Override
243         public void onAnimationEnd(Animator animation) {
244             // update position
245             onScrollChanged();
246         }
247 
248         @Override
249         public void onAnimationCancel(Animator animation) {
250         }
251     };
252 
getVisibleTitleHeight()253     private int getVisibleTitleHeight() {
254         Tab tab = mBaseUi.getActiveTab();
255         WebView webview = tab != null ? tab.getWebView() : null;
256         return webview != null ? webview.getVisibleTitleHeight() : 0;
257     }
258 
259     /**
260      * Update the progress, from 0 to 100.
261      */
setProgress(int newProgress)262     public void setProgress(int newProgress) {
263         if (newProgress >= PROGRESS_MAX) {
264             mProgress.setProgress(PageProgressView.MAX_PROGRESS);
265             mProgress.setVisibility(View.GONE);
266             mInLoad = false;
267             mNavBar.onProgressStopped();
268             // check if needs to be hidden
269             if (!isEditingUrl() && !wantsToBeVisible()) {
270                 if (mUseQuickControls) {
271                     hide();
272                 } else {
273                     mBaseUi.showTitleBarForDuration();
274                 }
275             }
276         } else {
277             if (!mInLoad) {
278                 mProgress.setVisibility(View.VISIBLE);
279                 mInLoad = true;
280                 mNavBar.onProgressStarted();
281             }
282             mProgress.setProgress(newProgress * PageProgressView.MAX_PROGRESS
283                     / PROGRESS_MAX);
284             if (mUseQuickControls && !isEditingUrl()) {
285                 setShowProgressOnly(true);
286             }
287             if (!mShowing) {
288                 show();
289             }
290         }
291     }
292 
getEmbeddedHeight()293     public int getEmbeddedHeight() {
294         if (mUseQuickControls || mIsFixedTitleBar) return 0;
295         return calculateEmbeddedHeight();
296     }
297 
calculateEmbeddedHeight()298     private int calculateEmbeddedHeight() {
299         int height = mNavBar.getHeight();
300         if (mAutoLogin != null && mAutoLogin.getVisibility() == View.VISIBLE) {
301             height += mAutoLogin.getHeight();
302         }
303         return height;
304     }
305 
updateAutoLogin(Tab tab, boolean animate)306     public void updateAutoLogin(Tab tab, boolean animate) {
307         if (mAutoLogin == null) {
308             if  (tab.getDeviceAccountLogin() == null) {
309                 return;
310             }
311             inflateAutoLoginBar();
312         }
313         mAutoLogin.updateAutoLogin(tab, animate);
314     }
315 
showAutoLogin(boolean animate)316     public void showAutoLogin(boolean animate) {
317         if (mUseQuickControls) {
318             mBaseUi.showTitleBar();
319         }
320         if (mAutoLogin == null) {
321             inflateAutoLoginBar();
322         }
323         mAutoLogin.setVisibility(View.VISIBLE);
324         if (animate) {
325             mAutoLogin.startAnimation(AnimationUtils.loadAnimation(
326                     getContext(), R.anim.autologin_enter));
327         }
328     }
329 
hideAutoLogin(boolean animate)330     public void hideAutoLogin(boolean animate) {
331         if (mUseQuickControls) {
332             mBaseUi.hideTitleBar();
333             mAutoLogin.setVisibility(View.GONE);
334             mBaseUi.refreshWebView();
335         } else {
336             if (animate) {
337                 Animation anim = AnimationUtils.loadAnimation(getContext(),
338                         R.anim.autologin_exit);
339                 anim.setAnimationListener(new AnimationListener() {
340                     @Override
341                     public void onAnimationEnd(Animation a) {
342                         mAutoLogin.setVisibility(View.GONE);
343                         mBaseUi.refreshWebView();
344                     }
345 
346                     @Override
347                     public void onAnimationStart(Animation a) {
348                     }
349 
350                     @Override
351                     public void onAnimationRepeat(Animation a) {
352                     }
353                 });
354                 mAutoLogin.startAnimation(anim);
355             } else if (mAutoLogin.getAnimation() == null) {
356                 mAutoLogin.setVisibility(View.GONE);
357                 mBaseUi.refreshWebView();
358             }
359         }
360     }
361 
wantsToBeVisible()362     public boolean wantsToBeVisible() {
363         return inAutoLogin()
364             || (mSnapshotBar != null && mSnapshotBar.getVisibility() == View.VISIBLE
365                     && mSnapshotBar.isAnimating());
366     }
367 
inAutoLogin()368     private boolean inAutoLogin() {
369         return mAutoLogin != null && mAutoLogin.getVisibility() == View.VISIBLE;
370     }
371 
isEditingUrl()372     public boolean isEditingUrl() {
373         return mNavBar.isEditingUrl();
374     }
375 
getCurrentWebView()376     public WebView getCurrentWebView() {
377         Tab t = mBaseUi.getActiveTab();
378         if (t != null) {
379             return t.getWebView();
380         } else {
381             return null;
382         }
383     }
384 
getProgressView()385     public PageProgressView getProgressView() {
386         return mProgress;
387     }
388 
getNavigationBar()389     public NavigationBarBase getNavigationBar() {
390         return mNavBar;
391     }
392 
useQuickControls()393     public boolean useQuickControls() {
394         return mUseQuickControls;
395     }
396 
isInLoad()397     public boolean isInLoad() {
398         return mInLoad;
399     }
400 
makeLayoutParams()401     private ViewGroup.LayoutParams makeLayoutParams() {
402         return new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
403                 LayoutParams.WRAP_CONTENT);
404     }
405 
406     @Override
focusSearch(View focused, int dir)407     public View focusSearch(View focused, int dir) {
408         WebView web = getCurrentWebView();
409         if (FOCUS_DOWN == dir && hasFocus() && web != null
410                 && web.hasFocusable() && web.getParent() != null) {
411             return web;
412         }
413         return super.focusSearch(focused, dir);
414     }
415 
onTabDataChanged(Tab tab)416     public void onTabDataChanged(Tab tab) {
417         if (mSnapshotBar != null) {
418             mSnapshotBar.onTabDataChanged(tab);
419         }
420 
421         if (tab.isSnapshot()) {
422             inflateSnapshotBar();
423             mSnapshotBar.setVisibility(VISIBLE);
424             mNavBar.setVisibility(GONE);
425         } else {
426             if (mSnapshotBar != null) {
427                 mSnapshotBar.setVisibility(GONE);
428             }
429             mNavBar.setVisibility(VISIBLE);
430         }
431     }
432 
onScrollChanged()433     public void onScrollChanged() {
434         if (!mShowing && !mIsFixedTitleBar) {
435             setTranslationY(getVisibleTitleHeight() - getEmbeddedHeight());
436         }
437     }
438 
439 }
440