blob: 479b62ebfb6cf4f837da23bae07a5f59c33548bb [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;
48 private FrameLayout mParent;
49 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;
61
62 public TitleBar(Context context, UiController controller, BaseUi ui,
63 FrameLayout parent) {
64 super(context, null);
65 mUiController = controller;
66 mBaseUi = ui;
67 mParent = parent;
68 initLayout(context);
Michael Kolb4923c222012-04-02 16:18:36 -070069 mParent.addView(this, makeLayoutParams());
John Reck0f602f32011-07-07 15:38:43 -070070 }
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);
John Reck0f602f32011-07-07 15:38:43 -070076 mNavBar = (NavigationBarBase) findViewById(R.id.taburlbar);
77 mNavBar.setTitleBar(this);
Ben Murdochd51bb572011-08-17 20:42:02 +010078 }
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();
John Reckef654f12011-07-12 16:42:08 -070097 mSnapshotBar.setTitleBar(this);
John Reck0f602f32011-07-07 15:38:43 -070098 }
99
Michael Kolb57059a82012-04-30 14:32:03 -0700100 @Override
101 protected void onConfigurationChanged(Configuration config) {
102 super.onConfigurationChanged(config);
103 if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
104 if (!mContext.getResources().getBoolean(R.bool.hide_title)) {
105 show();
106 }
107 }
108 }
109
John Reck0f602f32011-07-07 15:38:43 -0700110 public BaseUi getUi() {
111 return mBaseUi;
112 }
113
114 public UiController getUiController() {
115 return mUiController;
116 }
117
118 public void setUseQuickControls(boolean use) {
119 mUseQuickControls = use;
Michael Kolb4923c222012-04-02 16:18:36 -0700120 if (use) {
121 this.setVisibility(View.GONE);
122 } else {
123 this.setVisibility(View.VISIBLE);
124 }
John Reck0f602f32011-07-07 15:38:43 -0700125 }
126
127 void setShowProgressOnly(boolean progress) {
John Reckef654f12011-07-12 16:42:08 -0700128 if (progress && !wantsToBeVisible()) {
John Reck0f602f32011-07-07 15:38:43 -0700129 mNavBar.setVisibility(View.GONE);
130 } else {
131 mNavBar.setVisibility(View.VISIBLE);
132 }
133 }
134
135 void setSkipTitleBarAnimations(boolean skip) {
136 mSkipTitleBarAnimations = skip;
137 }
138
139 void setupTitleBarAnimator(Animator animator) {
140 Resources res = mContext.getResources();
141 int duration = res.getInteger(R.integer.titlebar_animation_duration);
142 animator.setInterpolator(new DecelerateInterpolator(
143 ANIM_TITLEBAR_DECELERATE));
144 animator.setDuration(duration);
145 }
146
147 void show() {
148 if (mUseQuickControls) {
Michael Kolb4923c222012-04-02 16:18:36 -0700149 this.setVisibility(View.VISIBLE);
150 this.setTranslationY(0);
John Reck0f602f32011-07-07 15:38:43 -0700151 } else {
152 if (!mSkipTitleBarAnimations) {
153 cancelTitleBarAnimation(false);
154 int visibleHeight = getVisibleTitleHeight();
155 float startPos = (-getEmbeddedHeight() + visibleHeight);
156 if (getTranslationY() != 0) {
157 startPos = Math.max(startPos, getTranslationY());
158 }
159 mTitleBarAnimator = ObjectAnimator.ofFloat(this,
160 "translationY",
161 startPos, 0);
162 setupTitleBarAnimator(mTitleBarAnimator);
163 mTitleBarAnimator.start();
164 }
John Reck0f602f32011-07-07 15:38:43 -0700165 }
166 mShowing = true;
167 }
168
169 void hide() {
170 if (mUseQuickControls) {
Michael Kolb4923c222012-04-02 16:18:36 -0700171 this.setVisibility(View.GONE);
John Reck0f602f32011-07-07 15:38:43 -0700172 } else {
Michael Kolb57059a82012-04-30 14:32:03 -0700173 if (!mContext.getResources().getBoolean(R.bool.hide_title)) return;
John Reck0f602f32011-07-07 15:38:43 -0700174 if (!mSkipTitleBarAnimations) {
175 cancelTitleBarAnimation(false);
176 int visibleHeight = getVisibleTitleHeight();
177 mTitleBarAnimator = ObjectAnimator.ofFloat(this,
178 "translationY", getTranslationY(),
179 (-getEmbeddedHeight() + visibleHeight));
180 mTitleBarAnimator.addListener(mHideTileBarAnimatorListener);
181 setupTitleBarAnimator(mTitleBarAnimator);
182 mTitleBarAnimator.start();
183 } else {
Michael Kolb4923c222012-04-02 16:18:36 -0700184 onScrollChanged();
John Reck0f602f32011-07-07 15:38:43 -0700185 }
186 }
187 mShowing = false;
188 }
189
190 boolean isShowing() {
191 return mShowing;
192 }
193
194 void cancelTitleBarAnimation(boolean reset) {
195 if (mTitleBarAnimator != null) {
196 mTitleBarAnimator.cancel();
197 mTitleBarAnimator = null;
198 }
199 if (reset) {
200 setTranslationY(0);
201 }
202 }
203
204 private AnimatorListener mHideTileBarAnimatorListener = new AnimatorListener() {
205
John Reck0f602f32011-07-07 15:38:43 -0700206 @Override
207 public void onAnimationStart(Animator animation) {
John Reck0f602f32011-07-07 15:38:43 -0700208 }
209
210 @Override
211 public void onAnimationRepeat(Animator animation) {
212 }
213
214 @Override
215 public void onAnimationEnd(Animator animation) {
Michael Kolb4923c222012-04-02 16:18:36 -0700216 // update position
217 onScrollChanged();
John Reck0f602f32011-07-07 15:38:43 -0700218 }
219
220 @Override
221 public void onAnimationCancel(Animator animation) {
John Reck0f602f32011-07-07 15:38:43 -0700222 }
223 };
224
225 private int getVisibleTitleHeight() {
226 Tab tab = mBaseUi.getActiveTab();
227 WebView webview = tab != null ? tab.getWebView() : null;
228 return webview != null ? webview.getVisibleTitleHeight() : 0;
229 }
230
231 /**
232 * Update the progress, from 0 to 100.
233 */
234 public void setProgress(int newProgress) {
235 if (newProgress >= PROGRESS_MAX) {
236 mProgress.setProgress(PageProgressView.MAX_PROGRESS);
237 mProgress.setVisibility(View.GONE);
238 mInLoad = false;
239 mNavBar.onProgressStopped();
240 // check if needs to be hidden
John Reckef654f12011-07-12 16:42:08 -0700241 if (!isEditingUrl() && !wantsToBeVisible()) {
John Reck0f602f32011-07-07 15:38:43 -0700242 if (mUseQuickControls) {
Michael Kolbe8a82332012-04-25 14:14:26 -0700243 hide();
John Reckbc82ec92012-04-19 13:12:35 -0700244 } else {
245 mBaseUi.showTitleBarForDuration();
John Reck0f602f32011-07-07 15:38:43 -0700246 }
247 }
248 } else {
249 if (!mInLoad) {
250 mProgress.setVisibility(View.VISIBLE);
251 mInLoad = true;
252 mNavBar.onProgressStarted();
253 }
254 mProgress.setProgress(newProgress * PageProgressView.MAX_PROGRESS
255 / PROGRESS_MAX);
Michael Kolbe8a82332012-04-25 14:14:26 -0700256 if (mUseQuickControls && !isEditingUrl()) {
257 setShowProgressOnly(true);
258 }
John Reck0f602f32011-07-07 15:38:43 -0700259 if (!mShowing) {
John Reck0f602f32011-07-07 15:38:43 -0700260 show();
261 }
262 }
263 }
264
265 public int getEmbeddedHeight() {
Michael Kolb4923c222012-04-02 16:18:36 -0700266 if (mUseQuickControls) return 0;
John Reck0f602f32011-07-07 15:38:43 -0700267 int height = mNavBar.getHeight();
Ben Murdochd51bb572011-08-17 20:42:02 +0100268 if (mAutoLogin != null && mAutoLogin.getVisibility() == View.VISIBLE) {
John Reck0f602f32011-07-07 15:38:43 -0700269 height += mAutoLogin.getHeight();
270 }
271 return height;
272 }
273
274 public void updateAutoLogin(Tab tab, boolean animate) {
Ben Murdochd51bb572011-08-17 20:42:02 +0100275 if (mAutoLogin == null) {
276 if (tab.getDeviceAccountLogin() == null) {
277 return;
278 }
279 inflateAutoLoginBar();
280 }
John Reck0f602f32011-07-07 15:38:43 -0700281 mAutoLogin.updateAutoLogin(tab, animate);
282 }
283
284 public void showAutoLogin(boolean animate) {
285 if (mUseQuickControls) {
286 mBaseUi.showTitleBar();
287 }
Ben Murdochd51bb572011-08-17 20:42:02 +0100288 if (mAutoLogin == null) {
289 inflateAutoLoginBar();
290 }
John Reck0f602f32011-07-07 15:38:43 -0700291 mAutoLogin.setVisibility(View.VISIBLE);
292 if (animate) {
293 mAutoLogin.startAnimation(AnimationUtils.loadAnimation(
294 getContext(), R.anim.autologin_enter));
295 }
296 }
297
298 public void hideAutoLogin(boolean animate) {
299 if (mUseQuickControls) {
300 mBaseUi.hideTitleBar();
301 mAutoLogin.setVisibility(View.GONE);
302 mBaseUi.refreshWebView();
303 } else {
304 if (animate) {
305 Animation anim = AnimationUtils.loadAnimation(getContext(),
306 R.anim.autologin_exit);
307 anim.setAnimationListener(new AnimationListener() {
308 @Override
309 public void onAnimationEnd(Animation a) {
310 mAutoLogin.setVisibility(View.GONE);
311 mBaseUi.refreshWebView();
312 }
313
314 @Override
315 public void onAnimationStart(Animation a) {
316 }
317
318 @Override
319 public void onAnimationRepeat(Animation a) {
320 }
321 });
322 mAutoLogin.startAnimation(anim);
323 } else if (mAutoLogin.getAnimation() == null) {
324 mAutoLogin.setVisibility(View.GONE);
325 mBaseUi.refreshWebView();
326 }
327 }
328 }
329
John Reckef654f12011-07-12 16:42:08 -0700330 public boolean wantsToBeVisible() {
331 return inAutoLogin()
Ben Murdochd51bb572011-08-17 20:42:02 +0100332 || (mSnapshotBar != null && mSnapshotBar.getVisibility() == View.VISIBLE
John Reckef654f12011-07-12 16:42:08 -0700333 && mSnapshotBar.isAnimating());
334 }
335
336 private boolean inAutoLogin() {
Ben Murdochd51bb572011-08-17 20:42:02 +0100337 return mAutoLogin != null && mAutoLogin.getVisibility() == View.VISIBLE;
John Reck0f602f32011-07-07 15:38:43 -0700338 }
339
340 public boolean isEditingUrl() {
341 return mNavBar.isEditingUrl();
342 }
343
344 public WebView getCurrentWebView() {
345 Tab t = mBaseUi.getActiveTab();
346 if (t != null) {
347 return t.getWebView();
348 } else {
349 return null;
350 }
351 }
352
353 public PageProgressView getProgressView() {
354 return mProgress;
355 }
356
357 public NavigationBarBase getNavigationBar() {
358 return mNavBar;
359 }
360
361 public boolean useQuickControls() {
362 return mUseQuickControls;
363 }
364
365 public boolean isInLoad() {
366 return mInLoad;
367 }
368
369 private ViewGroup.LayoutParams makeLayoutParams() {
Michael Kolb4923c222012-04-02 16:18:36 -0700370 return new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
371 LayoutParams.WRAP_CONTENT);
John Reck0f602f32011-07-07 15:38:43 -0700372 }
373
374 @Override
375 public View focusSearch(View focused, int dir) {
376 if (FOCUS_DOWN == dir && hasFocus()) {
377 return getCurrentWebView();
378 }
379 return super.focusSearch(focused, dir);
380 }
381
John Reckef654f12011-07-12 16:42:08 -0700382 public void onTabDataChanged(Tab tab) {
Ben Murdochd51bb572011-08-17 20:42:02 +0100383 if (mSnapshotBar != null) {
384 mSnapshotBar.onTabDataChanged(tab);
385 }
386
John Reckef654f12011-07-12 16:42:08 -0700387 if (tab.isSnapshot()) {
Ben Murdochd51bb572011-08-17 20:42:02 +0100388 inflateSnapshotBar();
John Reckef654f12011-07-12 16:42:08 -0700389 mSnapshotBar.setVisibility(VISIBLE);
390 mNavBar.setVisibility(GONE);
391 } else {
Ben Murdochd51bb572011-08-17 20:42:02 +0100392 if (mSnapshotBar != null) {
393 mSnapshotBar.setVisibility(GONE);
394 }
John Reckef654f12011-07-12 16:42:08 -0700395 mNavBar.setVisibility(VISIBLE);
396 }
397 }
398
Michael Kolb4923c222012-04-02 16:18:36 -0700399 public void onScrollChanged() {
400 if (!mShowing) {
401 setTranslationY(getVisibleTitleHeight() - getEmbeddedHeight());
402 }
403 }
404
John Reck0f602f32011-07-07 15:38:43 -0700405}