diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/com/android/browser/BaseUi.java | 2 | ||||
-rw-r--r-- | src/com/android/browser/Controller.java | 3 | ||||
-rw-r--r-- | src/com/android/browser/NavScreen.java | 382 | ||||
-rw-r--r-- | src/com/android/browser/PhoneUi.java | 215 | ||||
-rw-r--r-- | src/com/android/browser/TitleBarPhone.java | 2 | ||||
-rw-r--r-- | src/com/android/browser/UiController.java | 2 |
6 files changed, 520 insertions, 86 deletions
diff --git a/src/com/android/browser/BaseUi.java b/src/com/android/browser/BaseUi.java index b7964dc..43bc7d6 100644 --- a/src/com/android/browser/BaseUi.java +++ b/src/com/android/browser/BaseUi.java @@ -76,7 +76,7 @@ public abstract class BaseUi implements UI, WebViewFactory { private FrameLayout mBrowserFrameLayout; protected FrameLayout mContentView; - private FrameLayout mCustomViewContainer; + protected FrameLayout mCustomViewContainer; private View mCustomView; private WebChromeClient.CustomViewCallback mCustomViewCallback; diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java index 2f47cad..f920702 100644 --- a/src/com/android/browser/Controller.java +++ b/src/com/android/browser/Controller.java @@ -2128,7 +2128,8 @@ public class Controller mTabControl.removeTab(tab); } - protected void setActiveTab(Tab tab) { + @Override + public void setActiveTab(Tab tab) { // monkey protection against delayed start if (tab != null) { mTabControl.setCurrentTab(tab); diff --git a/src/com/android/browser/NavScreen.java b/src/com/android/browser/NavScreen.java new file mode 100644 index 0000000..8b897df --- /dev/null +++ b/src/com/android/browser/NavScreen.java @@ -0,0 +1,382 @@ +/* + * Copyright (C) 2011 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.app.Activity; +import android.content.Context; +import android.graphics.Bitmap; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.webkit.WebView; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.AdapterView.OnItemSelectedListener; +import android.widget.BaseAdapter; +import android.widget.FrameLayout; +import android.widget.Gallery; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.ImageView.ScaleType; +import android.widget.LinearLayout; +import android.widget.ListPopupWindow; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.List; + +public class NavScreen extends LinearLayout implements OnClickListener { + + UiController mUiController; + PhoneUi mUi; + Tab mTab; + Activity mActivity; + + View mTopPanel; + ImageButton mBack; + ImageButton mRefresh; + ImageButton mForward; + ImageButton mTabs; + ImageButton mBookmarks; + ImageButton mMore; + ImageButton mNewTab; + ImageButton mNewIncognito; + FrameLayout mHolder; + + Gallery mFlipper; + int mTabWidth; + int mTabHeight; + TabAdapter mAdapter; + ListPopupWindow mPopup; + + boolean mReady; + + public NavScreen(Activity activity, UiController ctl, PhoneUi ui) { + super(activity); + mActivity = activity; + mUiController = ctl; + mUi = ui; + init(); + } + + protected Tab getSelectedTab() { + return (Tab) mFlipper.getSelectedItem(); + } + + protected void setTabDimensions(int w, int h) { + mTabWidth = w; + mTabHeight = h; + requestLayout(); + } + + protected void showMenu(Menu menu) { + MenuAdapter menuAdapter = new MenuAdapter(mContext); + menuAdapter.setMenu(menu); + ListPopupWindow popup = new ListPopupWindow(mContext); + popup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED); + popup.setAdapter(menuAdapter); + popup.setModal(true); + popup.setAnchorView(mMore); + popup.setWidth((int) mContext.getResources().getDimension( + R.dimen.menu_width)); + popup.show(); + mPopup = popup; + } + + protected void dismissMenu() { + if (mPopup != null) { + mPopup.dismiss(); + } + } + + private void init() { + LayoutInflater.from(mContext).inflate(R.layout.nav_screen, this); + LinearLayout content = (LinearLayout) findViewById(R.id.nav_screen); + mTopPanel = findViewById(R.id.navtop); + mBack = (ImageButton) findViewById(R.id.back); + mForward = (ImageButton) findViewById(R.id.forward); + mRefresh = (ImageButton) findViewById(R.id.refresh); + mTabs = (ImageButton) findViewById(R.id.tabs); + mBookmarks = (ImageButton) findViewById(R.id.bookmarks); + mNewTab = (ImageButton) findViewById(R.id.newtab); + mNewIncognito = (ImageButton) findViewById(R.id.newincognito); + mMore = (ImageButton) findViewById(R.id.more); + mBack.setOnClickListener(this); + mForward.setOnClickListener(this); + mRefresh.setOnClickListener(this); + mTabs.setOnClickListener(this); + mBookmarks.setOnClickListener(this); + mNewTab.setOnClickListener(this); + mNewIncognito.setOnClickListener(this); + mMore.setOnClickListener(this); + mHolder = (FrameLayout) findViewById(R.id.galleryholder); + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + mFlipper = new TabGallery(mContext); + mFlipper.setSpacing((int)(mContext.getResources() + .getDimension(R.dimen.nav_tab_spacing))); + mFlipper.setLayoutParams(lp); + mHolder.addView(mFlipper, 0); + mAdapter = new TabAdapter(mContext, mUiController.getTabControl()); + mFlipper.setAdapter(mAdapter); + setTab(mUi.getActiveTab(), true); + mFlipper.setOnItemClickListener(new OnItemClickListener() { + @Override + public void onItemClick(AdapterView<?> parent, View view, + int position, long id) { + // post as runnable to prevent bug in gesturedetector + // when view is removed in click handler + // sends action_cancel before action_up + mFlipper.post(new Runnable() { + public void run() { + close(); + } + }); + } + }); + mFlipper.setOnItemSelectedListener(new OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView<?> parent, View view, + int position, long id) { + final Tab tab = mAdapter.getItem(position); + setTab(tab, false); + } + + @Override + public void onNothingSelected(AdapterView<?> parent) { + } + }); + } + + private void setTab(Tab tab, boolean updateFlipper) { + mTab = tab; + // refresh state from tab + WebView web = tab.getWebView(); + if (web != null) { + mBack.setImageResource(web.canGoBack() + ? R.drawable.ic_back_holo_dark + : R.drawable.ic_back_disabled_holo_dark); + mForward.setImageResource(web.canGoForward() + ? R.drawable.ic_forward_holo_dark + : R.drawable.ic_forward_disabled_holo_dark); + } + if (updateFlipper) { + mFlipper.setSelection(mUiController.getTabControl().getTabIndex(tab)); + } + } + + @Override + public void onClick(View v) { + WebView web = (mTab != null) ? mTab.getWebView() : null; + if (web != null) { + if (mBack == v) { + mUi.hideNavScreen(true); + web.goBack(); + } else if (mForward == v) { + mUi.hideNavScreen(true); + web.goForward(); + } else if (mRefresh == v) { + mUi.hideNavScreen(true); + web.reload(); + } + } + if (mBookmarks == v) { + mUi.hideNavScreen(false); + mUiController.bookmarksOrHistoryPicker(false); + } else if (mTabs == v) { + mUi.hideNavScreen(false); + mUi.showActiveTabsPage(); + } else if (mNewTab == v) { + mUi.hideNavScreen(true); + mUiController.openTabToHomePage(); + } else if (mMore == v) { + mActivity.openOptionsMenu(); + } else if (mNewIncognito == v) { + mUi.hideNavScreen(true); + mUiController.openIncognitoTab(); + } + } + + protected void close() { + close(true); + } + + protected void close(boolean animate) { + mUi.hideNavScreen(animate); + Tab tab = (Tab) mFlipper.getSelectedItem(); + if (tab != mUi.getActiveTab()) { + mUiController.setActiveTab(tab); + } + } + + class TabGallery extends Gallery { + + public TabGallery(Context ctx) { + super(ctx); + setUnselectedAlpha(0.3f); + } + + @Override + protected ViewGroup.LayoutParams generateDefaultLayoutParams() { + return new Gallery.LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + } + + @Override + protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) { + return generateDefaultLayoutParams(); + } + + } + + class TabAdapter extends BaseAdapter { + + Context context; + TabControl tabControl; + + public TabAdapter(Context ctx, TabControl tc) { + context = ctx; + tabControl = tc; + } + + void onCloseTab(Tab tab) { + if (tab != null) { + mUiController.closeTab(tab); + if (tabControl.getTabCount() == 0) { + mUiController.openTabToHomePage(); + mUi.hideNavScreen(false); + } else { + notifyDataSetChanged(); + } + } + } + + @Override + public int getCount() { + return tabControl.getTabCount(); + } + + @Override + public Tab getItem(int position) { + return tabControl.getTab(position); + } + + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ImageView content = null; + if (convertView == null) { + convertView = LayoutInflater.from(context).inflate(R.layout.nav_tab_view, + null); + content = (ImageView) convertView.findViewById(R.id.content); + content.setLayoutParams(new LayoutParams(mTabWidth, mTabHeight)); + } else { + content = (ImageView) convertView.findViewById(R.id.content); + } + TextView title = (TextView) convertView.findViewById(R.id.title); + ImageView icon = (ImageView) convertView.findViewById(R.id.favicon); + ImageButton close = (ImageButton) convertView.findViewById(R.id.closetab); + final Tab tab = getItem(position); + if (tab.getFavicon() != null) { + icon.setImageBitmap(tab.getFavicon()); + } + title.setText(tab.getUrl()); + Bitmap screen = tab.getScreenshot(); + content.setImageBitmap(screen); + close.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + onCloseTab(tab); + } + }); + title.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + close(false); + mUi.editUrl(false); + } + }); + return convertView; + } + } + + private class MenuAdapter extends BaseAdapter implements OnClickListener { + + List<MenuItem> mItems; + LayoutInflater mInflater; + + public MenuAdapter(Context ctx) { + mInflater = LayoutInflater.from(ctx); + mItems = new ArrayList<MenuItem>(); + } + + public void setMenu(Menu menu) { + mItems.clear(); + for (int i = 0; i < menu.size(); i++) { + MenuItem item = menu.getItem(i); + if (item.isEnabled() && item.isVisible()) { + mItems.add(item); + } + } + notifyDataSetChanged(); + } + + @Override + public int getCount() { + return mItems.size(); + } + + @Override + public MenuItem getItem(int position) { + return mItems.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public void onClick(View v) { + if (v.getTag() != null) { + dismissMenu(); + mActivity.closeOptionsMenu(); + mUi.hideNavScreen(false); + mUiController.onOptionsItemSelected((MenuItem) v.getTag()); + } + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + final MenuItem item = mItems.get(position); + View view = mInflater.inflate(R.layout.qc_menu_item, null); + TextView label = (TextView) view.findViewById(R.id.title); + label.setText(item.getTitle()); + label.setTag(item); + label.setOnClickListener(this); + return label; + } + + } + +} diff --git a/src/com/android/browser/PhoneUi.java b/src/com/android/browser/PhoneUi.java index 471a9e6..3415e39 100644 --- a/src/com/android/browser/PhoneUi.java +++ b/src/com/android/browser/PhoneUi.java @@ -16,17 +16,17 @@ package com.android.browser; +import android.animation.Animator; +import android.animation.Animator.AnimatorListener; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; import android.app.Activity; -import android.content.Context; -import android.graphics.PixelFormat; import android.util.Log; import android.view.ActionMode; import android.view.Gravity; import android.view.KeyEvent; import android.view.Menu; -import android.view.MotionEvent; import android.view.View; -import android.view.WindowManager; import android.webkit.WebView; import android.widget.FrameLayout; @@ -36,12 +36,13 @@ import android.widget.FrameLayout; public class PhoneUi extends BaseUi { private static final String LOGTAG = "PhoneUi"; + private static final float NAV_TAB_SCALE = 0.75f; private TitleBarPhone mTitleBar; private ActiveTabsPage mActiveTabsPage; - private TouchProxy mTitleOverlay; private boolean mUseQuickControls; private PieControl mPieControl; + private NavScreen mNavScreen; boolean mExtendedMenuOpen; boolean mOptionsMenuOpen; @@ -100,11 +101,31 @@ public class PhoneUi extends BaseUi { // if tab page is showing, hide it mUiController.removeActiveTabsPage(true); return true; + } else if (mNavScreen != null) { + mNavScreen.close(); + return true; } return super.onBackKey(); } @Override + public boolean dispatchKey(int code, KeyEvent event) { + if (!isComboViewShowing()) { + switch (code) { + case KeyEvent.KEYCODE_MENU: + if (mNavScreen == null) { + showNavScreen(); + return true; + } else { + mNavScreen.close(); + return true; + } + } + } + return false; + } + + @Override public void onProgressChanged(Tab tab) { if (tab.inForeground()) { int progress = tab.getLoadProgress(); @@ -198,46 +219,6 @@ public class PhoneUi extends BaseUi { // menu handling callbacks @Override - public void onOptionsMenuOpened() { - if (!mUseQuickControls) { - mOptionsMenuOpen = true; - // options menu opened, show title bar - showTitleBar(); - if (mTitleOverlay == null) { - // This assumes that getTitleBar always returns the same View - mTitleOverlay = new TouchProxy(mActivity, getTitleBar()); - } - mActivity.getWindowManager().addView(mTitleOverlay, - mTitleOverlay.getWindowLayoutParams()); - } - } - - @Override - public void onExtendedMenuOpened() { - // Switching the menu to expanded view, so hide the - // title bar. - mExtendedMenuOpen = true; - hideTitleBar(); - } - - @Override - public void onOptionsMenuClosed(boolean inLoad) { - mOptionsMenuOpen = false; - mActivity.getWindowManager().removeView(mTitleOverlay); - if (!inLoad && !getTitleBar().hasFocus()) { - hideTitleBar(); - } - } - - @Override - public void onExtendedMenuClosed(boolean inLoad) { - mExtendedMenuOpen = false; - if (!mUseQuickControls) { - showTitleBar(); - } - } - - @Override public void onContextMenuCreated(Menu menu) { hideTitleBar(); } @@ -268,40 +249,6 @@ public class PhoneUi extends BaseUi { } @Override - public boolean dispatchKey(int code, KeyEvent event) { - return false; - } - - static class TouchProxy extends View { - - View mTarget; - - TouchProxy(Context context, View target) { - super(context); - mTarget = target; - } - - @Override - public boolean dispatchTouchEvent(MotionEvent event) { - return mTarget.dispatchTouchEvent(event); - } - - WindowManager.LayoutParams getWindowLayoutParams() { - WindowManager.LayoutParams params = - new WindowManager.LayoutParams( - mTarget.getWidth(), - mTarget.getHeight(), - WindowManager.LayoutParams.TYPE_APPLICATION, - WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, - PixelFormat.TRANSPARENT); - params.gravity = Gravity.TOP | Gravity.LEFT; - params.y = mTarget.getTop(); - params.x = mTarget.getLeft(); - return params; - } - } - - @Override protected void setTitleGravity(int gravity) { if (mUseQuickControls) { FrameLayout.LayoutParams lp = @@ -337,12 +284,15 @@ public class PhoneUi extends BaseUi { @Override public boolean onPrepareOptionsMenu(Menu menu) { + menu.setGroupVisible(R.id.NAV_MENU, false); if (mUseQuickControls) { - menu.setGroupVisible(R.id.NAV_MENU, false); mPieControl.onMenuOpened(menu); return false; } else { - return true; + if (mNavScreen != null) { + mNavScreen.showMenu(menu); + } + return false; } } @@ -353,9 +303,108 @@ public class PhoneUi extends BaseUi { } else { captureTab(tab, mActivity.getWindowManager().getDefaultDisplay().getWidth(), - (int) mActivity.getResources() - .getDimension(R.dimen.tab_view_thumbnail_height)); + mActivity.getWindowManager().getDefaultDisplay().getHeight()); + } + } + + void showNavScreen() { + captureTab(mActiveTab); + mNavScreen = new NavScreen(mActivity, mUiController, this); + WebView web = getWebView(); + if (web != null) { + int w = web.getWidth(); + int h = web.getHeight(); + mNavScreen.setTabDimensions((int) (w * NAV_TAB_SCALE), + (int) (h * NAV_TAB_SCALE)); + } + // Add the custom view to its container. + mCustomViewContainer.addView(mNavScreen, COVER_SCREEN_GRAVITY_CENTER); + ObjectAnimator animx = ObjectAnimator.ofFloat(mContentView, + "scaleX", 1.0f, 0.85f); + ObjectAnimator animy = ObjectAnimator.ofFloat(mContentView, + "scaleY", 1.0f, 0.85f); + AnimatorSet anims = new AnimatorSet(); + anims.setDuration(200); + anims.addListener(new AnimatorListener() { + + @Override + public void onAnimationCancel(Animator animation) { + finishShowNavScreen(); + } + + @Override + public void onAnimationEnd(Animator animation) { + finishShowNavScreen(); + } + + @Override + public void onAnimationRepeat(Animator animation) { + } + + @Override + public void onAnimationStart(Animator animation) { + } + }); + anims.playTogether(animx, animy); + anims.start(); + } + + private void finishShowNavScreen() { + // Hide the content view. + mContentView.setVisibility(View.GONE); + mContentView.setScaleX(1.0f); + mContentView.setScaleY(1.0f); + // Finally show the custom view container. + mCustomViewContainer.setVisibility(View.VISIBLE); + mCustomViewContainer.bringToFront(); + } + + void hideNavScreen(boolean animateToPage) { + if (mNavScreen == null) return; + if (animateToPage) { + ObjectAnimator animx = ObjectAnimator.ofFloat(mNavScreen, "scaleX", + 1.0f, 1.2f); + ObjectAnimator animy = ObjectAnimator.ofFloat(mNavScreen, "scaleY", + 1.0f, 1.2f); + AnimatorSet anims = new AnimatorSet(); + anims.setDuration(200); + anims.addListener(new AnimatorListener() { + + @Override + public void onAnimationCancel(Animator animation) { + finishHideNavScreen(); + } + + @Override + public void onAnimationEnd(Animator animation) { + finishHideNavScreen(); + } + + @Override + public void onAnimationRepeat(Animator animation) { + } + + @Override + public void onAnimationStart(Animator animation) { + } + }); + anims.playTogether(animx, animy); + anims.start(); + } else { + finishHideNavScreen(); } + + } + + private void finishHideNavScreen() { + // Hide the custom view. + mNavScreen.setVisibility(View.GONE); + // Remove the custom view from its container. + mCustomViewContainer.removeView(mNavScreen); + mNavScreen = null; + mCustomViewContainer.setVisibility(View.GONE); + // Show the content view. + mContentView.setVisibility(View.VISIBLE); } } diff --git a/src/com/android/browser/TitleBarPhone.java b/src/com/android/browser/TitleBarPhone.java index 875e4b5..0eb2d1a 100644 --- a/src/com/android/browser/TitleBarPhone.java +++ b/src/com/android/browser/TitleBarPhone.java @@ -134,7 +134,7 @@ public class TitleBarPhone extends TitleBarBase implements OnFocusChangeListener } } super.onFocusChange(v, hasFocus); - if (mUseQuickControls && !hasFocus) { + if (!hasFocus) { mBaseUi.hideTitleBar(); } } diff --git a/src/com/android/browser/UiController.java b/src/com/android/browser/UiController.java index ed5fa6a..2b3ee69 100644 --- a/src/com/android/browser/UiController.java +++ b/src/com/android/browser/UiController.java @@ -44,6 +44,8 @@ public interface UiController extends BookmarksHistoryCallbacks { Tab openIncognitoTab(); + void setActiveTab(Tab tab); + boolean switchToTab(int tabIndex); void closeCurrentTab(); |