blob: f5be5d3a8420654e5c052777e781b4a386f0f4bb [file] [log] [blame]
John Reck0f602f32011-07-07 15:38:43 -07001/*
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
17package com.android.browser;
18
19import android.animation.Animator;
20import android.animation.Animator.AnimatorListener;
21import android.animation.ObjectAnimator;
22import android.content.Context;
Michael Kolb57059a82012-04-30 14:32:03 -070023import android.content.res.Configuration;
John Reck0f602f32011-07-07 15:38:43 -070024import android.content.res.Resources;
John Reck0f602f32011-07-07 15:38:43 -070025import android.view.LayoutInflater;
26import android.view.View;
27import android.view.ViewGroup;
Ben Murdochd51bb572011-08-17 20:42:02 +010028import android.view.ViewStub;
John Reck0f602f32011-07-07 15:38:43 -070029import android.view.animation.Animation;
30import android.view.animation.Animation.AnimationListener;
31import android.view.animation.AnimationUtils;
32import android.view.animation.DecelerateInterpolator;
33import android.webkit.WebView;
John Reck0f602f32011-07-07 15:38:43 -070034import android.widget.FrameLayout;
35import android.widget.RelativeLayout;
36
37
38/**
39 * Base class for a title bar used by the browser.
40 */
41public 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;
John Reck2711fab2012-05-18 21:38:59 -070048 private FrameLayout mContentView;
John Reck0f602f32011-07-07 15:38:43 -070049 private PageProgressView mProgress;
50
51 private AutologinBar mAutoLogin;
52 private NavigationBarBase mNavBar;
53 private boolean mUseQuickControls;
John Reckef654f12011-07-12 16:42:08 -070054 private SnapshotBar mSnapshotBar;
John Reck0f602f32011-07-07 15:38:43 -070055
56 //state
57 private boolean mShowing;
58 private boolean mInLoad;
59 private boolean mSkipTitleBarAnimations;
60 private Animator mTitleBarAnimator;
John Reck2711fab2012-05-18 21:38:59 -070061 private boolean mIsFixedTitleBar;
John Reck0f602f32011-07-07 15:38:43 -070062
63 public TitleBar(Context context, UiController controller, BaseUi ui,
John Reck2711fab2012-05-18 21:38:59 -070064 FrameLayout contentView) {
John Reck0f602f32011-07-07 15:38:43 -070065 super(context, null);
66 mUiController = controller;
67 mBaseUi = ui;
John Reck2711fab2012-05-18 21:38:59 -070068 mContentView = contentView;
John Reck0f602f32011-07-07 15:38:43 -070069 initLayout(context);
John Reck0f9aaeb2012-05-23 14:40:19 -070070 setFixedTitleBar();
John Reck0f602f32011-07-07 15:38:43 -070071 }
72
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);
John Reck0f602f32011-07-07 15:38:43 -070077 mNavBar = (NavigationBarBase) findViewById(R.id.taburlbar);
78 mNavBar.setTitleBar(this);
Ben Murdochd51bb572011-08-17 20:42:02 +010079 }
80
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
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();
John Reckef654f12011-07-12 16:42:08 -070098 mSnapshotBar.setTitleBar(this);
John Reck0f602f32011-07-07 15:38:43 -070099 }
100
Michael Kolb57059a82012-04-30 14:32:03 -0700101 @Override
102 protected void onConfigurationChanged(Configuration config) {
103 super.onConfigurationChanged(config);
John Reck0f9aaeb2012-05-23 14:40:19 -0700104 setFixedTitleBar();
John Reck2711fab2012-05-18 21:38:59 -0700105 }
106
107 @Override
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);
John Reck0f9aaeb2012-05-23 14:40:19 -0700113 } else {
114 mBaseUi.setContentViewMarginTop(0);
John Reck2711fab2012-05-18 21:38:59 -0700115 }
116 }
117
John Reck0f9aaeb2012-05-23 14:40:19 -0700118 private void setFixedTitleBar() {
119 boolean isFixed = !mUseQuickControls
120 && !mContext.getResources().getBoolean(R.bool.hide_title);
John Reck2711fab2012-05-18 21:38:59 -0700121 // 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);
Michael Kolb57059a82012-04-30 14:32:03 -0700136 }
137 }
138
John Reck0f602f32011-07-07 15:38:43 -0700139 public BaseUi getUi() {
140 return mBaseUi;
141 }
142
143 public UiController getUiController() {
144 return mUiController;
145 }
146
147 public void setUseQuickControls(boolean use) {
148 mUseQuickControls = use;
John Reck0f9aaeb2012-05-23 14:40:19 -0700149 setFixedTitleBar();
Michael Kolb4923c222012-04-02 16:18:36 -0700150 if (use) {
151 this.setVisibility(View.GONE);
152 } else {
153 this.setVisibility(View.VISIBLE);
154 }
John Reck0f602f32011-07-07 15:38:43 -0700155 }
156
157 void setShowProgressOnly(boolean progress) {
John Reckef654f12011-07-12 16:42:08 -0700158 if (progress && !wantsToBeVisible()) {
John Reck0f602f32011-07-07 15:38:43 -0700159 mNavBar.setVisibility(View.GONE);
160 } else {
161 mNavBar.setVisibility(View.VISIBLE);
162 }
163 }
164
165 void setSkipTitleBarAnimations(boolean skip) {
166 mSkipTitleBarAnimations = skip;
167 }
168
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
177 void show() {
John Reck2711fab2012-05-18 21:38:59 -0700178 cancelTitleBarAnimation(false);
179 if (mUseQuickControls || mSkipTitleBarAnimations) {
Michael Kolb4923c222012-04-02 16:18:36 -0700180 this.setVisibility(View.VISIBLE);
181 this.setTranslationY(0);
John Reck0f602f32011-07-07 15:38:43 -0700182 } else {
John Reck2711fab2012-05-18 21:38:59 -0700183 int visibleHeight = getVisibleTitleHeight();
184 float startPos = (-getEmbeddedHeight() + visibleHeight);
185 if (getTranslationY() != 0) {
186 startPos = Math.max(startPos, getTranslationY());
John Reck0f602f32011-07-07 15:38:43 -0700187 }
John Reck2711fab2012-05-18 21:38:59 -0700188 mTitleBarAnimator = ObjectAnimator.ofFloat(this,
189 "translationY",
190 startPos, 0);
191 setupTitleBarAnimator(mTitleBarAnimator);
192 mTitleBarAnimator.start();
John Reck0f602f32011-07-07 15:38:43 -0700193 }
194 mShowing = true;
195 }
196
197 void hide() {
198 if (mUseQuickControls) {
Michael Kolb4923c222012-04-02 16:18:36 -0700199 this.setVisibility(View.GONE);
John Reck0f602f32011-07-07 15:38:43 -0700200 } else {
John Reck2711fab2012-05-18 21:38:59 -0700201 if (mIsFixedTitleBar) return;
John Reck0f602f32011-07-07 15:38:43 -0700202 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 {
Michael Kolb4923c222012-04-02 16:18:36 -0700212 onScrollChanged();
John Reck0f602f32011-07-07 15:38:43 -0700213 }
214 }
215 mShowing = false;
216 }
217
218 boolean isShowing() {
219 return mShowing;
220 }
221
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
John Reck0f602f32011-07-07 15:38:43 -0700234 @Override
235 public void onAnimationStart(Animator animation) {
John Reck0f602f32011-07-07 15:38:43 -0700236 }
237
238 @Override
239 public void onAnimationRepeat(Animator animation) {
240 }
241
242 @Override
243 public void onAnimationEnd(Animator animation) {
Michael Kolb4923c222012-04-02 16:18:36 -0700244 // update position
245 onScrollChanged();
John Reck0f602f32011-07-07 15:38:43 -0700246 }
247
248 @Override
249 public void onAnimationCancel(Animator animation) {
John Reck0f602f32011-07-07 15:38:43 -0700250 }
251 };
252
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 */
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
John Reckef654f12011-07-12 16:42:08 -0700269 if (!isEditingUrl() && !wantsToBeVisible()) {
John Reck0f602f32011-07-07 15:38:43 -0700270 if (mUseQuickControls) {
Michael Kolbe8a82332012-04-25 14:14:26 -0700271 hide();
John Reckbc82ec92012-04-19 13:12:35 -0700272 } else {
273 mBaseUi.showTitleBarForDuration();
John Reck0f602f32011-07-07 15:38:43 -0700274 }
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);
Michael Kolbe8a82332012-04-25 14:14:26 -0700284 if (mUseQuickControls && !isEditingUrl()) {
285 setShowProgressOnly(true);
286 }
John Reck0f602f32011-07-07 15:38:43 -0700287 if (!mShowing) {
John Reck0f602f32011-07-07 15:38:43 -0700288 show();
289 }
290 }
291 }
292
293 public int getEmbeddedHeight() {
John Reck2711fab2012-05-18 21:38:59 -0700294 if (mUseQuickControls || mIsFixedTitleBar) return 0;
295 return calculateEmbeddedHeight();
296 }
297
298 private int calculateEmbeddedHeight() {
John Reck0f602f32011-07-07 15:38:43 -0700299 int height = mNavBar.getHeight();
Ben Murdochd51bb572011-08-17 20:42:02 +0100300 if (mAutoLogin != null && mAutoLogin.getVisibility() == View.VISIBLE) {
John Reck0f602f32011-07-07 15:38:43 -0700301 height += mAutoLogin.getHeight();
302 }
303 return height;
304 }
305
306 public void updateAutoLogin(Tab tab, boolean animate) {
Ben Murdochd51bb572011-08-17 20:42:02 +0100307 if (mAutoLogin == null) {
308 if (tab.getDeviceAccountLogin() == null) {
309 return;
310 }
311 inflateAutoLoginBar();
312 }
John Reck0f602f32011-07-07 15:38:43 -0700313 mAutoLogin.updateAutoLogin(tab, animate);
314 }
315
316 public void showAutoLogin(boolean animate) {
317 if (mUseQuickControls) {
318 mBaseUi.showTitleBar();
319 }
Ben Murdochd51bb572011-08-17 20:42:02 +0100320 if (mAutoLogin == null) {
321 inflateAutoLoginBar();
322 }
John Reck0f602f32011-07-07 15:38:43 -0700323 mAutoLogin.setVisibility(View.VISIBLE);
324 if (animate) {
325 mAutoLogin.startAnimation(AnimationUtils.loadAnimation(
326 getContext(), R.anim.autologin_enter));
327 }
328 }
329
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
John Reckef654f12011-07-12 16:42:08 -0700362 public boolean wantsToBeVisible() {
363 return inAutoLogin()
Ben Murdochd51bb572011-08-17 20:42:02 +0100364 || (mSnapshotBar != null && mSnapshotBar.getVisibility() == View.VISIBLE
John Reckef654f12011-07-12 16:42:08 -0700365 && mSnapshotBar.isAnimating());
366 }
367
368 private boolean inAutoLogin() {
Ben Murdochd51bb572011-08-17 20:42:02 +0100369 return mAutoLogin != null && mAutoLogin.getVisibility() == View.VISIBLE;
John Reck0f602f32011-07-07 15:38:43 -0700370 }
371
372 public boolean isEditingUrl() {
373 return mNavBar.isEditingUrl();
374 }
375
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
385 public PageProgressView getProgressView() {
386 return mProgress;
387 }
388
389 public NavigationBarBase getNavigationBar() {
390 return mNavBar;
391 }
392
393 public boolean useQuickControls() {
394 return mUseQuickControls;
395 }
396
397 public boolean isInLoad() {
398 return mInLoad;
399 }
400
401 private ViewGroup.LayoutParams makeLayoutParams() {
Michael Kolb4923c222012-04-02 16:18:36 -0700402 return new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
403 LayoutParams.WRAP_CONTENT);
John Reck0f602f32011-07-07 15:38:43 -0700404 }
405
406 @Override
407 public View focusSearch(View focused, int dir) {
John Reckfcb60952012-05-30 09:45:28 -0700408 WebView web = getCurrentWebView();
John Reckd70419a2012-05-30 16:09:17 -0700409 if (FOCUS_DOWN == dir && hasFocus() && web != null
John Reckfcb60952012-05-30 09:45:28 -0700410 && web.hasFocusable() && web.getParent() != null) {
411 return web;
John Reck0f602f32011-07-07 15:38:43 -0700412 }
413 return super.focusSearch(focused, dir);
414 }
415
John Reckef654f12011-07-12 16:42:08 -0700416 public void onTabDataChanged(Tab tab) {
Ben Murdochd51bb572011-08-17 20:42:02 +0100417 if (mSnapshotBar != null) {
418 mSnapshotBar.onTabDataChanged(tab);
419 }
420
John Reckef654f12011-07-12 16:42:08 -0700421 if (tab.isSnapshot()) {
Ben Murdochd51bb572011-08-17 20:42:02 +0100422 inflateSnapshotBar();
John Reckef654f12011-07-12 16:42:08 -0700423 mSnapshotBar.setVisibility(VISIBLE);
424 mNavBar.setVisibility(GONE);
425 } else {
Ben Murdochd51bb572011-08-17 20:42:02 +0100426 if (mSnapshotBar != null) {
427 mSnapshotBar.setVisibility(GONE);
428 }
John Reckef654f12011-07-12 16:42:08 -0700429 mNavBar.setVisibility(VISIBLE);
430 }
431 }
432
Michael Kolb4923c222012-04-02 16:18:36 -0700433 public void onScrollChanged() {
John Reck2711fab2012-05-18 21:38:59 -0700434 if (!mShowing && !mIsFixedTitleBar) {
Michael Kolb4923c222012-04-02 16:18:36 -0700435 setTranslationY(getVisibleTitleHeight() - getEmbeddedHeight());
436 }
437 }
438
John Reck0f602f32011-07-07 15:38:43 -0700439}