blob: f5a76b9243747ba5d50335c92d2a5d2cb98fe5fa [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.browser;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.util.Log;
import android.view.ActionMode;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.DecelerateInterpolator;
import android.webkit.WebView;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.android.browser.UrlInputView.StateListener;
/**
* Ui for regular phone screen sizes
*/
public class PhoneUi extends BaseUi {
private static final String LOGTAG = "PhoneUi";
private PieControlPhone mPieControl;
private NavScreen mNavScreen;
private NavigationBarPhone mNavigationBar;
boolean mExtendedMenuOpen;
boolean mOptionsMenuOpen;
boolean mAnimating;
/**
* @param browser
* @param controller
*/
public PhoneUi(Activity browser, UiController controller) {
super(browser, controller);
mActivity.getActionBar().hide();
setUseQuickControls(BrowserSettings.getInstance().useQuickControls());
mNavigationBar = (NavigationBarPhone) mTitleBar.getNavigationBar();
}
@Override
public void onDestroy() {
hideTitleBar();
}
@Override
public void editUrl(boolean clearInput) {
if (mUseQuickControls) {
mTitleBar.setShowProgressOnly(false);
}
super.editUrl(clearInput);
}
@Override
public boolean onBackKey() {
if (mNavScreen != null) {
mNavScreen.close();
return true;
}
return super.onBackKey();
}
@Override
public boolean dispatchKey(int code, KeyEvent event) {
return false;
}
@Override
public void onProgressChanged(Tab tab) {
if (tab.inForeground()) {
int progress = tab.getLoadProgress();
mTitleBar.setProgress(progress);
if (progress == 100) {
if (!mOptionsMenuOpen || !mExtendedMenuOpen) {
suggestHideTitleBar();
if (mUseQuickControls) {
mTitleBar.setShowProgressOnly(false);
}
}
} else {
if (!mOptionsMenuOpen || mExtendedMenuOpen) {
if (mUseQuickControls && !mTitleBar.isEditingUrl()) {
mTitleBar.setShowProgressOnly(true);
setTitleGravity(Gravity.TOP);
}
showTitleBar();
}
}
}
}
@Override
public void setActiveTab(final Tab tab) {
mTitleBar.cancelTitleBarAnimation(true);
mTitleBar.setSkipTitleBarAnimations(true);
super.setActiveTab(tab);
BrowserWebView view = (BrowserWebView) tab.getWebView();
// TabControl.setCurrentTab has been called before this,
// so the tab is guaranteed to have a webview
if (view == null) {
Log.e(LOGTAG, "active tab with no webview detected");
return;
}
// Request focus on the top window.
if (mUseQuickControls) {
mPieControl.forceToTop(mContentView);
} else {
// check if title bar is already attached by animation
if (mTitleBar.getParent() == null) {
view.setEmbeddedTitleBar(mTitleBar);
}
}
if (tab.isInVoiceSearchMode()) {
showVoiceTitleBar(tab.getVoiceDisplayTitle(), tab.getVoiceSearchResults());
} else {
revertVoiceTitleBar(tab);
}
// update nav bar state
mNavigationBar.onStateChanged(StateListener.STATE_NORMAL);
updateLockIconToLatest(tab);
tab.getTopWindow().requestFocus();
mTitleBar.setSkipTitleBarAnimations(false);
}
// menu handling callbacks
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
updateMenuState(mActiveTab, menu);
return true;
}
@Override
public void updateMenuState(Tab tab, Menu menu) {
menu.setGroupVisible(R.id.NAV_MENU, (mNavScreen == null));
MenuItem bm = menu.findItem(R.id.bookmarks_menu_id);
if (bm != null) {
bm.setVisible(mNavScreen == null);
}
MenuItem nt = menu.findItem(R.id.new_tab_menu_id);
if (nt != null) {
nt.setVisible(mNavScreen == null);
}
MenuItem abm = menu.findItem(R.id.add_bookmark_menu_id);
if (abm != null) {
abm.setVisible((tab != null) && !tab.isSnapshot());
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mNavScreen != null) {
hideNavScreen(false);
}
return false;
}
@Override
public void onContextMenuCreated(Menu menu) {
hideTitleBar();
}
@Override
public void onContextMenuClosed(Menu menu, boolean inLoad) {
if (inLoad) {
showTitleBar();
}
}
// action mode callbacks
@Override
public void onActionModeStarted(ActionMode mode) {
if (!isEditingUrl()) {
hideTitleBar();
}
}
@Override
public void onActionModeFinished(boolean inLoad) {
if (inLoad) {
if (mUseQuickControls) {
mTitleBar.setShowProgressOnly(true);
}
showTitleBar();
}
mActivity.getActionBar().hide();
}
@Override
protected void setTitleGravity(int gravity) {
if (mUseQuickControls) {
FrameLayout.LayoutParams lp =
(FrameLayout.LayoutParams) mTitleBar.getLayoutParams();
lp.gravity = gravity;
mTitleBar.setLayoutParams(lp);
} else {
super.setTitleGravity(gravity);
}
}
@Override
public void setUseQuickControls(boolean useQuickControls) {
mUseQuickControls = useQuickControls;
mTitleBar.setUseQuickControls(mUseQuickControls);
if (useQuickControls) {
mPieControl = new PieControlPhone(mActivity, mUiController, this);
mPieControl.attachToContainer(mContentView);
WebView web = getWebView();
if (web != null) {
web.setEmbeddedTitleBar(null);
}
} else {
if (mPieControl != null) {
mPieControl.removeFromContainer(mContentView);
}
WebView web = getWebView();
if (web != null) {
// make sure we can re-parent titlebar
if ((mTitleBar != null) && (mTitleBar.getParent() != null)) {
((ViewGroup) mTitleBar.getParent()).removeView(mTitleBar);
}
web.setEmbeddedTitleBar(mTitleBar);
}
setTitleGravity(Gravity.NO_GRAVITY);
}
updateUrlBarAutoShowManagerTarget();
}
@Override
public boolean isWebShowing() {
return super.isWebShowing() && mNavScreen == null;
}
@Override
public void showWeb(boolean animate) {
super.showWeb(animate);
hideNavScreen(animate);
}
void showNavScreen() {
mUiController.setBlockEvents(true);
mNavScreen = new NavScreen(mActivity, mUiController, this);
mActiveTab.capture();
// Add the custom view to its container
mCustomViewContainer.addView(mNavScreen, COVER_SCREEN_PARAMS);
AnimScreen ascreen = new AnimScreen(mActivity, getTitleBar(), getWebView());
final View animView = ascreen.mMain;
mCustomViewContainer.addView(animView, COVER_SCREEN_PARAMS);
mCustomViewContainer.setVisibility(View.VISIBLE);
mCustomViewContainer.bringToFront();
View target = ((NavTabView) mNavScreen.mScroller.getSelectedView()).mImage;
int fromLeft = 0;
int fromTop = getTitleBar().getHeight();
int fromRight = mContentView.getWidth();
int fromBottom = mContentView.getHeight();
int width = target.getWidth();
int height = target.getHeight();
int toLeft = (mContentView.getWidth() - width) / 2;
int toTop = fromTop + (mContentView.getHeight() - fromTop - height) / 2;
int toRight = toLeft + width;
int toBottom = toTop + height;
float scaleFactor = width / (float) mContentView.getWidth();
detachTab(mActiveTab);
mContentView.setVisibility(View.GONE);
AnimatorSet inanim = new AnimatorSet();
ObjectAnimator tx = ObjectAnimator.ofInt(ascreen.mContent, "left",
fromLeft, toLeft);
ObjectAnimator ty = ObjectAnimator.ofInt(ascreen.mContent, "top",
fromTop, toTop);
ObjectAnimator tr = ObjectAnimator.ofInt(ascreen.mContent, "right",
fromRight, toRight);
ObjectAnimator tb = ObjectAnimator.ofInt(ascreen.mContent, "bottom",
fromBottom, toBottom);
ObjectAnimator title = ObjectAnimator.ofFloat(ascreen.mTitle, "alpha",
1f, 0f);
ObjectAnimator content = ObjectAnimator.ofFloat(ascreen.mContent, "alpha",
1f, 0f);
ObjectAnimator sx = ObjectAnimator.ofFloat(ascreen, "scaleFactor",
1f, scaleFactor);
inanim.playTogether(tx, ty, tr, tb, title, content, sx);
inanim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator anim) {
mCustomViewContainer.removeView(animView);
finishAnimationIn();
mUiController.setBlockEvents(false);
}
});
inanim.setInterpolator(new DecelerateInterpolator(2f));
inanim.setDuration(300);
inanim.start();
}
private void finishAnimationIn() {
if (mNavScreen != null) {
// notify accessibility manager about the screen change
mNavScreen.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
mTabControl.setOnThumbnailUpdatedListener(mNavScreen);
}
}
void hideNavScreen(boolean animate) {
if (mNavScreen == null) return;
final Tab tab = mNavScreen.getSelectedTab();
if ((tab == null) || !animate) {
if (tab != null) {
setActiveTab(tab);
} else if (mTabControl.getTabCount() > 0) {
// use a fallback tab
setActiveTab(mTabControl.getCurrentTab());
}
mContentView.setVisibility(View.VISIBLE);
finishAnimateOut();
return;
}
NavTabView tabview = (NavTabView) mNavScreen.getSelectedTabView();
if (tabview == null) {
if (mTabControl.getTabCount() > 0) {
// use a fallback tab
setActiveTab(mTabControl.getCurrentTab());
}
mContentView.setVisibility(View.VISIBLE);
finishAnimateOut();
return;
}
mUiController.setBlockEvents(true);
mUiController.setActiveTab(tab);
mContentView.setVisibility(View.VISIBLE);
final AnimScreen screen = new AnimScreen(mActivity, tab.getScreenshot());
View target = ((NavTabView) mNavScreen.mScroller.getSelectedView()).mImage;
int toLeft = 0;
int toTop = getTitleBar().getHeight();
int toRight = mContentView.getWidth();
int width = target.getWidth();
int height = target.getHeight();
int[] pos = new int[2];
tabview.mImage.getLocationInWindow(pos);
int fromLeft = pos[0];
int fromTop = pos[1];
int fromRight = fromLeft + width;
int fromBottom = fromTop + height;
float scaleFactor = mContentView.getWidth() / (float) width;
int toBottom = (int) (height * scaleFactor);
screen.mMain.setAlpha(0f);
mCustomViewContainer.addView(screen.mMain, COVER_SCREEN_PARAMS);
AnimatorSet animSet = new AnimatorSet();
ObjectAnimator l = ObjectAnimator.ofInt(screen.mContent, "left",
fromLeft, toLeft);
ObjectAnimator t = ObjectAnimator.ofInt(screen.mContent, "top",
fromTop, toTop);
ObjectAnimator r = ObjectAnimator.ofInt(screen.mContent, "right",
fromRight, toRight);
ObjectAnimator b = ObjectAnimator.ofInt(screen.mContent, "bottom",
fromBottom, toBottom);
ObjectAnimator scale = ObjectAnimator.ofFloat(screen, "scaleFactor",
1f, scaleFactor);
ObjectAnimator alpha = ObjectAnimator.ofFloat(screen.mMain, "alpha", 1f, 1f);
ObjectAnimator otheralpha = ObjectAnimator.ofFloat(mCustomViewContainer, "alpha", 1f, 0f);
alpha.setStartDelay(100);
animSet.playTogether(l, t, r, b, scale, alpha, otheralpha);
animSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator anim) {
mCustomViewContainer.removeView(screen.mMain);
finishAnimateOut();
mUiController.setBlockEvents(false);
}
});
animSet.setDuration(250);
animSet.start();
}
private void finishAnimateOut() {
mTabControl.setOnThumbnailUpdatedListener(null);
mCustomViewContainer.removeView(mNavScreen);
mCustomViewContainer.setAlpha(1f);
mNavScreen = null;
mCustomViewContainer.setVisibility(View.GONE);
}
@Override
public boolean needsRestoreAllTabs() {
return false;
}
public void toggleNavScreen() {
if (mNavScreen == null) {
showNavScreen();
} else {
hideNavScreen(false);
}
}
@Override
public boolean shouldCaptureThumbnails() {
return true;
}
static class AnimScreen {
private View mMain;
private ImageView mTitle;
private ImageView mContent;
private float mScale;
public AnimScreen(Context ctx, TitleBar tbar, WebView web) {
mMain = LayoutInflater.from(ctx).inflate(R.layout.anim_screen,
null);
mContent = (ImageView) mMain.findViewById(R.id.content);
mContent.setTop(tbar.getHeight());
mTitle = (ImageView) mMain.findViewById(R.id.title);
Bitmap bm1 = Bitmap.createBitmap(tbar.getWidth(), tbar.getHeight(),
Bitmap.Config.RGB_565);
Canvas c1 = new Canvas(bm1);
tbar.draw(c1);
mTitle.setImageBitmap(bm1);
int h = web.getHeight() - tbar.getHeight();
Bitmap bm2 = Bitmap.createBitmap(web.getWidth(), h,
Bitmap.Config.RGB_565);
Canvas c2 = new Canvas(bm2);
int tx = web.getScrollX();
int ty = web.getScrollY();
c2.translate(-tx, -ty - tbar.getHeight());
web.draw(c2);
mContent.setImageBitmap(bm2);
mContent.setScaleType(ImageView.ScaleType.MATRIX);
mContent.setImageMatrix(new Matrix());
mScale = 1.0f;
setScaleFactor(getScaleFactor());
}
public AnimScreen(Context ctx, Bitmap image) {
mMain = LayoutInflater.from(ctx).inflate(R.layout.anim_screen,
null);
mContent = (ImageView) mMain.findViewById(R.id.content);
mContent.setImageBitmap(image);
mContent.setScaleType(ImageView.ScaleType.MATRIX);
mContent.setImageMatrix(new Matrix());
mScale = 1.0f;
setScaleFactor(getScaleFactor());
}
public void setScaleFactor(float sf) {
mScale = sf;
Matrix m = new Matrix();
m.postScale(sf,sf);
mContent.setImageMatrix(m);
}
public float getScaleFactor() {
return mScale;
}
}
}