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