blob: 490cc15b5d99b95fb0882e09cbc1b1138b5e136a [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
John Reck0f602f32011-07-07 15:38:43 -070037import android.widget.FrameLayout;
38import android.widget.RelativeLayout;
39
40
41/**
42 * Base class for a title bar used by the browser.
43 */
44public class TitleBar extends RelativeLayout {
45
46 private static final int PROGRESS_MAX = 100;
47 private static final float ANIM_TITLEBAR_DECELERATE = 2.5f;
48
49 private UiController mUiController;
50 private BaseUi mBaseUi;
John Reck2711fab2012-05-18 21:38:59 -070051 private FrameLayout mContentView;
John Reck0f602f32011-07-07 15:38:43 -070052 private PageProgressView mProgress;
John Reck1cc1d1d2012-09-04 18:13:51 -070053 private AccessibilityManager mAccessibilityManager;
John Reck0f602f32011-07-07 15:38:43 -070054
John Reck0f602f32011-07-07 15:38:43 -070055 private NavigationBarBase mNavBar;
John Reckef654f12011-07-12 16:42:08 -070056 private SnapshotBar mSnapshotBar;
John Reck0f602f32011-07-07 15:38:43 -070057
58 //state
59 private boolean mShowing;
60 private boolean mInLoad;
61 private boolean mSkipTitleBarAnimations;
62 private Animator mTitleBarAnimator;
John Reck2711fab2012-05-18 21:38:59 -070063 private boolean mIsFixedTitleBar;
John Reck0f602f32011-07-07 15:38:43 -070064
65 public TitleBar(Context context, UiController controller, BaseUi ui,
John Reck2711fab2012-05-18 21:38:59 -070066 FrameLayout contentView) {
John Reck0f602f32011-07-07 15:38:43 -070067 super(context, null);
68 mUiController = controller;
69 mBaseUi = ui;
John Reck2711fab2012-05-18 21:38:59 -070070 mContentView = contentView;
John Reck1cc1d1d2012-09-04 18:13:51 -070071 mAccessibilityManager = (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
John Reck0f602f32011-07-07 15:38:43 -070072 initLayout(context);
John Reck0f9aaeb2012-05-23 14:40:19 -070073 setFixedTitleBar();
John Reck0f602f32011-07-07 15:38:43 -070074 }
75
76 private void initLayout(Context context) {
77 LayoutInflater factory = LayoutInflater.from(context);
78 factory.inflate(R.layout.title_bar, this);
79 mProgress = (PageProgressView) findViewById(R.id.progress);
John Reck0f602f32011-07-07 15:38:43 -070080 mNavBar = (NavigationBarBase) findViewById(R.id.taburlbar);
81 mNavBar.setTitleBar(this);
Ben Murdochd51bb572011-08-17 20:42:02 +010082 }
83
Ben Murdochd51bb572011-08-17 20:42:02 +010084 private void inflateSnapshotBar() {
85 if (mSnapshotBar != null) {
86 return;
87 }
88
89 ViewStub stub = (ViewStub) findViewById(R.id.snapshotbar_stub);
90 mSnapshotBar = (SnapshotBar) stub.inflate();
John Reckef654f12011-07-12 16:42:08 -070091 mSnapshotBar.setTitleBar(this);
John Reck0f602f32011-07-07 15:38:43 -070092 }
93
Michael Kolb57059a82012-04-30 14:32:03 -070094 @Override
95 protected void onConfigurationChanged(Configuration config) {
96 super.onConfigurationChanged(config);
John Reck0f9aaeb2012-05-23 14:40:19 -070097 setFixedTitleBar();
John Reck2711fab2012-05-18 21:38:59 -070098 }
99
100 @Override
101 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
102 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Vivek Sekhar8a660782014-10-27 17:00:53 -0700103 mBaseUi.setContentViewMarginTop(0);
John Reck2711fab2012-05-18 21:38:59 -0700104 }
105
John Reck0f9aaeb2012-05-23 14:40:19 -0700106 private void setFixedTitleBar() {
Vivek Sekhar3bec6a32014-10-22 17:03:42 -0700107 boolean isFixed = !getContext().getResources().getBoolean(R.bool.hide_title);
Tarun Nainani8eb00912014-07-17 12:28:32 -0700108
Vivek Sekhar80572142014-12-01 10:54:22 -0800109 isFixed |= mAccessibilityManager.isEnabled() &&
110 mAccessibilityManager.isTouchExplorationEnabled();
John Reck2711fab2012-05-18 21:38:59 -0700111 // If getParent() returns null, we are initializing
112 ViewGroup parent = (ViewGroup)getParent();
113 if (mIsFixedTitleBar == isFixed && parent != null) return;
114 mIsFixedTitleBar = isFixed;
115 setSkipTitleBarAnimations(true);
116 show();
117 setSkipTitleBarAnimations(false);
118 if (parent != null) {
119 parent.removeView(this);
120 }
Vivek Sekhar8a660782014-10-27 17:00:53 -0700121 mContentView.addView(this, makeLayoutParams());
122 mBaseUi.setContentViewMarginTop(0);
Michael Kolb57059a82012-04-30 14:32:03 -0700123 }
124
John Reck0f602f32011-07-07 15:38:43 -0700125 public BaseUi getUi() {
126 return mBaseUi;
127 }
128
129 public UiController getUiController() {
130 return mUiController;
131 }
132
John Reck0f602f32011-07-07 15:38:43 -0700133 void setShowProgressOnly(boolean progress) {
John Reckef654f12011-07-12 16:42:08 -0700134 if (progress && !wantsToBeVisible()) {
John Reck0f602f32011-07-07 15:38:43 -0700135 mNavBar.setVisibility(View.GONE);
136 } else {
137 mNavBar.setVisibility(View.VISIBLE);
138 }
139 }
140
141 void setSkipTitleBarAnimations(boolean skip) {
142 mSkipTitleBarAnimations = skip;
143 }
144
145 void setupTitleBarAnimator(Animator animator) {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800146 Resources res = getContext().getResources();
John Reck0f602f32011-07-07 15:38:43 -0700147 int duration = res.getInteger(R.integer.titlebar_animation_duration);
148 animator.setInterpolator(new DecelerateInterpolator(
149 ANIM_TITLEBAR_DECELERATE));
150 animator.setDuration(duration);
151 }
152
Tarun Nainani8eb00912014-07-17 12:28:32 -0700153 //Disable stock autohide behavior in favor of top controls
154 private static final boolean bOldStyleAutoHideDisabled = true;
John Reck0f602f32011-07-07 15:38:43 -0700155 void show() {
John Reck2711fab2012-05-18 21:38:59 -0700156 cancelTitleBarAnimation(false);
Vivek Sekhar3bec6a32014-10-22 17:03:42 -0700157 if (mSkipTitleBarAnimations) {
Michael Kolb4923c222012-04-02 16:18:36 -0700158 this.setVisibility(View.VISIBLE);
159 this.setTranslationY(0);
Vivek Sekhar8a660782014-10-27 17:00:53 -0700160 // reaffirm top-controls
161 if (isFixed() || isInLoad())
162 showTopControls();
163 else
164 enableTopControls();
Tarun Nainani8eb00912014-07-17 12:28:32 -0700165 } else if (!bOldStyleAutoHideDisabled) {
John Reck2711fab2012-05-18 21:38:59 -0700166 int visibleHeight = getVisibleTitleHeight();
167 float startPos = (-getEmbeddedHeight() + visibleHeight);
168 if (getTranslationY() != 0) {
169 startPos = Math.max(startPos, getTranslationY());
John Reck0f602f32011-07-07 15:38:43 -0700170 }
John Reck2711fab2012-05-18 21:38:59 -0700171 mTitleBarAnimator = ObjectAnimator.ofFloat(this,
172 "translationY",
173 startPos, 0);
174 setupTitleBarAnimator(mTitleBarAnimator);
175 mTitleBarAnimator.start();
John Reck0f602f32011-07-07 15:38:43 -0700176 }
Tarun Nainani8eb00912014-07-17 12:28:32 -0700177
John Reck0f602f32011-07-07 15:38:43 -0700178 mShowing = true;
179 }
180
181 void hide() {
Vivek Sekhar3bec6a32014-10-22 17:03:42 -0700182 if (mIsFixedTitleBar || bOldStyleAutoHideDisabled) return;
183 if (!mSkipTitleBarAnimations) {
184 cancelTitleBarAnimation(false);
185 int visibleHeight = getVisibleTitleHeight();
186 mTitleBarAnimator = ObjectAnimator.ofFloat(this,
187 "translationY", getTranslationY(),
188 (-getEmbeddedHeight() + visibleHeight));
189 mTitleBarAnimator.addListener(mHideTileBarAnimatorListener);
190 setupTitleBarAnimator(mTitleBarAnimator);
191 mTitleBarAnimator.start();
John Reck0f602f32011-07-07 15:38:43 -0700192 } else {
Vivek Sekhar3bec6a32014-10-22 17:03:42 -0700193 onScrollChanged();
John Reck0f602f32011-07-07 15:38:43 -0700194 }
195 mShowing = false;
196 }
197
198 boolean isShowing() {
199 return mShowing;
200 }
201
202 void cancelTitleBarAnimation(boolean reset) {
203 if (mTitleBarAnimator != null) {
204 mTitleBarAnimator.cancel();
205 mTitleBarAnimator = null;
206 }
207 if (reset) {
208 setTranslationY(0);
209 }
210 }
211
212 private AnimatorListener mHideTileBarAnimatorListener = new AnimatorListener() {
213
John Reck0f602f32011-07-07 15:38:43 -0700214 @Override
215 public void onAnimationStart(Animator animation) {
John Reck0f602f32011-07-07 15:38:43 -0700216 }
217
218 @Override
219 public void onAnimationRepeat(Animator animation) {
220 }
221
222 @Override
223 public void onAnimationEnd(Animator animation) {
Michael Kolb4923c222012-04-02 16:18:36 -0700224 // update position
225 onScrollChanged();
John Reck0f602f32011-07-07 15:38:43 -0700226 }
227
228 @Override
229 public void onAnimationCancel(Animator animation) {
John Reck0f602f32011-07-07 15:38:43 -0700230 }
231 };
232
233 private int getVisibleTitleHeight() {
234 Tab tab = mBaseUi.getActiveTab();
235 WebView webview = tab != null ? tab.getWebView() : null;
236 return webview != null ? webview.getVisibleTitleHeight() : 0;
237 }
238
Tarun Nainani8eb00912014-07-17 12:28:32 -0700239 private void hideTopControls() {
240 Tab tab = mBaseUi.getActiveTab();
241 WebView view = tab != null ? tab.getWebView() : null;
242 if (view != null)
243 view.updateTopControls(true, false, true);
244 }
245
246 private void showTopControls() {
247 Tab tab = mBaseUi.getActiveTab();
248 WebView view = tab != null ? tab.getWebView() : null;
249 if (view != null)
250 view.updateTopControls(false, true, true);
251 }
252
253 private void enableTopControls() {
254 Tab tab = mBaseUi.getActiveTab();
255 WebView view = tab != null ? tab.getWebView() : null;
256 if (view != null)
257 view.updateTopControls(true, true, true);
258 }
259
260
John Reck0f602f32011-07-07 15:38:43 -0700261 /**
262 * Update the progress, from 0 to 100.
263 */
264 public void setProgress(int newProgress) {
265 if (newProgress >= PROGRESS_MAX) {
266 mProgress.setProgress(PageProgressView.MAX_PROGRESS);
267 mProgress.setVisibility(View.GONE);
268 mInLoad = false;
269 mNavBar.onProgressStopped();
270 // check if needs to be hidden
John Reckef654f12011-07-12 16:42:08 -0700271 if (!isEditingUrl() && !wantsToBeVisible()) {
Vivek Sekhar3bec6a32014-10-22 17:03:42 -0700272 mBaseUi.showTitleBarForDuration();
John Reck0f602f32011-07-07 15:38:43 -0700273 }
Tarun Nainani8eb00912014-07-17 12:28:32 -0700274
275 //onPageFinished
Vivek Sekhar8a660782014-10-27 17:00:53 -0700276 if (isFixed())
277 showTopControls();
278 else
279 enableTopControls();
Tarun Nainani8eb00912014-07-17 12:28:32 -0700280
John Reck0f602f32011-07-07 15:38:43 -0700281 } else {
282 if (!mInLoad) {
283 mProgress.setVisibility(View.VISIBLE);
284 mInLoad = true;
285 mNavBar.onProgressStarted();
Kulanthaivel Palanichamy77942682014-10-28 11:52:06 -0700286 mProgress.onProgressStarted();
Tarun Nainani8eb00912014-07-17 12:28:32 -0700287 //onPageStarted
Vivek Sekhar3bec6a32014-10-22 17:03:42 -0700288 showTopControls();
John Reck0f602f32011-07-07 15:38:43 -0700289 }
290 mProgress.setProgress(newProgress * PageProgressView.MAX_PROGRESS
291 / PROGRESS_MAX);
292 if (!mShowing) {
John Reck0f602f32011-07-07 15:38:43 -0700293 show();
294 }
295 }
296 }
297
298 public int getEmbeddedHeight() {
Vivek Sekhar3bec6a32014-10-22 17:03:42 -0700299 if (mIsFixedTitleBar) return 0;
John Reck2711fab2012-05-18 21:38:59 -0700300 return calculateEmbeddedHeight();
301 }
302
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800303 public boolean isFixed() {
304 return mIsFixedTitleBar;
305 }
306
307 int calculateEmbeddedHeight() {
John Reck0f602f32011-07-07 15:38:43 -0700308 int height = mNavBar.getHeight();
John Reck0f602f32011-07-07 15:38:43 -0700309 return height;
310 }
311
John Reckef654f12011-07-12 16:42:08 -0700312 public boolean wantsToBeVisible() {
Bijan Amirzada289e1e62014-04-15 11:53:48 -0700313 return (mSnapshotBar != null && mSnapshotBar.getVisibility() == View.VISIBLE
John Reckef654f12011-07-12 16:42:08 -0700314 && mSnapshotBar.isAnimating());
315 }
316
John Reck0f602f32011-07-07 15:38:43 -0700317 public boolean isEditingUrl() {
318 return mNavBar.isEditingUrl();
319 }
320
321 public WebView getCurrentWebView() {
322 Tab t = mBaseUi.getActiveTab();
323 if (t != null) {
324 return t.getWebView();
325 } else {
326 return null;
327 }
328 }
329
330 public PageProgressView getProgressView() {
331 return mProgress;
332 }
333
334 public NavigationBarBase getNavigationBar() {
335 return mNavBar;
336 }
337
John Reck0f602f32011-07-07 15:38:43 -0700338 public boolean isInLoad() {
339 return mInLoad;
340 }
341
342 private ViewGroup.LayoutParams makeLayoutParams() {
Michael Kolb4923c222012-04-02 16:18:36 -0700343 return new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
344 LayoutParams.WRAP_CONTENT);
John Reck0f602f32011-07-07 15:38:43 -0700345 }
346
347 @Override
Panos Thomas752ce592014-10-16 13:00:35 -0700348 public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
349 return mBaseUi.isCustomViewShowing() ? false :
350 super.requestFocus(direction, previouslyFocusedRect);
351 }
352
353 @Override
John Reck0f602f32011-07-07 15:38:43 -0700354 public View focusSearch(View focused, int dir) {
John Reckfcb60952012-05-30 09:45:28 -0700355 WebView web = getCurrentWebView();
John Reckd70419a2012-05-30 16:09:17 -0700356 if (FOCUS_DOWN == dir && hasFocus() && web != null
John Reckfcb60952012-05-30 09:45:28 -0700357 && web.hasFocusable() && web.getParent() != null) {
358 return web;
John Reck0f602f32011-07-07 15:38:43 -0700359 }
360 return super.focusSearch(focused, dir);
361 }
362
John Reckef654f12011-07-12 16:42:08 -0700363 public void onTabDataChanged(Tab tab) {
Ben Murdochd51bb572011-08-17 20:42:02 +0100364 if (mSnapshotBar != null) {
365 mSnapshotBar.onTabDataChanged(tab);
366 }
367
John Reckef654f12011-07-12 16:42:08 -0700368 if (tab.isSnapshot()) {
Ben Murdochd51bb572011-08-17 20:42:02 +0100369 inflateSnapshotBar();
John Reckef654f12011-07-12 16:42:08 -0700370 mSnapshotBar.setVisibility(VISIBLE);
371 mNavBar.setVisibility(GONE);
372 } else {
Ben Murdochd51bb572011-08-17 20:42:02 +0100373 if (mSnapshotBar != null) {
374 mSnapshotBar.setVisibility(GONE);
375 }
John Reckef654f12011-07-12 16:42:08 -0700376 mNavBar.setVisibility(VISIBLE);
377 }
378 }
379
Michael Kolb4923c222012-04-02 16:18:36 -0700380 public void onScrollChanged() {
John Reck2711fab2012-05-18 21:38:59 -0700381 if (!mShowing && !mIsFixedTitleBar) {
Michael Kolb4923c222012-04-02 16:18:36 -0700382 setTranslationY(getVisibleTitleHeight() - getEmbeddedHeight());
383 }
384 }
385
John Reck1cc1d1d2012-09-04 18:13:51 -0700386 public void onResume() {
387 setFixedTitleBar();
388 }
389
John Reck0f602f32011-07-07 15:38:43 -0700390}