diff options
author | Michael Kolb <kolby@google.com> | 2010-08-04 17:54:03 -0700 |
---|---|---|
committer | Michael Kolb <kolby@google.com> | 2010-08-06 11:19:45 -0700 |
commit | a2b2ba8da913f26c820e49d3e43158e2fe6ebeba (patch) | |
tree | 4d6f5f3482ab53e5dfdc1bd8ff2e1d16395c5f2d | |
parent | ed9f333da9d4817f94758fb7eb3e4129b6fc30a2 (diff) | |
download | android_packages_apps_Gello-a2b2ba8da913f26c820e49d3e43158e2fe6ebeba.tar.gz android_packages_apps_Gello-a2b2ba8da913f26c820e49d3e43158e2fe6ebeba.tar.bz2 android_packages_apps_Gello-a2b2ba8da913f26c820e49d3e43158e2fe6ebeba.zip |
UI revision for tabbed browsing
bug # http://b/issue?id=2712871
separated tab bar from url bar
subclassed webview for scroll listener
added search button support
Change-Id: Ib9bd0c7e815e2ef08cdd20334daf61263cd52938
21 files changed, 973 insertions, 729 deletions
diff --git a/res/drawable-mdpi/tab_selected_bg.9.png b/res/drawable-mdpi/tab_selected_bg.9.png Binary files differindex 5e6b1ed8..b843242d 100644 --- a/res/drawable-mdpi/tab_selected_bg.9.png +++ b/res/drawable-mdpi/tab_selected_bg.9.png diff --git a/res/drawable-mdpi/tab_unselected_bg.9.png b/res/drawable-mdpi/tab_unselected_bg.9.png Binary files differindex c19443a9..872117a8 100644 --- a/res/drawable-mdpi/tab_unselected_bg.9.png +++ b/res/drawable-mdpi/tab_unselected_bg.9.png diff --git a/res/drawable/browserbarbutton.xml b/res/drawable/browserbarbutton.xml index 35a6f48b..5c9eca09 100644 --- a/res/drawable/browserbarbutton.xml +++ b/res/drawable/browserbarbutton.xml @@ -16,6 +16,6 @@ <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" - android:drawable="@drawable/button_selected" /> + android:drawable="@drawable/button_bg_selected" /> <item android:state_pressed="false" android:drawable="@drawable/clear" /> </selector> diff --git a/res/drawable/button_bg_selected.xml b/res/drawable/button_bg_selected.xml new file mode 100644 index 00000000..17c1fc3f --- /dev/null +++ b/res/drawable/button_bg_selected.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> + <!-- + 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. + --> +<shape + xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="oval"> + <solid + android:color="#ff4d83ba" /> +</shape>
\ No newline at end of file diff --git a/res/drawable/clear.xml b/res/drawable/clear.xml index 5973f5c1..267db106 100644 --- a/res/drawable/clear.xml +++ b/res/drawable/clear.xml @@ -18,6 +18,6 @@ state --> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#00000000"/> - <padding android:left="9dp" android:top="9dp" - android:right="9dp" android:bottom="9dp" /> + <padding android:left="4dp" android:top="4dp" + android:right="4dp" android:bottom="4dp" /> </shape> diff --git a/res/drawable/ic_menu_showurl.png b/res/drawable/ic_menu_showurl.png Binary files differnew file mode 100644 index 00000000..4b346a86 --- /dev/null +++ b/res/drawable/ic_menu_showurl.png diff --git a/res/drawable/progress.xml b/res/drawable/progress.xml index dd7c375f..fd89317e 100644 --- a/res/drawable/progress.xml +++ b/res/drawable/progress.xml @@ -14,16 +14,17 @@ limitations under the License. --> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> - +<!-- <item android:id="@android:id/background"> <shape> - <solid android:color="#ffffffff"/> + <solid android:color="#804d83ba"/> </shape> </item> + --> <item android:id="@android:id/progress"> <clip> <shape> - <solid android:color="#ff94b73f"/> + <solid android:color="#804d83ba"/> </shape> </clip> </item> diff --git a/res/drawable/tab_background.xml b/res/drawable/tab_background.xml new file mode 100644 index 00000000..65db25ef --- /dev/null +++ b/res/drawable/tab_background.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_selected="true" + android:drawable="@drawable/tab_selected_bg" /> + <item android:state_selected="false" + android:drawable="@drawable/tab_unselected_bg" /> +</selector> diff --git a/res/layout-land/title_bar_tabbed.xml b/res/layout-land/title_bar_tabbed.xml deleted file mode 100644 index 853dbeb4..00000000 --- a/res/layout-land/title_bar_tabbed.xml +++ /dev/null @@ -1,87 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - <!-- - Copyright 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. - --> -<LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/tabbedtitleland" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" - android:paddingLeft="6dip" - android:paddingRight="6dip" - android:background="#ffdddddd"> - <ImageButton - android:id="@+id/back" - android:src="@drawable/ic_arrow_left" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginRight="6dip" - android:background="@drawable/browserbarbutton" /> - <ImageButton - android:id="@+id/forward" - android:src="@drawable/ic_arrow_right" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginRight="6dip" - android:background="@drawable/browserbarbutton" /> - <ImageButton - android:id="@+id/star" - android:src="@drawable/ic_star" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginRight="6dip" - android:background="@drawable/browserbarbutton" /> - <com.android.browser.TabScrollView - android:id="@+id/tabs" - android:layout_width="0dip" - android:layout_weight="1.0" - android:layout_height="wrap_content" - android:orientation="horizontal" /> - <com.android.browser.UrlInputView - android:id="@+id/editurl" - android:layout_width="0dip" - android:layout_weight="1.0" - android:layout_height="wrap_content" - android:layout_marginLeft="3dip" - android:textAppearance="?android:attr/textAppearanceMedium" - android:textColor="@color/black" - android:gravity="center_vertical" - android:singleLine="true" - android:ellipsize="end" - android:lines="1" - android:scrollHorizontally="true" - android:visibility="gone" - android:background="@drawable/textfield_stroke" - android:inputType="textUri" - android:imeOptions="actionGo" /> - <ImageButton - android:id="@+id/newtab" - android:src="@drawable/ic_menu_new_window" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginRight="6dip" - android:background="@drawable/browserbarbutton" /> - <ImageButton - android:id="@+id/menu" - android:src="@drawable/ic_menu" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginRight="6dip" - android:background="@drawable/browserbarbutton" /> - <ImageButton - android:id="@+id/all_btn" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:scaleType="center" - android:background="@drawable/browserbarbutton" - android:src="@drawable/ic_pages" /> -</LinearLayout> diff --git a/res/layout/tab_bar.xml b/res/layout/tab_bar.xml new file mode 100644 index 00000000..60f08efe --- /dev/null +++ b/res/layout/tab_bar.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> + <!-- + Copyright 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. + --> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/tabbarcontent" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="#ffdddddd" + android:orientation="horizontal"> + <com.android.browser.TabScrollView + android:id="@+id/tabs" + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1.0" + android:orientation="horizontal" /> + <ImageButton + android:id="@+id/showurl" + android:src="@drawable/ic_menu_showurl" + android:layout_width="48dip" + android:layout_height="48dip" + android:layout_marginLeft="6dip" + android:background="@drawable/browserbarbutton" + android:visibility="invisible" /> + <ImageButton + android:id="@+id/newtab" + android:src="@drawable/ic_menu_new_window" + android:layout_width="48dip" + android:layout_height="48dip" + android:layout_marginLeft="6dip" + android:layout_marginRight="6dip" + android:background="@drawable/browserbarbutton" /> +</LinearLayout> diff --git a/res/layout/tab_title.xml b/res/layout/tab_title.xml index 28b553d0..6166d245 100644 --- a/res/layout/tab_title.xml +++ b/res/layout/tab_title.xml @@ -14,9 +14,10 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="0dip" android:layout_weight="1.0" - android:layout_height="wrap_content" + android:layout_height="match_parent" android:gravity="center_vertical" - android:orientation="horizontal"> + android:orientation="horizontal" + android:background="@drawable/tab_background" > <ImageView android:id="@+id/favicon" android:layout_width="20dip" @@ -30,21 +31,15 @@ android:visibility="gone" /> <TextView android:id="@+id/title" - android:layout_height="wrap_content" + android:layout_height="match_parent" android:layout_width="0dip" android:layout_weight="1.0" android:layout_marginLeft="3dip" - android:textAppearance="?android:attr/textAppearanceMedium" + android:textAppearance="?android:attr/textAppearanceSmall" android:textColor="@color/black" - android:gravity="center_vertical" + android:gravity="center_vertical|center_horizontal" android:singleLine="true" android:ellipsize="end" /> - <com.android.browser.CircularProgressView - android:id="@+id/stop" - android:layout_width="36dip" - android:layout_height="36dip" - android:background="@null" - android:src="@drawable/progress_stop" /> <ImageView android:id="@+id/close" android:layout_width="wrap_content" diff --git a/res/layout/title_bar_tabbed.xml b/res/layout/title_bar_tabbed.xml deleted file mode 100644 index fc786e0e..00000000 --- a/res/layout/title_bar_tabbed.xml +++ /dev/null @@ -1,97 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - <!-- - Copyright 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. - --> -<LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/tabbedtitleport" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:background="#ffdddddd"> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal"> - <com.android.browser.TabScrollView - android:id="@+id/tabs" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_weight="1.0" - android:orientation="horizontal" /> - <ImageButton - android:id="@+id/newtab" - android:src="@drawable/ic_menu_new_window" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:background="@drawable/browserbarbutton" /> - </LinearLayout> - <LinearLayout - android:id="@+id/urlbar" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" - android:paddingLeft="6dip" - android:paddingRight="6dip"> - <ImageButton - android:id="@+id/back" - android:src="@drawable/ic_arrow_left" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginRight="6dip" - android:background="@drawable/browserbarbutton" /> - <ImageButton - android:id="@+id/forward" - android:src="@drawable/ic_arrow_right" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginRight="6dip" - android:background="@drawable/browserbarbutton" /> - <ImageButton - android:id="@+id/star" - android:src="@drawable/ic_star" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginRight="6dip" - android:background="@drawable/browserbarbutton" /> - <com.android.browser.UrlInputView - android:id="@+id/editurl" - android:layout_width="0dip" - android:layout_weight="1.0" - android:layout_height="wrap_content" - android:layout_marginLeft="3dip" - android:textAppearance="?android:attr/textAppearanceMedium" - android:textColor="@color/black" - android:gravity="center_vertical" - android:singleLine="true" - android:ellipsize="end" - android:lines="1" - android:scrollHorizontally="true" - android:visibility="gone" - android:background="@drawable/textfield_nostroke" - android:inputType="textUri" - android:imeOptions="actionGo" /> - <ImageButton - android:id="@+id/menu" - android:src="@drawable/ic_menu" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginRight="6dip" - android:background="@drawable/browserbarbutton" /> - <ImageButton - android:id="@+id/all_btn" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:scaleType="center" - android:background="@drawable/browserbarbutton" - android:src="@drawable/ic_pages" /> - </LinearLayout> -</LinearLayout> diff --git a/res/layout/url_bar.xml b/res/layout/url_bar.xml new file mode 100644 index 00000000..9bf617dd --- /dev/null +++ b/res/layout/url_bar.xml @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="utf-8"?> + <!-- + Copyright 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. + --> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/content" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + <LinearLayout + android:id="@+id/taburlbar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:background="#ffdddddd" + android:paddingLeft="6dip" + android:paddingRight="6dip" + android:paddingTop="2dip" + android:paddingBottom="2dip"> + <ImageButton + android:id="@+id/back" + android:src="@drawable/ic_arrow_left" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_marginRight="6dip" + android:background="@drawable/browserbarbutton" /> + <ImageButton + android:id="@+id/forward" + android:src="@drawable/ic_arrow_right" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_marginRight="6dip" + android:background="@drawable/browserbarbutton" /> + <LinearLayout + android:id="@+id/urlbar" + android:layout_width="0dip" + android:layout_height="match_parent" + android:layout_weight="1.0" + android:orientation="horizontal" + android:background="#ffffffff"> + <ImageButton + android:id="@+id/star" + android:src="@drawable/ic_star" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_marginLeft="6dip" + android:background="@drawable/browserbarbutton" /> + <ImageView + android:id="@+id/lock" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="6dip" + android:visibility="gone" /> + <com.android.browser.UrlInputView + android:id="@+id/editurl" + android:layout_width="0dip" + android:layout_weight="1.0" + android:layout_height="match_parent" + android:layout_marginLeft="6dip" + android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="@color/black" + android:hint="@string/search_hint" + android:gravity="center_vertical" + android:singleLine="true" + android:ellipsize="end" + android:lines="1" + android:scrollHorizontally="true" + android:background="@null" + android:inputType="textUri" + android:imeOptions="actionGo" /> + <ImageView + android:id="@+id/stop" + android:background="@drawable/browserbarbutton" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_marginLeft="6dip" + android:gravity="center_vertical" + android:src="@drawable/ic_stop" /> + <ImageButton + android:id="@+id/search" + android:src="@drawable/ic_btn_find" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:gravity="center_vertical" + android:layout_marginLeft="6dip" + android:layout_marginRight="6dip" + android:background="@drawable/browserbarbutton" /> + </LinearLayout> + <ImageButton + android:id="@+id/menu" + android:src="@drawable/ic_menu" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_marginLeft="6dip" + android:layout_marginRight="6dip" + android:background="@drawable/browserbarbutton" /> + <ImageButton + android:id="@+id/all_btn" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:scaleType="center" + android:layout_marginLeft="6dip" + android:background="@drawable/browserbarbutton" + android:src="@drawable/ic_pages" /> + </LinearLayout> + <ImageView + android:id="@+id/progress" + android:layout_width="match_parent" + android:layout_height="8dip" + android:src="@drawable/progress" + android:visibility="gone" /> +</LinearLayout> diff --git a/res/values/dimensions.xml b/res/values/dimensions.xml new file mode 100644 index 00000000..2fc3233f --- /dev/null +++ b/res/values/dimensions.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. +--> +<resources + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- The width of a selected tab --> + <dimen + name="tab_width_selected">300dp</dimen> + <!-- The width of an unselected tab --> + <dimen + name="tab_width_unselected">300dp</dimen> +</resources>
\ No newline at end of file diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java index b9f5f01d..40ada94b 100644 --- a/src/com/android/browser/BrowserActivity.java +++ b/src/com/android/browser/BrowserActivity.java @@ -59,31 +59,30 @@ import android.os.Handler; import android.os.Message; import android.os.PowerManager; import android.os.Process; -import android.os.ServiceManager; import android.os.SystemClock; import android.provider.Browser; import android.provider.ContactsContract; +import android.provider.ContactsContract.Intents.Insert; import android.provider.Downloads; import android.provider.MediaStore; -import android.provider.ContactsContract.Intents.Insert; import android.speech.RecognizerResultsIntent; import android.text.TextUtils; import android.text.format.DateFormat; import android.util.Log; import android.util.Patterns; import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; +import android.view.MenuItem.OnMenuItemClickListener; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.MenuItem.OnMenuItemClickListener; import android.view.accessibility.AccessibilityManager; import android.webkit.CookieManager; import android.webkit.CookieSyncManager; @@ -103,6 +102,7 @@ import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; +import com.android.browser.ScrollWebView.ScrollListener; import com.android.common.Search; import com.android.common.speech.LoggingEvents; @@ -216,13 +216,14 @@ public class BrowserActivity extends Activity // Create the tab control and our initial tab mTabControl = new TabControl(this); - - if (mXLargeScreenSize) { - mTitleBar = new TitleBarXLarge(this, mTabControl); + mTitleBar = new TitleBarXLarge(this); + mTitleBar.setProgress(100); + mFakeTitleBar = new TitleBarXLarge(this); + mTabBar = new TabBar(this, mTabControl, (TitleBarXLarge) mFakeTitleBar); LinearLayout layout = (LinearLayout) mBrowserFrameLayout. findViewById(R.id.vertical_layout); - layout.addView(mTitleBar, 0, new LinearLayout.LayoutParams( + layout.addView(mTabBar, 0, new LinearLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); } else { @@ -234,7 +235,6 @@ public class BrowserActivity extends Activity mFakeTitleBar = new TitleBar(this); } - // Open the icon database and retain all the bookmark urls for favicons retainIconsOnStartup(); @@ -394,6 +394,10 @@ public class BrowserActivity extends Activity mSystemAllowGeolocationOrigins.start(); } + ScrollListener getScrollListener() { + return mTabBar; + } + /** * Feed the previously stored results strings to the BrowserProvider so that * the SearchDialog will show them instead of the standard searches. @@ -724,20 +728,14 @@ public class BrowserActivity extends Activity /* package */ void showVoiceTitleBar(String title) { mTitleBar.setInVoiceMode(true); mTitleBar.setDisplayTitle(title); - - if (!mXLargeScreenSize) { - mFakeTitleBar.setInVoiceMode(true); - mFakeTitleBar.setDisplayTitle(title); - } + mFakeTitleBar.setInVoiceMode(true); + mFakeTitleBar.setDisplayTitle(title); } /* package */ void revertVoiceTitleBar() { mTitleBar.setInVoiceMode(false); mTitleBar.setDisplayTitle(mUrl); - - if (!mXLargeScreenSize) { - mFakeTitleBar.setInVoiceMode(false); - mFakeTitleBar.setDisplayTitle(mUrl); - } + mFakeTitleBar.setInVoiceMode(false); + mFakeTitleBar.setDisplayTitle(mUrl); } /* package */ static String fixUrl(String inUrl) { // FIXME: Converting the url to lower case @@ -800,7 +798,7 @@ public class BrowserActivity extends Activity * would change its appearance, use a different TitleBar to show overlayed * at the top of the screen, when the menu is open or the page is loading. */ - private TitleBar mFakeTitleBar; + private TitleBarBase mFakeTitleBar; /** * Keeps track of whether the options menu is open. This is important in @@ -856,16 +854,8 @@ public class BrowserActivity extends Activity return true; } - private void rebuildTitleBar() { - if (mXLargeScreenSize) { - ((TitleBarXLarge) mTitleBar).rebuildLayout(); - } - } - - private void showFakeTitleBar() { - if (mXLargeScreenSize) return; - if (mFakeTitleBar.getParent() == null && mActiveTabsPage == null - && !mActivityInPause) { + void showFakeTitleBar() { + if (!isFakeTitleBarShowing() && mActiveTabsPage == null && !mActivityInPause) { WebView mainView = mTabControl.getCurrentWebView(); // if there is no current WebView, don't show the faked title bar; if (mainView == null) { @@ -878,23 +868,26 @@ public class BrowserActivity extends Activity // find or select dialog. return; } - - WindowManager manager - = (WindowManager) getSystemService(Context.WINDOW_SERVICE); - - // Add the title bar to the window manager so it can receive touches - // while the menu is up - WindowManager.LayoutParams params - = new WindowManager.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT, - WindowManager.LayoutParams.TYPE_APPLICATION, - WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, - PixelFormat.TRANSLUCENT); - params.gravity = Gravity.TOP; - boolean atTop = mainView.getScrollY() == 0; - params.windowAnimations = atTop ? 0 : R.style.TitleBar; - manager.addView(mFakeTitleBar, params); + if (mXLargeScreenSize) { + mContentView.addView(mFakeTitleBar); + mTabBar.onShowTitleBar(); + } else { + WindowManager manager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); + + // Add the title bar to the window manager so it can receive + // touches + // while the menu is up + WindowManager.LayoutParams params = + new WindowManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT, + WindowManager.LayoutParams.TYPE_APPLICATION, + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, + PixelFormat.TRANSLUCENT); + params.gravity = Gravity.TOP; + boolean atTop = mainView.getScrollY() == 0; + params.windowAnimations = atTop ? 0 : R.style.TitleBar; + manager.addView(mFakeTitleBar, params); + } } } @@ -911,21 +904,34 @@ public class BrowserActivity extends Activity } } - private void hideFakeTitleBar() { - if (mXLargeScreenSize || mFakeTitleBar.getParent() == null) return; - WindowManager.LayoutParams params = (WindowManager.LayoutParams) - mFakeTitleBar.getLayoutParams(); - WebView mainView = mTabControl.getCurrentWebView(); - // Although we decided whether or not to animate based on the current - // scroll position, the scroll position may have changed since the - // fake title bar was displayed. Make sure it has the appropriate - // animation/lack thereof before removing. - params.windowAnimations = mainView != null && mainView.getScrollY() == 0 - ? 0 : R.style.TitleBar; - WindowManager manager - = (WindowManager) getSystemService(Context.WINDOW_SERVICE); - manager.updateViewLayout(mFakeTitleBar, params); - manager.removeView(mFakeTitleBar); + void stopScrolling() { + ((ScrollWebView) mTabControl.getCurrentWebView()).stopScroll(); + } + + void hideFakeTitleBar() { + if (!isFakeTitleBarShowing()) return; + if (mXLargeScreenSize) { + mContentView.removeView(mFakeTitleBar); + mTabBar.onHideTitleBar(); + } else { + WindowManager.LayoutParams params = + (WindowManager.LayoutParams) mFakeTitleBar.getLayoutParams(); + WebView mainView = mTabControl.getCurrentWebView(); + // Although we decided whether or not to animate based on the + // current + // scroll position, the scroll position may have changed since the + // fake title bar was displayed. Make sure it has the appropriate + // animation/lack thereof before removing. + params.windowAnimations = + mainView != null && mainView.getScrollY() == 0 ? 0 : R.style.TitleBar; + WindowManager manager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); + manager.updateViewLayout(mFakeTitleBar, params); + manager.removeView(mFakeTitleBar); + } + } + + boolean isFakeTitleBarShowing() { + return (mFakeTitleBar.getParent() != null); } /** @@ -1071,7 +1077,6 @@ public class BrowserActivity extends Activity showHttpAuthentication(mHttpAuthHandler, null, null, title, name, password, focusId); } - rebuildTitleBar(); } @Override @@ -1547,21 +1552,19 @@ public class BrowserActivity extends Activity */ public void closeDialogs() { if (!(closeDialog(mFindDialog) || closeDialog(mSelectDialog))) return; - if (!mXLargeScreenSize) { - // If the Find was being performed in the main WebView, replace the - // embedded title bar. - Tab currentTab = mTabControl.getCurrentTab(); - if (currentTab.getSubWebView() == null) { - WebView mainView = currentTab.getWebView(); - if (mainView != null) { - mainView.setEmbeddedTitleBar(mTitleBar); - } + // If the Find was being performed in the main WebView, replace the + // embedded title bar. + Tab currentTab = mTabControl.getCurrentTab(); + if (currentTab.getSubWebView() == null) { + WebView mainView = currentTab.getWebView(); + if (mainView != null) { + mainView.setEmbeddedTitleBar(mTitleBar); } } mMenuState = R.id.MAIN_MENU; if (mInLoad) { // The title bar was hidden, because otherwise it would cover up the - // find or select dialog. Now that the dialog has been removed, + // find or select dialog. Now that the dialog has been removed, // show the fake title bar once again. showFakeTitleBar(); } @@ -1807,10 +1810,8 @@ public class BrowserActivity extends Activity ViewGroup.LayoutParams.WRAP_CONTENT)); } - if (!mXLargeScreenSize){ - WebView view = t.getWebView(); - view.setEmbeddedTitleBar(mTitleBar); - } + WebView view = t.getWebView(); + view.setEmbeddedTitleBar(mTitleBar); if (t.isInVoiceSearchMode()) { showVoiceTitleBar(t.getVoiceDisplayTitle()); } else { @@ -1818,6 +1819,9 @@ public class BrowserActivity extends Activity } // Request focus on the top window. t.getTopWindow().requestFocus(); + if (mTabControl.getTabChangeListener() != null) { + mTabControl.getTabChangeListener().onCurrentTab(t); + } } // Attach a sub window to the main WebView of the given tab. @@ -1836,11 +1840,9 @@ public class BrowserActivity extends Activity mErrorConsoleContainer.removeView(errorConsole); } - if (!mXLargeScreenSize) { - WebView view = t.getWebView(); - if (view != null) { - view.setEmbeddedTitleBar(null); - } + WebView view = t.getWebView(); + if (view != null) { + view.setEmbeddedTitleBar(null); } } @@ -2079,9 +2081,7 @@ public class BrowserActivity extends Activity // If we are in voice search mode, the title has already been set. if (mTabControl.getCurrentTab().isInVoiceSearchMode()) return; mTitleBar.setDisplayTitle(url); - if (!mXLargeScreenSize) { - mFakeTitleBar.setDisplayTitle(url); - } + mFakeTitleBar.setDisplayTitle(url); } /** @@ -2124,9 +2124,7 @@ public class BrowserActivity extends Activity // Set the favicon in the title bar. void setFavicon(Bitmap icon) { mTitleBar.setFavicon(icon); - if (!mXLargeScreenSize) { - mFakeTitleBar.setFavicon(icon); - } + mFakeTitleBar.setFavicon(icon); } /** @@ -2803,14 +2801,11 @@ public class BrowserActivity extends Activity // ------------------------------------------------------------------------- void onProgressChanged(WebView view, int newProgress) { - if (mXLargeScreenSize) { - mTitleBar.setProgress(newProgress); - } else { - // On the phone, the fake title bar will always cover up the - // regular title bar (or the regular one is offscreen), so only the - // fake title bar needs to change its progress - mFakeTitleBar.setProgress(newProgress); - } + + // On the phone, the fake title bar will always cover up the + // regular title bar (or the regular one is offscreen), so only the + // fake title bar needs to change its progress + mFakeTitleBar.setProgress(newProgress); if (newProgress == 100) { // onProgressChanged() may continue to be called after the main @@ -3246,9 +3241,7 @@ public class BrowserActivity extends Activity d = mMixLockIcon; } mTitleBar.setLock(d); - if (!mXLargeScreenSize) { - mFakeTitleBar.setLock(d); - } + mFakeTitleBar.setLock(d); } /** @@ -4269,6 +4262,7 @@ public class BrowserActivity extends Activity private Toast mStopToast; private TitleBarBase mTitleBar; + private TabBar mTabBar; private LinearLayout mErrorConsoleContainer = null; private boolean mShouldShowErrorConsole = false; diff --git a/src/com/android/browser/ScrollWebView.java b/src/com/android/browser/ScrollWebView.java new file mode 100644 index 00000000..16404aa8 --- /dev/null +++ b/src/com/android/browser/ScrollWebView.java @@ -0,0 +1,121 @@ +/* + * 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.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.webkit.WebView; + +import java.util.Map; + +/** + * Manage WebView scroll events + */ +public class ScrollWebView extends WebView { + + private ScrollListener mScrollListener; + private boolean mIsCancelled; + private Runnable mScrollRunnable; + + /** + * @param context + * @param attrs + * @param defStyle + * @param javascriptInterfaces + */ + public ScrollWebView(Context context, AttributeSet attrs, int defStyle, + Map<String, Object> javascriptInterfaces, boolean privateBrowsing) { + super(context, attrs, defStyle, javascriptInterfaces, privateBrowsing); + } + + /** + * @param context + * @param attrs + * @param defStyle + */ + public ScrollWebView(Context context, AttributeSet attrs, int defStyle, + boolean privateBrowsing) { + super(context, attrs, defStyle, privateBrowsing); + } + + /** + * @param context + * @param attrs + */ + public ScrollWebView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + /** + * @param context + */ + public ScrollWebView(Context context) { + super(context); + } + + @Override + public void setEmbeddedTitleBar(final View title) { + super.setEmbeddedTitleBar(title); + if (title != null && mScrollListener != null) { + // allow the scroll listener to initialize its state + post(new Runnable() { + @Override + public void run() { + mScrollListener.onScroll((title.getHeight() == 0 || + getVisibleTitleHeight() > 0)); + } + }); + } + } + + @Override + public void stopScroll() { + mIsCancelled = true; + super.stopScroll(); + } + + @Override + protected void onScrollChanged(int l, final int t, int ol, int ot) { + super.onScrollChanged(l, t, ol, ot); + if (!mIsCancelled) { + post(mScrollRunnable); + } else { + mIsCancelled = false; + } + } + + void setScrollListener(ScrollListener l) { + mScrollListener = l; + if (mScrollListener != null) { + mScrollRunnable = new Runnable() { + public void run() { + if (!mIsCancelled) { + mScrollListener.onScroll(getVisibleTitleHeight() > 0); + } + } + }; + } + } + + // callback for scroll events + + interface ScrollListener { + public void onScroll(boolean titleVisible); + } + +} diff --git a/src/com/android/browser/TabBar.java b/src/com/android/browser/TabBar.java new file mode 100644 index 00000000..f73185fb --- /dev/null +++ b/src/com/android/browser/TabBar.java @@ -0,0 +1,416 @@ +/* + * 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.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.Color; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; +import android.graphics.drawable.PaintDrawable; +import android.view.ContextMenu; +import android.view.LayoutInflater; +import android.view.MenuInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.webkit.WebView; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.android.browser.ScrollWebView.ScrollListener; +import com.android.browser.TabControl.TabChangeListener; + +import java.util.HashMap; +import java.util.Map; + +/** + * tabbed title bar for xlarge screen browser + */ +public class TabBar extends LinearLayout + implements TabChangeListener, ScrollListener, OnClickListener { + + private static final int PROGRESS_MAX = 100; + + private static final int TAB_WIDTH_SELECTED = 300; + private static final int TAB_WIDTH_UNSELECTED = 300; + + private BrowserActivity mBrowserActivity; + + private final float mTabWidthSelected; + private final float mTabWidthUnselected; + + private TitleBarXLarge mTitleBar; + + private TabScrollView mTabs; + private View mNewButton; + private View mShowUrlButton; + private TabControl mControl; + + private Map<Tab, TabViewData> mTabMap; + + private float mDensityScale; + private boolean mUserRequestedUrlbar; + private boolean mTitleVisible; + + public TabBar(BrowserActivity context, TabControl tabcontrol, TitleBarXLarge titlebar) { + super(context); + Resources res = context.getResources(); + mTabWidthSelected = res.getDimension(R.dimen.tab_width_selected); + mTabWidthUnselected = res.getDimension(R.dimen.tab_width_unselected); + + mTitleBar = titlebar; + mTitleBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, + LayoutParams.WRAP_CONTENT)); + mDensityScale = context.getResources().getDisplayMetrics().density; + mTabMap = new HashMap<Tab, TabViewData>(); + mBrowserActivity = context; + mControl = tabcontrol; + Resources resources = context.getResources(); + LayoutInflater factory = LayoutInflater.from(context); + factory.inflate(R.layout.tab_bar, this); + mTabs = (TabScrollView) findViewById(R.id.tabs); + mNewButton = findViewById(R.id.newtab); + mShowUrlButton = findViewById(R.id.showurl); + + // TODO: Change enabled states based on whether you can go + // back/forward. Probably should be done inside onPageStarted. + + mNewButton.setOnClickListener(this); + mShowUrlButton.setOnClickListener(this); + + // build tabs + int tabcount = mControl.getTabCount(); + for (int i = 0; i < tabcount; i++) { + Tab tab = mControl.getTab(i); + TabViewData data = buildTab(tab); + TabView tv = buildView(data); + } + mTabs.setSelectedTab(mControl.getCurrentIndex()); + + // register the tab change listener + mControl.setOnTabChangeListener(this); + mUserRequestedUrlbar = false; + mTitleVisible = true; + } + + public void onClick(View view) { + if (mShowUrlButton == view) { + mBrowserActivity.stopScrolling(); + mBrowserActivity.showFakeTitleBar(); + mUserRequestedUrlbar = true; + } else if (mNewButton == view) { + mBrowserActivity.openTabToHomePage(); + } else if (mTabs.getSelectedTab() == view) { + mBrowserActivity.showFakeTitleBar(); + mTitleBar.requestUrlInputFocus(); + } else { + TabViewData data = (TabViewData) view.getTag(); + int ix = mControl.getTabIndex(data.mTab); + mTabs.setSelectedTab(ix); + mBrowserActivity.switchToTab(ix); + } + } + + void onShowTitleBar() { + mShowUrlButton.setVisibility(View.INVISIBLE); + } + + void onHideTitleBar() { + mShowUrlButton.setVisibility(mTitleVisible ? View.INVISIBLE : View.VISIBLE); + Tab tab = mControl.getCurrentTab(); + tab.getWebView().requestFocus(); + mUserRequestedUrlbar = false; + } + + // UrlInputListener implementation + + @Override + public void createContextMenu(ContextMenu menu) { + MenuInflater inflater = mBrowserActivity.getMenuInflater(); + inflater.inflate(R.menu.title_context, menu); + mBrowserActivity.onCreateContextMenu(menu, this, null); + } + + private TabViewData buildTab(Tab tab) { + TabViewData data = new TabViewData(tab); + mTabMap.put(tab, data); + return data; + } + + private TabView buildView(final TabViewData data) { + TabView tv = new TabView(mBrowserActivity, data); + tv.setTag(data); + tv.setOnClickListener(this); + mTabs.addTab(tv); + return tv; + } + + /** + * View used in the tab bar + */ + class TabView extends LinearLayout implements OnClickListener { + + TabViewData mTabData; + View mTabContent; + TextView mTitle; + ImageView mIconView; + ImageView mLock; + ImageView mClose; + boolean mSelected; + boolean mInLoad; + + /** + * @param context + */ + public TabView(Context context, TabViewData tab) { + super(context); + mTabData = tab; + LayoutInflater inflater = LayoutInflater.from(mContext); + mTabContent = inflater.inflate(R.layout.tab_title, this); + mTitle = (TextView) mTabContent.findViewById(R.id.title); + mIconView = (ImageView) mTabContent.findViewById(R.id.favicon); + mLock = (ImageView) mTabContent.findViewById(R.id.lock); + mClose = (ImageView) mTabContent.findViewById(R.id.close); + mClose.setOnClickListener(this); + mSelected = false; + mInLoad = false; + // update the status + updateFromData(); + } + + @Override + public void onClick(View v) { + if (v == mClose) { + closeTab(); + } + } + + private void updateFromData() { + mTabData.mTabView = this; + if (mTabData.mUrl != null) { + setDisplayTitle(mTabData.mUrl); + } + if (mTabData.mTitle != null) { + setDisplayTitle(mTabData.mTitle); + } + setProgress(mTabData.mProgress); + if (mTabData.mIcon != null) { + setFavicon(mTabData.mIcon); + } + if (mTabData.mLock != null) { + setLock(mTabData.mLock); + } + } + + @Override + public void setSelected(boolean selected) { + mSelected = selected; + mClose.setVisibility(mSelected ? View.VISIBLE : View.GONE); + mTitle.setTextColor(mSelected ? Color.BLACK : Color.GRAY); + super.setSelected(selected); + setLayoutParams(new LayoutParams(selected ? + (int) (TAB_WIDTH_SELECTED * mDensityScale) + : (int) (TAB_WIDTH_UNSELECTED * mDensityScale), + LayoutParams.MATCH_PARENT)); + } + + void setDisplayTitle(String title) { + mTitle.setText(title); + } + + void setFavicon(Drawable d) { + mIconView.setImageDrawable(d); + } + + void setLock(Drawable d) { + if (null == d) { + mLock.setVisibility(View.GONE); + } else { + mLock.setImageDrawable(d); + mLock.setVisibility(View.VISIBLE); + } + } + + void setTitleCompoundDrawables(Drawable left, Drawable top, + Drawable right, Drawable bottom) { + mTitle.setCompoundDrawables(left, top, right, bottom); + } + + void setProgress(int newProgress) { + if (newProgress >= PROGRESS_MAX) { + mInLoad = false; + } else { + if (!mInLoad && getWindowToken() != null) { + mInLoad = true; + } + } + } + + private void closeTab() { + if (mTabData.mTab == mControl.getCurrentTab()) { + mBrowserActivity.closeCurrentWindow(); + } else { + mBrowserActivity.closeTab(mTabData.mTab); + } + } + + } + + /** + * Store tab state within the title bar + */ + class TabViewData { + + Tab mTab; + TabView mTabView; + int mProgress; + Drawable mIcon; + Drawable mLock; + String mTitle; + String mUrl; + + TabViewData(Tab tab) { + mTab = tab; + } + + void setUrlAndTitle(String url, String title) { + mUrl = url; + mTitle = title; + if (mTabView != null) { + if (title != null) { + mTabView.setDisplayTitle(title); + } else if (url != null) { + mTabView.setDisplayTitle(url); + } + } + } + + void setProgress(int newProgress) { + mProgress = newProgress; + if (mTabView != null) { + mTabView.setProgress(mProgress); + } + } + + void setFavicon(Bitmap icon) { + Drawable[] array = new Drawable[3]; + array[0] = new PaintDrawable(Color.BLACK); + array[1] = new PaintDrawable(Color.WHITE); + if (icon == null) { +// array[2] = mGenericFavicon; + } else { + array[2] = new BitmapDrawable(icon); + } + LayerDrawable d = new LayerDrawable(array); + d.setLayerInset(1, 1, 1, 1, 1); + d.setLayerInset(2, 2, 2, 2, 2); + mIcon = d; + if (mTabView != null) { + mTabView.setFavicon(mIcon); + } + } + + } + + // TabChangeListener implementation + + @Override + public void onCurrentTab(Tab tab) { + mTabs.setSelectedTab(mControl.getCurrentIndex()); + TabViewData tvd = mTabMap.get(tab); + if (tvd != null) { + tvd.setProgress(tvd.mProgress); + // update the scroll state + WebView webview = tab.getWebView(); + onScroll(webview.getVisibleTitleHeight() > 0); + } + } + + @Override + public void onFavicon(Tab tab, Bitmap favicon) { + TabViewData tvd = mTabMap.get(tab); + if (tvd != null) { + tvd.setFavicon(favicon); + } + } + + @Override + public void onNewTab(Tab tab) { + TabViewData tvd = buildTab(tab); + buildView(tvd); + mShowUrlButton.setVisibility(View.INVISIBLE); + } + + @Override + public void onProgress(Tab tab, int progress) { + TabViewData tvd = mTabMap.get(tab); + if (tvd != null) { + tvd.setProgress(progress); + } + } + + @Override + public void onRemoveTab(Tab tab) { + TabViewData tvd = mTabMap.get(tab); + TabView tv = tvd.mTabView; + if (tv != null) { + mTabs.removeTab(tv); + } + mTabMap.remove(tab); + } + + @Override + public void onUrlAndTitle(Tab tab, String url, String title) { + TabViewData tvd = mTabMap.get(tab); + if (tvd != null) { + tvd.setUrlAndTitle(url, title); + } + } + + @Override + public void onPageFinished(Tab tab) { + } + + @Override + public void onPageStarted(Tab tab) { + } + + + private boolean isLoading() { + return mTabMap.get(mControl.getCurrentTab()).mTabView.mInLoad; + } + + // webview scroll listener + + @Override + public void onScroll(boolean titleVisible) { + mTitleVisible = titleVisible; + boolean buttonVisible = (mShowUrlButton.getVisibility() == View.VISIBLE); + if (!buttonVisible && !mTitleVisible && !isLoading()) { + mShowUrlButton.setVisibility(View.VISIBLE); + if (mUserRequestedUrlbar) { + mBrowserActivity.hideFakeTitleBar(); + } + } else if (mTitleVisible && !isLoading()) { + mShowUrlButton.setVisibility(View.INVISIBLE); + } + } + +} diff --git a/src/com/android/browser/TabControl.java b/src/com/android/browser/TabControl.java index d850b1ef..333ce911 100644 --- a/src/com/android/browser/TabControl.java +++ b/src/com/android/browser/TabControl.java @@ -546,8 +546,9 @@ class TabControl { */ private WebView createNewWebView(boolean privateBrowsing) { // Create a new WebView - WebView w = new WebView(mActivity, null, + ScrollWebView w = new ScrollWebView(mActivity, null, com.android.internal.R.attr.webViewStyle, privateBrowsing); + w.setScrollListener(mActivity.getScrollListener()); w.setScrollbarFadingEnabled(true); w.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY); w.setMapTrackballToArrowKeys(false); // use trackball directly @@ -634,9 +635,6 @@ class TabControl { mainView.loadUrl(BrowserSettings.getInstance().getHomePage()); } } - if (mTabChangeListener != null) { - mTabChangeListener.onCurrentTab(newTab); - } return true; } diff --git a/src/com/android/browser/TabScrollView.java b/src/com/android/browser/TabScrollView.java index 6d8b91be..13abb505 100644 --- a/src/com/android/browser/TabScrollView.java +++ b/src/com/android/browser/TabScrollView.java @@ -66,7 +66,7 @@ public class TabScrollView extends HorizontalScrollView { mContentView = new LinearLayout(mContext); mContentView.setOrientation(LinearLayout.HORIZONTAL); mContentView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.WRAP_CONTENT)); + LayoutParams.MATCH_PARENT)); addView(mContentView); mSelected = -1; } diff --git a/src/com/android/browser/TitleBarXLarge.java b/src/com/android/browser/TitleBarXLarge.java index fd6d67b0..4e653759 100644 --- a/src/com/android/browser/TitleBarXLarge.java +++ b/src/com/android/browser/TitleBarXLarge.java @@ -19,87 +19,56 @@ package com.android.browser; import android.app.SearchManager; import android.content.Context; import android.content.Intent; -import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Bitmap; -import android.graphics.Color; -import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; -import android.graphics.drawable.LayerDrawable; -import android.graphics.drawable.PaintDrawable; import android.view.ContextMenu; import android.view.LayoutInflater; import android.view.MenuInflater; import android.view.View; +import android.view.View.OnClickListener; import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; -import com.android.browser.TabControl.TabChangeListener; import com.android.browser.UrlInputView.UrlInputListener; -import java.util.HashMap; -import java.util.Map; - /** * tabbed title bar for xlarge screen browser */ public class TitleBarXLarge extends TitleBarBase - implements TabChangeListener, UrlInputListener { + implements UrlInputListener, OnClickListener { private static final int PROGRESS_MAX = 100; - private static final int TAB_WIDTH_SELECTED = 400; - private static final int TAB_WIDTH_UNSELECTED = 150; - - private BrowserActivity mBrowserActivity; - private Drawable mStopDrawable; - private Drawable mReloadDrawable; - private Drawable mSelectedBackground; - private Drawable mUnselectedBackground; - - private View mBackButton; - private View mForwardButton; - private View mStar; - private View mMenu; - private View mAllButton; - private TabScrollView mTabs; - private View mNewButton; - private TabControl mControl; - private UrlInputView mUrlView; - - private boolean mIsInLandscape; - private Map<Tab, TabViewData> mTabMap; - - private float mDensityScale; - - public TitleBarXLarge(BrowserActivity context, TabControl tabcontrol) { + private BrowserActivity mBrowserActivity; + private Drawable mStopDrawable; + private Drawable mReloadDrawable; + private Drawable mProgressDrawable; + + private View mBackButton; + private View mForwardButton; + private View mStar; + private View mSearchButton; + private ImageView mStopButton; + private View mMenu; + private View mAllButton; + private ImageView mProgressView; + private UrlInputView mUrlView; + private boolean mInLoad; + + public TitleBarXLarge(BrowserActivity context) { super(context); - mDensityScale = context.getResources().getDisplayMetrics().density; - mTabMap = new HashMap<Tab, TabViewData>(); mBrowserActivity = context; - mControl = tabcontrol; Resources resources = context.getResources(); - mSelectedBackground = resources.getDrawable(R.drawable.tab_selected_bg); - mUnselectedBackground = resources.getDrawable(R.drawable.tab_unselected_bg); - mStopDrawable = resources.getDrawable(R.drawable.progress_stop); + mStopDrawable = resources.getDrawable(R.drawable.ic_stop); mReloadDrawable = resources.getDrawable(R.drawable.ic_reload); rebuildLayout(context, true); - // register the tab change listener - mControl.setOnTabChangeListener(this); - } - - void rebuildLayout() { - rebuildLayout(mBrowserActivity, false); } private void rebuildLayout(Context context, boolean rebuildData) { removeAllViews(); LayoutInflater factory = LayoutInflater.from(context); - factory.inflate(R.layout.title_bar_tabbed, this); + factory.inflate(R.layout.url_bar, this); - mTabs = (TabScrollView) findViewById(R.id.tabs); - mNewButton = findViewById(R.id.newtab); mUrlView = (UrlInputView) findViewById(R.id.editurl); mAllButton = findViewById(R.id.all_btn); // TODO: Change enabled states based on whether you can go @@ -108,67 +77,55 @@ public class TitleBarXLarge extends TitleBarBase mForwardButton = findViewById(R.id.forward); mStar = findViewById(R.id.star); mMenu = findViewById(R.id.menu); - View.OnClickListener listener = new View.OnClickListener() { - public void onClick(View v) { - if (mBackButton == v) { - mBrowserActivity.getTopWindow().goBack(); - } else if (mForwardButton == v) { - mBrowserActivity.getTopWindow().goForward(); - } else if (mStar == v) { - mBrowserActivity.promptAddOrInstallBookmark(); - } else if (mMenu == v) { - mBrowserActivity.openOptionsMenu(); - } else if (mAllButton == v) { - // TODO: Show the new bookmarks/windows view. - mBrowserActivity.bookmarksOrHistoryPicker(false); - } else if (mNewButton == v) { - mBrowserActivity.openTabToHomePage(); - } - } - }; - mBackButton.setOnClickListener(listener); - mForwardButton.setOnClickListener(listener); - mStar.setOnClickListener(listener); - mAllButton.setOnClickListener(listener); - mMenu.setOnClickListener(listener); - mNewButton.setOnClickListener(listener); - - mIsInLandscape = mBrowserActivity.getResources().getConfiguration().orientation - == Configuration.ORIENTATION_LANDSCAPE; - mUrlView.setVisibility(mIsInLandscape ? View.GONE : View.VISIBLE); + mStopButton = (ImageView) findViewById(R.id.stop); + mSearchButton = findViewById(R.id.search); + mLockIcon = (ImageView) findViewById(R.id.lock); + mProgressView = (ImageView) findViewById(R.id.progress); + mProgressDrawable = mProgressView.getDrawable(); + + mBackButton.setOnClickListener(this); + mForwardButton.setOnClickListener(this); + mStar.setOnClickListener(this); + mAllButton.setOnClickListener(this); + mStopButton.setOnClickListener(this); + mSearchButton.setOnClickListener(this); + mMenu.setOnClickListener(this); mUrlView.setUrlInputListener(this); - buildTabs(rebuildData); - // ensure title bar state - onCurrentTab(mControl.getCurrentTab()); } - void showUrlEditor(TabViewData tabdata) { - mUrlView.setVisibility(View.VISIBLE); - if (mIsInLandscape) { - mTabs.setVisibility(View.GONE); - mUrlView.requestFocus(); - mUrlView.forceIme(); + @Override + public void onClick(View v) { + if (mBackButton == v) { + mBrowserActivity.getTopWindow().goBack(); + } else if (mForwardButton == v) { + mBrowserActivity.getTopWindow().goForward(); + } else if (mStar == v) { + mBrowserActivity.promptAddOrInstallBookmark(); + } else if (mMenu == v) { + mBrowserActivity.openOptionsMenu(); + } else if (mAllButton == v) { + // TODO: Show the new bookmarks/windows view. + mBrowserActivity.bookmarksOrHistoryPicker(false); + } else if (mSearchButton == v) { + search(); + } else if (mStopButton == v) { + stopOrRefresh(); } } - void hideUrlEditor() { - Tab tab = mControl.getCurrentTab(); - if (mIsInLandscape) { - mUrlView.setVisibility(View.GONE); - mTabs.setVisibility(View.VISIBLE); - } else { - // portrait mode - mUrlView.setText(tab.getWebView().getUrl()); - } - tab.getWebView().requestFocus(); + void requestUrlInputFocus() { + mUrlView.requestFocus(); } + @Override + void setFavicon(Bitmap icon) { } // UrlInputListener implementation @Override public void onAction(String text) { - hideUrlEditor(); + mBrowserActivity.getTabControl().getCurrentTopWebView().requestFocus(); + mBrowserActivity.hideFakeTitleBar(); Intent i = new Intent(); i.setAction(Intent.ACTION_SEARCH); i.putExtra(SearchManager.QUERY, text); @@ -177,7 +134,8 @@ public class TitleBarXLarge extends TitleBarBase @Override public void onDismiss() { - hideUrlEditor(); + mBrowserActivity.getTabControl().getCurrentTopWebView().requestFocus(); + mBrowserActivity.hideFakeTitleBar(); } @Override @@ -187,321 +145,41 @@ public class TitleBarXLarge extends TitleBarBase mBrowserActivity.onCreateContextMenu(menu, this, null); } - @Override - /* package */ void setLock(Drawable d) { - // TODO: handle in tab specific callback - } - - @Override - /* package */ void setFavicon(Bitmap icon) { - // this is handled in the tab specific callback - } - - /** - * Update the progress, from 0 to 100. - */ - @Override - /* package */ void setProgress(int newProgress) { - // this is handled in tab specific callback - } - - @Override - /* package */ void setDisplayTitle(String title) { - // this is done in tab specific callback - } - - private void buildTabs(boolean needsRebuilding) { - mTabs.clearTabs(); - for (int i = 0; i < mControl.getTabCount(); i++) { - Tab tab = mControl.getTab(i); - TabViewData data = buildTab(needsRebuilding, tab); - TabView tv = buildView(data); - } - mTabs.setSelectedTab(mControl.getCurrentIndex()); + private void search() { + mUrlView.setText(""); + mUrlView.requestFocus(); } - private TabViewData buildTab(boolean needsRebuilding, Tab tab) { - TabViewData data = null; - if (needsRebuilding) { - data = new TabViewData(tab); - mTabMap.put(tab, data); + private void stopOrRefresh() { + if (mInLoad) { + mBrowserActivity.stopLoading(); } else { - data = mTabMap.get(tab); + mBrowserActivity.getTopWindow().reload(); } - return data; - } - - private TabView buildView(final TabViewData data) { - TabView tv = new TabView(mBrowserActivity, data); - tv.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if (mTabs.getSelectedTab() == v) { - showUrlEditor(data); - } else { - int ix = mControl.getTabIndex(data.mTab); - mTabs.setSelectedTab(ix); - mBrowserActivity.switchToTab(ix); - } - } - }); - mTabs.addTab(tv); - return tv; } /** - * the views used in the tab bar - */ - class TabView extends LinearLayout { - - TabViewData mTabData; - View mTabContent; - TextView mTitle; - ImageView mIconView; - ImageView mLock; - CircularProgressView mStop; - ImageView mClose; - boolean mSelected; - boolean mInLoad; - - /** - * @param context - */ - public TabView(Context context, TabViewData tab) { - super(context); - mTabData = tab; - LayoutInflater inflater = LayoutInflater.from(mContext); - mTabContent = inflater.inflate(R.layout.tab_title, this); - mTitle = (TextView) mTabContent.findViewById(R.id.title); - mIconView = (ImageView) mTabContent.findViewById(R.id.favicon); - mLock = (ImageView) mTabContent.findViewById(R.id.lock); - mStop = (CircularProgressView) mTabContent.findViewById(R.id.stop); - mStop.setMaxProgress(PROGRESS_MAX); - mClose = (ImageView) mTabContent.findViewById(R.id.close); - mClose.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - closeTab(); - } - }); - mStop.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if (mInLoad) { - mBrowserActivity.stopLoading(); - } else { - mBrowserActivity.getTopWindow().reload(); - } - } - }); - mSelected = false; - mInLoad = false; - // update the status - updateFromData(); - } - - private void updateFromData() { - mTabData.mTabView = this; - if (mTabData.mUrl != null) { - setDisplayTitle(mTabData.mUrl); - } - if (mTabData.mTitle != null) { - setDisplayTitle(mTabData.mTitle); - } - setProgress(mTabData.mProgress); - if (mTabData.mIcon != null) { - setFavicon(mTabData.mIcon); - } - if (mTabData.mLock != null) { - setLock(mTabData.mLock); - } - } - - @Override - public void setSelected(boolean selected) { - mSelected = selected; - mStop.setVisibility(mSelected ? View.VISIBLE : View.GONE); - mIconView.setVisibility(mSelected ? View.VISIBLE : View.GONE); - super.setSelected(selected); - setBackgroundDrawable(selected ? mSelectedBackground - : mUnselectedBackground); - setLayoutParams(new LayoutParams(selected ? - (int) (TAB_WIDTH_SELECTED * mDensityScale) - : (int) (TAB_WIDTH_UNSELECTED * mDensityScale), - LayoutParams.WRAP_CONTENT)); - } - - void setDisplayTitle(String title) { - mTitle.setText(title); - } - - void setFavicon(Drawable d) { - mIconView.setImageDrawable(d); - } - - void setLock(Drawable d) { - if (null == d) { - mLock.setVisibility(View.GONE); - } else { - mLock.setImageDrawable(d); - mLock.setVisibility(View.VISIBLE); - } - } - - void setTitleCompoundDrawables(Drawable left, Drawable top, - Drawable right, Drawable bottom) { - mTitle.setCompoundDrawables(left, top, right, bottom); - } - - void setProgress(int newProgress) { - mStop.setProgress(newProgress); - if (newProgress >= PROGRESS_MAX) { - mInLoad = false; - mStop.setImageDrawable(mReloadDrawable); - } else { - if (!mInLoad && getWindowToken() != null) { - // checking the window token lets us be sure that we - // are attached to a window before starting the animation, - // preventing a potential race condition - // (fix for bug http://b/2115736) - mInLoad = true; - mStop.setImageDrawable(mStopDrawable); - } - } - } - - private void closeTab() { - if (mTabData.mTab == mControl.getCurrentTab()) { - mBrowserActivity.closeCurrentWindow(); - } else { - mBrowserActivity.closeTab(mTabData.mTab); - } - } - - } - - /** - * class to store tab state within the title bar + * Update the progress, from 0 to 100. */ - class TabViewData { - - Tab mTab; - TabView mTabView; - int mProgress; - Drawable mIcon; - Drawable mLock; - String mTitle; - String mUrl; - - TabViewData(Tab tab) { - mTab = tab; - } - - void setUrlAndTitle(String url, String title) { - mUrl = url; - mTitle = title; - if (mTabView != null) { - if (title != null) { - mTabView.setDisplayTitle(title); - } else if (url != null) { - mTabView.setDisplayTitle(url); - } - } - } - - void setProgress(int newProgress) { - mProgress = newProgress; - if (mTabView != null) { - mTabView.setProgress(mProgress); - } - } - - void setFavicon(Bitmap icon) { - Drawable[] array = new Drawable[3]; - array[0] = new PaintDrawable(Color.BLACK); - array[1] = new PaintDrawable(Color.WHITE); - if (icon == null) { - array[2] = mGenericFavicon; - } else { - array[2] = new BitmapDrawable(icon); - } - LayerDrawable d = new LayerDrawable(array); - d.setLayerInset(1, 1, 1, 1, 1); - d.setLayerInset(2, 2, 2, 2, 2); - mIcon = d; - if (mTabView != null) { - mTabView.setFavicon(mIcon); - } - } - - } - - // TabChangeListener implementation - @Override - public void onCurrentTab(Tab tab) { - mTabs.setSelectedTab(mControl.getCurrentIndex()); - TabViewData tvd = mTabMap.get(tab); - if (tvd != null) { - if (tvd.mUrl != null) { - mUrlView.setText(tvd.mUrl); + void setProgress(int newProgress) { + if (newProgress >= PROGRESS_MAX) { + mProgressView.setVisibility(View.GONE); + mInLoad = false; + mStopButton.setImageDrawable(mReloadDrawable); + } else { + if (!mInLoad) { + mProgressView.setVisibility(View.VISIBLE); + mInLoad = true; + mStopButton.setImageDrawable(mStopDrawable); } - setProgress(tvd.mProgress); - } - } - - @Override - public void onFavicon(Tab tab, Bitmap favicon) { - TabViewData tvd = mTabMap.get(tab); - if (tvd != null) { - tvd.setFavicon(favicon); - } - } - - @Override - public void onNewTab(Tab tab) { - TabViewData tvd = buildTab(true, tab); - buildView(tvd); - } - - @Override - public void onProgress(Tab tab, int progress) { - TabViewData tvd = mTabMap.get(tab); - if (tvd != null) { - tvd.setProgress(progress); - } - if (tab == mControl.getCurrentTab()) { - setProgress(progress); + mProgressDrawable.setLevel(newProgress*10000/PROGRESS_MAX); } } @Override - public void onRemoveTab(Tab tab) { - TabViewData tvd = mTabMap.get(tab); - TabView tv = tvd.mTabView; - if (tv != null) { - mTabs.removeTab(tv); - } - mTabMap.remove(tab); - } - - @Override - public void onUrlAndTitle(Tab tab, String url, String title) { - TabViewData tvd = mTabMap.get(tab); - if (tvd != null) { - tvd.setUrlAndTitle(url, title); - } - if ((url != null) && (tab == mControl.getCurrentTab())) { - mUrlView.setText(url); - } - } - - @Override - public void onPageFinished(Tab tab) { - } - - @Override - public void onPageStarted(Tab tab) { + /* package */ void setDisplayTitle(String title) { + mUrlView.setText(title); } } diff --git a/src/com/android/browser/UrlInputView.java b/src/com/android/browser/UrlInputView.java index 38412579..f564d6aa 100644 --- a/src/com/android/browser/UrlInputView.java +++ b/src/com/android/browser/UrlInputView.java @@ -25,28 +25,28 @@ import android.util.AttributeSet; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; +import android.view.View.OnFocusChangeListener; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; import android.widget.AutoCompleteTextView; import android.widget.CursorAdapter; import android.widget.Filterable; import android.widget.ImageView; import android.widget.TextView; -import android.widget.AdapterView.OnItemClickListener; /** * url/search input view * handling suggestions */ -public class UrlInputView extends AutoCompleteTextView { +public class UrlInputView extends AutoCompleteTextView + implements OnFocusChangeListener, OnItemClickListener { private UrlInputListener mListener; private InputMethodManager mInputManager; private SuggestionsAdapter mAdapter; private Drawable mFocusDrawable; - private Drawable mNoFocusDrawable; - public UrlInputView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); @@ -65,7 +65,6 @@ public class UrlInputView extends AutoCompleteTextView { private void init(Context ctx) { mFocusDrawable = ctx.getResources().getDrawable(R.drawable.textfield_stroke); - mNoFocusDrawable = ctx.getResources().getDrawable(R.drawable.textfield_nostroke); mInputManager = (InputMethodManager) ctx.getSystemService(Context.INPUT_METHOD_SERVICE); setOnEditorActionListener(new OnEditorActionListener() { @Override @@ -74,26 +73,32 @@ public class UrlInputView extends AutoCompleteTextView { return true; } }); - setOnFocusChangeListener(new OnFocusChangeListener() { - @Override - public void onFocusChange(View v, boolean hasFocus) { - setBackgroundDrawable(hasFocus ? mFocusDrawable : mNoFocusDrawable); - } - }); + setOnFocusChangeListener(this); final ContentResolver cr = mContext.getContentResolver(); mAdapter = new SuggestionsAdapter(mContext, BrowserProvider.getBookmarksSuggestions(cr, null)); setAdapter(mAdapter); - setOnItemClickListener(new OnItemClickListener() { - @Override - public void onItemClick(AdapterView<?> parent, View view, int position, long id) { - String url = mAdapter.getViewString(view); - finishInput(url); - } - }); + setOnItemClickListener(this); setSelectAllOnFocus(true); } + @Override + public void onFocusChange(View v, boolean hasFocus) { + setBackgroundDrawable(hasFocus ? mFocusDrawable : null); + if (hasFocus) { + forceIme(); + } else { + finishInput(null); + } + } + + @Override + public void onItemClick(AdapterView<?> parent, View view, int position, long id) { + String url = mAdapter.getViewString(view); + finishInput(url); + } + + public void setUrlInputListener(UrlInputListener listener) { mListener = listener; } @@ -110,7 +115,6 @@ public class UrlInputView extends AutoCompleteTextView { } else { mListener.onAction(url); } - } @Override @@ -124,11 +128,8 @@ public class UrlInputView extends AutoCompleteTextView { } interface UrlInputListener { - public void onDismiss(); - public void onAction(String text); - } /** |