PhoneUi.java revision 08a687a75ef5164483ccfb3e144772c59bb14d83
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 17package com.android.browser; 18 19import android.animation.Animator; 20import android.animation.Animator.AnimatorListener; 21import android.animation.AnimatorSet; 22import android.animation.ObjectAnimator; 23import android.app.Activity; 24import android.util.Log; 25import android.view.ActionMode; 26import android.view.Gravity; 27import android.view.KeyEvent; 28import android.view.Menu; 29import android.view.View; 30import android.webkit.WebView; 31import android.widget.FrameLayout; 32 33/** 34 * Ui for regular phone screen sizes 35 */ 36public class PhoneUi extends BaseUi { 37 38 private static final String LOGTAG = "PhoneUi"; 39 private static final float NAV_TAB_SCALE = 0.75f; 40 41 private TitleBarPhone mTitleBar; 42 private ActiveTabsPage mActiveTabsPage; 43 private boolean mUseQuickControls; 44 private PieControl mPieControl; 45 private NavScreen mNavScreen; 46 47 boolean mExtendedMenuOpen; 48 boolean mOptionsMenuOpen; 49 boolean mAnimating; 50 51 /** 52 * @param browser 53 * @param controller 54 */ 55 public PhoneUi(Activity browser, UiController controller) { 56 super(browser, controller); 57 mTitleBar = new TitleBarPhone(mActivity, mUiController, this, 58 mContentView); 59 // mTitleBar will be always be shown in the fully loaded mode on 60 // phone 61 mTitleBar.setProgress(100); 62 mActivity.getActionBar().hide(); 63 setUseQuickControls(BrowserSettings.getInstance().useQuickControls()); 64 } 65 66 @Override 67 public void hideComboView() { 68 super.hideComboView(); 69 mActivity.getActionBar().hide(); 70 } 71 72 // lifecycle 73 74 @Override 75 public void onPause() { 76 // FIXME: This removes the active tabs page and resets the menu to 77 // MAIN_MENU. A better solution might be to do this work in onNewIntent 78 // but then we would need to save it in onSaveInstanceState and restore 79 // it in onCreate/onRestoreInstanceState 80 if (mActiveTabsPage != null) { 81 mUiController.removeActiveTabsPage(true); 82 } 83 super.onPause(); 84 } 85 86 @Override 87 public void onDestroy() { 88 hideTitleBar(); 89 } 90 91 @Override 92 public void editUrl(boolean clearInput) { 93 if (mUseQuickControls) { 94 getTitleBar().setShowProgressOnly(false); 95 } 96 super.editUrl(clearInput); 97 } 98 99 @Override 100 public boolean onBackKey() { 101 if (mActiveTabsPage != null) { 102 // if tab page is showing, hide it 103 mUiController.removeActiveTabsPage(true); 104 return true; 105 } else if (mNavScreen != null) { 106 mNavScreen.close(); 107 return true; 108 } 109 return super.onBackKey(); 110 } 111 112 @Override 113 public boolean dispatchKey(int code, KeyEvent event) { 114 if (!isComboViewShowing()) { 115 switch (code) { 116 case KeyEvent.KEYCODE_MENU: 117 if (mNavScreen == null) { 118 showNavScreen(); 119 return true; 120 } else { 121 mNavScreen.close(); 122 return true; 123 } 124 } 125 } 126 return false; 127 } 128 129 @Override 130 public void onProgressChanged(Tab tab) { 131 if (tab.inForeground()) { 132 int progress = tab.getLoadProgress(); 133 mTitleBar.setProgress(progress); 134 if (progress == 100) { 135 if (!mOptionsMenuOpen || !mExtendedMenuOpen) { 136 hideTitleBar(); 137 if (mUseQuickControls) { 138 mTitleBar.setShowProgressOnly(false); 139 } 140 } 141 } else { 142 if (!mOptionsMenuOpen || mExtendedMenuOpen) { 143 if (mUseQuickControls && !mTitleBar.isEditingUrl()) { 144 mTitleBar.setShowProgressOnly(true); 145 setTitleGravity(Gravity.TOP); 146 } 147 showTitleBar(); 148 } 149 } 150 } 151 } 152 153 @Override 154 public void setActiveTab(final Tab tab) { 155 captureTab(mActiveTab); 156 super.setActiveTab(tab, true); 157 setActiveTab(tab, true); 158 } 159 160 @Override 161 void setActiveTab(Tab tab, boolean needsAttaching) { 162 BrowserWebView view = (BrowserWebView) tab.getWebView(); 163 // TabControl.setCurrentTab has been called before this, 164 // so the tab is guaranteed to have a webview 165 if (view == null) { 166 Log.e(LOGTAG, "active tab with no webview detected"); 167 return; 168 } 169 // Request focus on the top window. 170 if (mUseQuickControls) { 171 mPieControl.forceToTop(mContentView); 172 view.setScrollListener(null); 173 } else { 174 // check if title bar is already attached by animation 175 if (mTitleBar.getParent() == null) { 176 view.setEmbeddedTitleBar(mTitleBar); 177 } 178 } 179 if (tab.isInVoiceSearchMode()) { 180 showVoiceTitleBar(tab.getVoiceDisplayTitle(), tab.getVoiceSearchResults()); 181 } else { 182 revertVoiceTitleBar(tab); 183 } 184 updateLockIconToLatest(tab); 185 tab.getTopWindow().requestFocus(); 186 } 187 188 @Override 189 protected TitleBarBase getTitleBar() { 190 return mTitleBar; 191 } 192 193 // active tabs page 194 195 @Override 196 public void showActiveTabsPage() { 197 captureTab(mActiveTab); 198 mActiveTabsPage = new ActiveTabsPage(mActivity, mUiController); 199 mTitleBar.setVisibility(View.GONE); 200 hideTitleBar(); 201 mContentView.addView(mActiveTabsPage, COVER_SCREEN_PARAMS); 202 mActiveTabsPage.requestFocus(); 203 } 204 205 /** 206 * Remove the active tabs page. 207 */ 208 @Override 209 public void removeActiveTabsPage() { 210 mContentView.removeView(mActiveTabsPage); 211 mTitleBar.setVisibility(View.VISIBLE); 212 mActiveTabsPage = null; 213 } 214 215 @Override 216 public boolean showsWeb() { 217 return super.showsWeb() && mActiveTabsPage == null; 218 } 219 220 // menu handling callbacks 221 222 @Override 223 public void onContextMenuCreated(Menu menu) { 224 hideTitleBar(); 225 } 226 227 @Override 228 public void onContextMenuClosed(Menu menu, boolean inLoad) { 229 if (inLoad) { 230 showTitleBar(); 231 } 232 } 233 234 // action mode callbacks 235 236 @Override 237 public void onActionModeStarted(ActionMode mode) { 238 hideTitleBar(); 239 } 240 241 @Override 242 public void onActionModeFinished(boolean inLoad) { 243 if (inLoad) { 244 if (mUseQuickControls) { 245 mTitleBar.setShowProgressOnly(true); 246 } 247 showTitleBar(); 248 } 249 mActivity.getActionBar().hide(); 250 } 251 252 @Override 253 protected void setTitleGravity(int gravity) { 254 if (mUseQuickControls) { 255 FrameLayout.LayoutParams lp = 256 (FrameLayout.LayoutParams) getTitleBar().getLayoutParams(); 257 lp.gravity = gravity; 258 getTitleBar().setLayoutParams(lp); 259 } else { 260 super.setTitleGravity(gravity); 261 } 262 } 263 264 private void setUseQuickControls(boolean useQuickControls) { 265 mUseQuickControls = useQuickControls; 266 getTitleBar().setUseQuickControls(mUseQuickControls); 267 if (useQuickControls) { 268 mPieControl = new PieControl(mActivity, mUiController, this); 269 mPieControl.attachToContainer(mContentView); 270 WebView web = getWebView(); 271 if (web != null) { 272 web.setEmbeddedTitleBar(null); 273 } 274 } else { 275 if (mPieControl != null) { 276 mPieControl.removeFromContainer(mContentView); 277 } 278 WebView web = getWebView(); 279 if (web != null) { 280 web.setEmbeddedTitleBar(mTitleBar); 281 } 282 setTitleGravity(Gravity.NO_GRAVITY); 283 } 284 } 285 286 @Override 287 public boolean onPrepareOptionsMenu(Menu menu) { 288 if (mUseQuickControls) { 289 menu.setGroupVisible(R.id.NAV_MENU, false); 290 mPieControl.onMenuOpened(menu); 291 return false; 292 } 293 return true; 294 } 295 296 @Override 297 protected void captureTab(final Tab tab) { 298 if (mUseQuickControls) { 299 super.captureTab(tab); 300 } else { 301 captureTab(tab, 302 mActivity.getWindowManager().getDefaultDisplay().getWidth(), 303 mActivity.getWindowManager().getDefaultDisplay().getHeight()); 304 } 305 } 306 307 void showNavScreen() { 308 if (mAnimating) return; 309 mAnimating = true; 310 mNavScreen = new NavScreen(mActivity, mUiController, this); 311 mNavScreen.startTask(new Runnable() { 312 public void run() { 313 BrowserWebView web = (BrowserWebView) getWebView(); 314 if (web != null) { 315 mActiveTab.setScreenshot(web.capture()); 316 } 317 mNavScreen.finishTask(); 318 } 319 }); 320 WebView web = getWebView(); 321 if (web != null) { 322 int w = web.getWidth(); 323 int h = web.getHeight(); 324 mNavScreen.setTabDimensions((int) (w * NAV_TAB_SCALE), 325 (int) (h * NAV_TAB_SCALE)); 326 } 327 // Add the custom view to its container. 328 mCustomViewContainer.addView(mNavScreen, COVER_SCREEN_GRAVITY_CENTER); 329 mContentView.setLayerType(View.LAYER_TYPE_HARDWARE, null); 330 ObjectAnimator animx = ObjectAnimator.ofFloat(mContentView, 331 "scaleX", 1.0f, 0.85f); 332 ObjectAnimator animy = ObjectAnimator.ofFloat(mContentView, 333 "scaleY", 1.0f, 0.85f); 334 AnimatorSet anims = new AnimatorSet(); 335 anims.setDuration(200); 336 anims.addListener(new AnimatorListener() { 337 338 @Override 339 public void onAnimationCancel(Animator animation) { 340 } 341 342 @Override 343 public void onAnimationEnd(Animator animation) { 344 finishShowNavScreen(); 345 } 346 347 @Override 348 public void onAnimationRepeat(Animator animation) { 349 } 350 351 @Override 352 public void onAnimationStart(Animator animation) { 353 } 354 }); 355 anims.playTogether(animx, animy); 356 anims.start(); 357 } 358 359 private void finishShowNavScreen() { 360 // Hide the content view. 361 mContentView.setLayerType(View.LAYER_TYPE_NONE, null); 362 mContentView.setVisibility(View.GONE); 363 mContentView.setScaleX(1.0f); 364 mContentView.setScaleY(1.0f); 365 mNavScreen.waitForTask(); 366 // Finally show the custom view container. 367 mCustomViewContainer.setVisibility(View.VISIBLE); 368 mCustomViewContainer.bringToFront(); 369 mAnimating = false; 370 } 371 372 void hideNavScreen(boolean animateToPage) { 373 if (mAnimating || mNavScreen == null) return; 374 mAnimating = true; 375 mNavScreen.setLayerType(View.LAYER_TYPE_HARDWARE, null); 376 if (animateToPage) { 377 ObjectAnimator animx = ObjectAnimator.ofFloat(mNavScreen, "scaleX", 378 1.0f, 1.2f); 379 ObjectAnimator animy = ObjectAnimator.ofFloat(mNavScreen, "scaleY", 380 1.0f, 1.2f); 381 AnimatorSet anims = new AnimatorSet(); 382 anims.setDuration(200); 383 anims.addListener(new AnimatorListener() { 384 385 @Override 386 public void onAnimationCancel(Animator animation) { 387 } 388 389 @Override 390 public void onAnimationEnd(Animator animation) { 391 finishHideNavScreen(); 392 } 393 394 @Override 395 public void onAnimationRepeat(Animator animation) { 396 } 397 398 @Override 399 public void onAnimationStart(Animator animation) { 400 } 401 }); 402 anims.playTogether(animx, animy); 403 anims.start(); 404 } else { 405 finishHideNavScreen(); 406 } 407 408 } 409 410 private void finishHideNavScreen() { 411 // Hide the custom view. 412 mNavScreen.setVisibility(View.GONE); 413 mNavScreen.setLayerType(View.LAYER_TYPE_NONE, null); 414 // Remove the custom view from its container. 415 mCustomViewContainer.removeView(mNavScreen); 416 mNavScreen = null; 417 mCustomViewContainer.setVisibility(View.GONE); 418 // Show the content view. 419 mContentView.setVisibility(View.VISIBLE); 420 mAnimating = false; 421 } 422 423} 424