blob: 5d5f1e3d2a10bc156925ed8d050df9ca9c3d86bd [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
Bijan Amirzada41242f22014-03-21 12:12:18 -070017package com.android.browser;
John Reck0f602f32011-07-07 15:38:43 -070018
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;
Panos Thomas752ce592014-10-16 13:00:35 -070025import android.graphics.Rect;
John Reck0f602f32011-07-07 15:38:43 -070026import android.view.LayoutInflater;
27import android.view.View;
28import android.view.ViewGroup;
Ben Murdochd51bb572011-08-17 20:42:02 +010029import android.view.ViewStub;
John Reck1cc1d1d2012-09-04 18:13:51 -070030import android.view.accessibility.AccessibilityManager;
John Reck0f602f32011-07-07 15:38:43 -070031import android.view.animation.Animation;
32import android.view.animation.Animation.AnimationListener;
33import android.view.animation.AnimationUtils;
34import android.view.animation.DecelerateInterpolator;
Bijan Amirzada9b1e9882014-02-26 17:15:46 -080035import org.codeaurora.swe.WebView;
36
Bijan Amirzada41242f22014-03-21 12:12:18 -070037import com.android.browser.R;
Bijan Amirzada9b1e9882014-02-26 17:15:46 -080038
John Reck0f602f32011-07-07 15:38:43 -070039import android.widget.FrameLayout;
40import android.widget.RelativeLayout;
41
42
43/**
44 * Base class for a title bar used by the browser.
45 */
46public class TitleBar extends RelativeLayout {
47
48 private static final int PROGRESS_MAX = 100;
49 private static final float ANIM_TITLEBAR_DECELERATE = 2.5f;
50
51 private UiController mUiController;
52 private BaseUi mBaseUi;
John Reck2711fab2012-05-18 21:38:59 -070053 private FrameLayout mContentView;
John Reck0f602f32011-07-07 15:38:43 -070054 private PageProgressView mProgress;
John Reck1cc1d1d2012-09-04 18:13:51 -070055 private AccessibilityManager mAccessibilityManager;
John Reck0f602f32011-07-07 15:38:43 -070056
John Reck0f602f32011-07-07 15:38:43 -070057 private NavigationBarBase mNavBar;
John Reckef654f12011-07-12 16:42:08 -070058 private SnapshotBar mSnapshotBar;
John Reck0f602f32011-07-07 15:38:43 -070059
60 //state
61 private boolean mShowing;
62 private boolean mInLoad;
63 private boolean mSkipTitleBarAnimations;
64 private Animator mTitleBarAnimator;
John Reck2711fab2012-05-18 21:38:59 -070065 private boolean mIsFixedTitleBar;
John Reck0f602f32011-07-07 15:38:43 -070066
67 public TitleBar(Context context, UiController controller, BaseUi ui,
John Reck2711fab2012-05-18 21:38:59 -070068 FrameLayout contentView) {
John Reck0f602f32011-07-07 15:38:43 -070069 super(context, null);
70 mUiController = controller;
71 mBaseUi = ui;
John Reck2711fab2012-05-18 21:38:59 -070072 mContentView = contentView;
John Reck1cc1d1d2012-09-04 18:13:51 -070073 mAccessibilityManager = (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
John Reck0f602f32011-07-07 15:38:43 -070074 initLayout(context);
John Reck0f9aaeb2012-05-23 14:40:19 -070075 setFixedTitleBar();
John Reck0f602f32011-07-07 15:38:43 -070076 }
77
78 private void initLayout(Context context) {
79 LayoutInflater factory = LayoutInflater.from(context);
80 factory.inflate(R.layout.title_bar, this);
81 mProgress = (PageProgressView) findViewById(R.id.progress);
John Reck0f602f32011-07-07 15:38:43 -070082 mNavBar = (NavigationBarBase) findViewById(R.id.taburlbar);
83 mNavBar.setTitleBar(this);
Ben Murdochd51bb572011-08-17 20:42:02 +010084 }
85
Ben Murdochd51bb572011-08-17 20:42:02 +010086 private void inflateSnapshotBar() {
87 if (mSnapshotBar != null) {
88 return;
89 }
90
91 ViewStub stub = (ViewStub) findViewById(R.id.snapshotbar_stub);
92 mSnapshotBar = (SnapshotBar) stub.inflate();
John Reckef654f12011-07-12 16:42:08 -070093 mSnapshotBar.setTitleBar(this);
John Reck0f602f32011-07-07 15:38:43 -070094 }
95
Michael Kolb57059a82012-04-30 14:32:03 -070096 @Override
97 protected void onConfigurationChanged(Configuration config) {
98 super.onConfigurationChanged(config);
John Reck0f9aaeb2012-05-23 14:40:19 -070099 setFixedTitleBar();
John Reck2711fab2012-05-18 21:38:59 -0700100 }
101
102 @Override
103 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
104 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Vivek Sekhar8a660782014-10-27 17:00:53 -0700105 mBaseUi.setContentViewMarginTop(0);
John Reck2711fab2012-05-18 21:38:59 -0700106 }
107
John Reck0f9aaeb2012-05-23 14:40:19 -0700108 private void setFixedTitleBar() {
Vivek Sekhar3bec6a32014-10-22 17:03:42 -0700109 boolean isFixed = !getContext().getResources().getBoolean(R.bool.hide_title);
Tarun Nainani8eb00912014-07-17 12:28:32 -0700110
John Reck1cc1d1d2012-09-04 18:13:51 -0700111 isFixed |= mAccessibilityManager.isEnabled();
John Reck2711fab2012-05-18 21:38:59 -0700112 // If getParent() returns null, we are initializing
113 ViewGroup parent = (ViewGroup)getParent();
114 if (mIsFixedTitleBar == isFixed && parent != null) return;
115 mIsFixedTitleBar = isFixed;
116 setSkipTitleBarAnimations(true);
117 show();
118 setSkipTitleBarAnimations(false);
119 if (parent != null) {
120 parent.removeView(this);
121 }
Vivek Sekhar8a660782014-10-27 17:00:53 -0700122 mContentView.addView(this, makeLayoutParams());
123 mBaseUi.setContentViewMarginTop(0);
Michael Kolb57059a82012-04-30 14:32:03 -0700124 }
125
John Reck0f602f32011-07-07 15:38:43 -0700126 public BaseUi getUi() {
127 return mBaseUi;
128 }
129
130 public UiController getUiController() {
131 return mUiController;
132 }
133
John Reck0f602f32011-07-07 15:38:43 -0700134 void setShowProgressOnly(boolean progress) {
John Reckef654f12011-07-12 16:42:08 -0700135 if (progress && !wantsToBeVisible()) {
John Reck0f602f32011-07-07 15:38:43 -0700136 mNavBar.setVisibility(View.GONE);
137 } else {
138 mNavBar.setVisibility(View.VISIBLE);
139 }
140 }
141
142 void setSkipTitleBarAnimations(boolean skip) {
143 mSkipTitleBarAnimations = skip;
144 }
145
146 void setupTitleBarAnimator(Animator animator) {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800147 Resources res = getContext().getResources();
John Reck0f602f32011-07-07 15:38:43 -0700148 int duration = res.getInteger(R.integer.titlebar_animation_duration);
149 animator.setInterpolator(new DecelerateInterpolator(
150 ANIM_TITLEBAR_DECELERATE));
151 animator.setDuration(duration);
152 }
153
Tarun Nainani8eb00912014-07-17 12:28:32 -0700154 //Disable stock autohide behavior in favor of top controls
155 private static final boolean bOldStyleAutoHideDisabled = true;
John Reck0f602f32011-07-07 15:38:43 -0700156 void show() {
John Reck2711fab2012-05-18 21:38:59 -0700157 cancelTitleBarAnimation(false);
Vivek Sekhar3bec6a32014-10-22 17:03:42 -0700158 if (mSkipTitleBarAnimations) {
Michael Kolb4923c222012-04-02 16:18:36 -0700159 this.setVisibility(View.VISIBLE);
160 this.setTranslationY(0);
Vivek Sekhar8a660782014-10-27 17:00:53 -0700161 // reaffirm top-controls
162 if (isFixed() || isInLoad())
163 showTopControls();
164 else
165 enableTopControls();
Tarun Nainani8eb00912014-07-17 12:28:32 -0700166 } else if (!bOldStyleAutoHideDisabled) {
John Reck2711fab2012-05-18 21:38:59 -0700167 int visibleHeight = getVisibleTitleHeight();
168 float startPos = (-getEmbeddedHeight() + visibleHeight);
169 if (getTranslationY() != 0) {
170 startPos = Math.max(startPos, getTranslationY());
John Reck0f602f32011-07-07 15:38:43 -0700171 }
John Reck2711fab2012-05-18 21:38:59 -0700172 mTitleBarAnimator = ObjectAnimator.ofFloat(this,
173 "translationY",
174 startPos, 0);
175 setupTitleBarAnimator(mTitleBarAnimator);
176 mTitleBarAnimator.start();
John Reck0f602f32011-07-07 15:38:43 -0700177 }
Tarun Nainani8eb00912014-07-17 12:28:32 -0700178
John Reck0f602f32011-07-07 15:38:43 -0700179 mShowing = true;
180 }
181
182 void hide() {
Vivek Sekhar3bec6a32014-10-22 17:03:42 -0700183 if (mIsFixedTitleBar || bOldStyleAutoHideDisabled) return;
184 if (!mSkipTitleBarAnimations) {
185 cancelTitleBarAnimation(false);
186 int visibleHeight = getVisibleTitleHeight();
187 mTitleBarAnimator = ObjectAnimator.ofFloat(this,
188 "translationY", getTranslationY(),
189 (-getEmbeddedHeight() + visibleHeight));
190 mTitleBarAnimator.addListener(mHideTileBarAnimatorListener);
191 setupTitleBarAnimator(mTitleBarAnimator);
192 mTitleBarAnimator.start();
John Reck0f602f32011-07-07 15:38:43 -0700193 } else {
Vivek Sekhar3bec6a32014-10-22 17:03:42 -0700194 onScrollChanged();
John Reck0f602f32011-07-07 15:38:43 -0700195 }
196 mShowing = false;
197 }
198
199 boolean isShowing() {
200 return mShowing;
201 }
202
203 void cancelTitleBarAnimation(boolean reset) {
204 if (mTitleBarAnimator != null) {
205 mTitleBarAnimator.cancel();
206 mTitleBarAnimator = null;
207 }
208 if (reset) {
209 setTranslationY(0);
210 }
211 }
212
213 private AnimatorListener mHideTileBarAnimatorListener = new AnimatorListener() {
214
John Reck0f602f32011-07-07 15:38:43 -0700215 @Override
216 public void onAnimationStart(Animator animation) {
John Reck0f602f32011-07-07 15:38:43 -0700217 }
218
219 @Override
220 public void onAnimationRepeat(Animator animation) {
221 }
222
223 @Override
224 public void onAnimationEnd(Animator animation) {
Michael Kolb4923c222012-04-02 16:18:36 -0700225 // update position
226 onScrollChanged();
John Reck0f602f32011-07-07 15:38:43 -0700227 }
228
229 @Override
230 public void onAnimationCancel(Animator animation) {
John Reck0f602f32011-07-07 15:38:43 -0700231 }
232 };
233
234 private int getVisibleTitleHeight() {
235 Tab tab = mBaseUi.getActiveTab();
236 WebView webview = tab != null ? tab.getWebView() : null;
237 return webview != null ? webview.getVisibleTitleHeight() : 0;
238 }
239
Tarun Nainani8eb00912014-07-17 12:28:32 -0700240 private void hideTopControls() {
241 Tab tab = mBaseUi.getActiveTab();
242 WebView view = tab != null ? tab.getWebView() : null;
243 if (view != null)
244 view.updateTopControls(true, false, true);
245 }
246
247 private void showTopControls() {
248 Tab tab = mBaseUi.getActiveTab();
249 WebView view = tab != null ? tab.getWebView() : null;
250 if (view != null)
251 view.updateTopControls(false, true, true);
252 }
253
254 private void enableTopControls() {
255 Tab tab = mBaseUi.getActiveTab();
256 WebView view = tab != null ? tab.getWebView() : null;
257 if (view != null)
258 view.updateTopControls(true, true, true);
259 }
260
261
John Reck0f602f32011-07-07 15:38:43 -0700262 /**
263 * Update the progress, from 0 to 100.
264 */
265 public void setProgress(int newProgress) {
Tarun Nainani8eb00912014-07-17 12:28:32 -0700266 Tab tab = mBaseUi.getActiveTab();
267 WebView view = tab != null ? tab.getWebView() : null;
268
John Reck0f602f32011-07-07 15:38:43 -0700269 if (newProgress >= PROGRESS_MAX) {
270 mProgress.setProgress(PageProgressView.MAX_PROGRESS);
271 mProgress.setVisibility(View.GONE);
272 mInLoad = false;
273 mNavBar.onProgressStopped();
274 // check if needs to be hidden
John Reckef654f12011-07-12 16:42:08 -0700275 if (!isEditingUrl() && !wantsToBeVisible()) {
Vivek Sekhar3bec6a32014-10-22 17:03:42 -0700276 mBaseUi.showTitleBarForDuration();
John Reck0f602f32011-07-07 15:38:43 -0700277 }
Tarun Nainani8eb00912014-07-17 12:28:32 -0700278
279 //onPageFinished
Vivek Sekhar8a660782014-10-27 17:00:53 -0700280 if (isFixed())
281 showTopControls();
282 else
283 enableTopControls();
Tarun Nainani8eb00912014-07-17 12:28:32 -0700284
John Reck0f602f32011-07-07 15:38:43 -0700285 } else {
286 if (!mInLoad) {
287 mProgress.setVisibility(View.VISIBLE);
288 mInLoad = true;
289 mNavBar.onProgressStarted();
Tarun Nainani8eb00912014-07-17 12:28:32 -0700290
291 //onPageStarted
Vivek Sekhar3bec6a32014-10-22 17:03:42 -0700292 showTopControls();
John Reck0f602f32011-07-07 15:38:43 -0700293 }
294 mProgress.setProgress(newProgress * PageProgressView.MAX_PROGRESS
295 / PROGRESS_MAX);
296 if (!mShowing) {
John Reck0f602f32011-07-07 15:38:43 -0700297 show();
298 }
299 }
300 }
301
302 public int getEmbeddedHeight() {
Vivek Sekhar3bec6a32014-10-22 17:03:42 -0700303 if (mIsFixedTitleBar) return 0;
John Reck2711fab2012-05-18 21:38:59 -0700304 return calculateEmbeddedHeight();
305 }
306
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800307 public boolean isFixed() {
308 return mIsFixedTitleBar;
309 }
310
311 int calculateEmbeddedHeight() {
John Reck0f602f32011-07-07 15:38:43 -0700312 int height = mNavBar.getHeight();
John Reck0f602f32011-07-07 15:38:43 -0700313 return height;
314 }
315
John Reckef654f12011-07-12 16:42:08 -0700316 public boolean wantsToBeVisible() {
Bijan Amirzada289e1e62014-04-15 11:53:48 -0700317 return (mSnapshotBar != null && mSnapshotBar.getVisibility() == View.VISIBLE
John Reckef654f12011-07-12 16:42:08 -0700318 && mSnapshotBar.isAnimating());
319 }
320
John Reck0f602f32011-07-07 15:38:43 -0700321 public boolean isEditingUrl() {
322 return mNavBar.isEditingUrl();
323 }
324
325 public WebView getCurrentWebView() {
326 Tab t = mBaseUi.getActiveTab();
327 if (t != null) {
328 return t.getWebView();
329 } else {
330 return null;
331 }
332 }
333
334 public PageProgressView getProgressView() {
335 return mProgress;
336 }
337
338 public NavigationBarBase getNavigationBar() {
339 return mNavBar;
340 }
341
John Reck0f602f32011-07-07 15:38:43 -0700342 public boolean isInLoad() {
343 return mInLoad;
344 }
345
346 private ViewGroup.LayoutParams makeLayoutParams() {
Michael Kolb4923c222012-04-02 16:18:36 -0700347 return new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
348 LayoutParams.WRAP_CONTENT);
John Reck0f602f32011-07-07 15:38:43 -0700349 }
350
351 @Override
Panos Thomas752ce592014-10-16 13:00:35 -0700352 public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
353 return mBaseUi.isCustomViewShowing() ? false :
354 super.requestFocus(direction, previouslyFocusedRect);
355 }
356
357 @Override
John Reck0f602f32011-07-07 15:38:43 -0700358 public View focusSearch(View focused, int dir) {
John Reckfcb60952012-05-30 09:45:28 -0700359 WebView web = getCurrentWebView();
John Reckd70419a2012-05-30 16:09:17 -0700360 if (FOCUS_DOWN == dir && hasFocus() && web != null
John Reckfcb60952012-05-30 09:45:28 -0700361 && web.hasFocusable() && web.getParent() != null) {
362 return web;
John Reck0f602f32011-07-07 15:38:43 -0700363 }
364 return super.focusSearch(focused, dir);
365 }
366
John Reckef654f12011-07-12 16:42:08 -0700367 public void onTabDataChanged(Tab tab) {
Ben Murdochd51bb572011-08-17 20:42:02 +0100368 if (mSnapshotBar != null) {
369 mSnapshotBar.onTabDataChanged(tab);
370 }
371
John Reckef654f12011-07-12 16:42:08 -0700372 if (tab.isSnapshot()) {
Ben Murdochd51bb572011-08-17 20:42:02 +0100373 inflateSnapshotBar();
John Reckef654f12011-07-12 16:42:08 -0700374 mSnapshotBar.setVisibility(VISIBLE);
375 mNavBar.setVisibility(GONE);
376 } else {
Ben Murdochd51bb572011-08-17 20:42:02 +0100377 if (mSnapshotBar != null) {
378 mSnapshotBar.setVisibility(GONE);
379 }
John Reckef654f12011-07-12 16:42:08 -0700380 mNavBar.setVisibility(VISIBLE);
381 }
382 }
383
Michael Kolb4923c222012-04-02 16:18:36 -0700384 public void onScrollChanged() {
John Reck2711fab2012-05-18 21:38:59 -0700385 if (!mShowing && !mIsFixedTitleBar) {
Michael Kolb4923c222012-04-02 16:18:36 -0700386 setTranslationY(getVisibleTitleHeight() - getEmbeddedHeight());
387 }
388 }
389
John Reck1cc1d1d2012-09-04 18:13:51 -0700390 public void onResume() {
391 setFixedTitleBar();
392 }
393
John Reck0f602f32011-07-07 15:38:43 -0700394}