Bug 768667 - Provide an action mode for compatibility with old Android versions. r=sriram

This commit is contained in:
Wes Johnston 2013-11-19 11:57:35 -08:00
parent 6b5a818ef6
commit 9747791d38
23 changed files with 467 additions and 31 deletions

View File

@ -0,0 +1,101 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko;
import org.mozilla.gecko.widget.GeckoPopupMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
class ActionModeCompat implements GeckoPopupMenu.OnMenuItemClickListener,
View.OnClickListener {
private final String LOGTAG = "GeckoActionModeCompat";
private Callback mCallback;
private ActionModeCompatView mView;
private Presenter mPresenter;
/* A set of callbacks to be called during this ActionMode's lifecycle. These will control the
* creation, interaction with, and destruction of menuitems for the view */
public static interface Callback {
/* Called when action mode is first created. Implementors should use this to inflate menu resources. */
public boolean onCreateActionMode(ActionModeCompat mode, Menu menu);
/* Called to refresh an action mode's action menu. Called whenever the mode is invalidated. Implementors
* should use this to enable/disable/show/hide menu items. */
public boolean onPrepareActionMode(ActionModeCompat mode, Menu menu);
/* Called to report a user click on an action button. */
public boolean onActionItemClicked(ActionModeCompat mode, MenuItem item);
/* Called when an action mode is about to be exited and destroyed. */
public void onDestroyActionMode(ActionModeCompat mode);
}
/* Presenters handle the actual showing/hiding of the action mode UI in the app. Its their responsibility
* to create an action mode, and assign it Callbacks and ActionModeCompatView's. */
public static interface Presenter {
/* Called when an action mode should be shown */
public void startActionModeCompat(final Callback callback);
/* Called when whatever action mode is showing should be hidden */
public void endActionModeCompat();
}
public ActionModeCompat(Presenter presenter, Callback callback, ActionModeCompatView view) {
mPresenter = presenter;
mCallback = callback;
mView = view;
mView.initForMode(this);
}
public void finish() {
// Clearing the menu will also clear the ActionItemBar
mView.getMenu().clear();
if (mCallback != null) {
mCallback.onDestroyActionMode(this);
}
}
public CharSequence getTitle() {
return mView.getTitle();
}
public void setTitle(CharSequence title) {
mView.setTitle(title);
}
public void setTitle(int resId) {
mView.setTitle(resId);
}
public Menu getMenu() {
return mView.getMenu();
}
public void invalidate() {
if (mCallback != null) {
mCallback.onPrepareActionMode(this, mView.getMenu());
}
mView.invalidate();
}
/* GeckoPopupMenu.OnMenuItemClickListener */
@Override
public boolean onMenuItemClick(MenuItem item) {
if (mCallback != null) {
return mCallback.onActionItemClicked(this, item);
}
return false;
}
/* View.OnClickListener*/
@Override
public void onClick(View v) {
mPresenter.endActionModeCompat();
}
}

View File

@ -0,0 +1,151 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko;
import org.mozilla.gecko.menu.GeckoMenu;
import org.mozilla.gecko.menu.MenuPopup;
import org.mozilla.gecko.menu.MenuPanel;
import org.mozilla.gecko.menu.MenuItemActionBar;
import org.mozilla.gecko.widget.GeckoPopupMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuInflater;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.view.View;
import android.view.ViewGroup;
import android.content.Context;
import android.widget.TextView;
import android.widget.ImageButton;
import android.widget.Button;
import android.widget.PopupWindow;
import android.util.AttributeSet;
class ActionModeCompatView extends LinearLayout implements GeckoMenu.ActionItemBarPresenter {
private final String LOGTAG = "GeckoActionModeCompatPresenter";
private static final int SPEC = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
private Button mTitleView;
private ImageButton mMenuButton;
private ViewGroup mActionButtonBar;
private GeckoPopupMenu mPopupMenu;
// Maximum number of items to show as actions
private static final int MAX_ACTION_ITEMS = 4;
private int mActionButtonsWidth = 0;
public ActionModeCompatView(Context context) {
this(context, null);
}
public ActionModeCompatView(Context context, AttributeSet attrs) {
this(context, null, 0);
}
public ActionModeCompatView(Context context, AttributeSet attrs, int style) {
super(context, attrs, style);
}
@Override
public void onFinishInflate() {
mTitleView = (Button) findViewById(R.id.actionmode_title);
mMenuButton = (ImageButton) findViewById(R.id.actionbar_menu);
mActionButtonBar = (ViewGroup) findViewById(R.id.actionbar_buttons);
mPopupMenu = new GeckoPopupMenu(getContext(), mMenuButton);
((GeckoMenu) mPopupMenu.getMenu()).setActionItemBarPresenter(this);
mMenuButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
openMenu();
}
});
}
public void initForMode(final ActionModeCompat mode) {
mTitleView.setOnClickListener(mode);
mPopupMenu.setOnMenuItemClickListener(mode);
}
public CharSequence getTitle() {
return mTitleView.getText();
}
public void setTitle(CharSequence title) {
mTitleView.setText(title);
}
public void setTitle(int resId) {
mTitleView.setText(resId);
}
public Menu getMenu() {
return mPopupMenu.getMenu();
}
public void invalidate() {
mMenuButton.setVisibility(mPopupMenu.getMenu().hasVisibleItems() ? View.VISIBLE : View.GONE);
super.invalidate();
}
/* GeckoMenu.ActionItemBarPresenter */
@Override
public boolean addActionItem(View actionItem) {
final int count = mActionButtonBar.getChildCount();
if (count >= MAX_ACTION_ITEMS) {
return false;
}
int maxWidth = mActionButtonBar.getMeasuredWidth();
if (maxWidth == 0) {
mActionButtonBar.measure(SPEC, SPEC);
maxWidth = mActionButtonBar.getMeasuredWidth();
}
// Since we don't know how many items will be added, we always reserve space for the overflow menu
mMenuButton.measure(SPEC, SPEC);
maxWidth -= mMenuButton.getMeasuredWidth();
if (mActionButtonsWidth <= 0) {
mActionButtonsWidth = 0;
// Loop over child views, measure them, and add their width to the taken width
for (int i = 0; i < count; i++) {
View v = mActionButtonBar.getChildAt(i);
v.measure(SPEC, SPEC);
mActionButtonsWidth += v.getMeasuredWidth();
}
}
actionItem.measure(SPEC, SPEC);
int w = actionItem.getMeasuredWidth();
if (mActionButtonsWidth + w < maxWidth) {
// We cache the new width of our children.
mActionButtonsWidth += w;
mActionButtonBar.addView(actionItem);
return true;
}
return false;
}
/* GeckoMenu.ActionItemBarPresenter */
@Override
public void removeActionItem(View actionItem) {
mActionButtonsWidth -= actionItem.getMeasuredWidth();
mActionButtonBar.removeView(actionItem);
}
public void openMenu() {
mPopupMenu.openMenu();
}
public void closeMenu() {
mPopupMenu.dismiss();
}
}

View File

@ -14,6 +14,7 @@ import org.mozilla.gecko.favicons.LoadFaviconTask;
import org.mozilla.gecko.gfx.BitmapUtils;
import org.mozilla.gecko.gfx.GeckoLayerClient;
import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
import org.mozilla.gecko.gfx.LayerMarginsAnimator;
import org.mozilla.gecko.health.BrowserHealthRecorder;
import org.mozilla.gecko.health.BrowserHealthReporter;
import org.mozilla.gecko.home.BrowserSearch;
@ -71,8 +72,10 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.view.animation.Interpolator;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;
import android.widget.ViewFlipper;
import java.io.File;
import java.io.FileNotFoundException;
@ -88,7 +91,8 @@ abstract public class BrowserApp extends GeckoApp
BrowserSearch.OnSearchListener,
BrowserSearch.OnEditSuggestionListener,
HomePager.OnNewTabsListener,
OnUrlOpenListener {
OnUrlOpenListener,
ActionModeCompat.Presenter {
private static final String LOGTAG = "GeckoBrowserApp";
private static final String PREF_CHROME_DYNAMICTOOLBAR = "browser.chrome.dynamictoolbar";
@ -111,10 +115,13 @@ abstract public class BrowserApp extends GeckoApp
private BrowserSearch mBrowserSearch;
private View mBrowserSearchContainer;
public ViewFlipper mViewFlipper;
public ActionModeCompatView mActionBar;
private BrowserToolbar mBrowserToolbar;
private HomePager mHomePager;
private View mHomePagerContainer;
protected Telemetry.Timer mAboutHomeStartupTimer = null;
private ActionModeCompat mActionMode;
private static final int GECKO_TOOLS_MENU = -1;
private static final int ADDON_MENU_OFFSET = 1000;
@ -265,7 +272,7 @@ abstract public class BrowserApp extends GeckoApp
switch (keyCode) {
case KeyEvent.KEYCODE_BUTTON_Y:
// Toggle/focus the address bar on gamepad-y button.
if (mBrowserToolbar.isVisible()) {
if (mViewFlipper.getVisibility() == View.VISIBLE) {
if (isDynamicToolbarEnabled() && !isHomePagerVisible()) {
if (mLayerView != null) {
mLayerView.getLayerMarginsAnimator().hideMargins(false);
@ -425,6 +432,9 @@ abstract public class BrowserApp extends GeckoApp
super.onCreate(savedInstanceState);
mViewFlipper = (ViewFlipper) findViewById(R.id.browser_actionbar);
mActionBar = (ActionModeCompatView) findViewById(R.id.actionbar);
mBrowserToolbar = (BrowserToolbar) findViewById(R.id.browser_toolbar);
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
// Show the target URL immediately in the toolbar
@ -602,6 +612,11 @@ abstract public class BrowserApp extends GeckoApp
return;
}
if (mActionMode != null) {
endActionModeCompat();
return;
}
super.onBackPressed();
}
@ -660,7 +675,7 @@ abstract public class BrowserApp extends GeckoApp
mLayerView.getLayerClient().setOnMetricsChangedListener(this);
}
setToolbarMargin(0);
mHomePagerContainer.setPadding(0, mBrowserToolbar.getHeight(), 0, 0);
mHomePagerContainer.setPadding(0, mViewFlipper.getHeight(), 0, 0);
} else {
// Immediately show the toolbar when disabling the dynamic
// toolbar.
@ -668,8 +683,8 @@ abstract public class BrowserApp extends GeckoApp
mLayerView.getLayerClient().setOnMetricsChangedListener(null);
}
mHomePagerContainer.setPadding(0, 0, 0, 0);
if (mBrowserToolbar != null) {
mBrowserToolbar.scrollTo(0, 0);
if (mViewFlipper != null) {
mViewFlipper.scrollTo(0, 0);
}
}
@ -902,7 +917,7 @@ abstract public class BrowserApp extends GeckoApp
@Override
public void onMetricsChanged(ImmutableViewportMetrics aMetrics) {
if (isHomePagerVisible() || mBrowserToolbar == null) {
if (isHomePagerVisible() || mViewFlipper == null) {
return;
}
@ -911,7 +926,7 @@ abstract public class BrowserApp extends GeckoApp
if (aMetrics.getPageHeight() <= aMetrics.getHeight()) {
if (mDynamicToolbarCanScroll) {
mDynamicToolbarCanScroll = false;
if (!mBrowserToolbar.isVisible()) {
if (mViewFlipper.getVisibility() != View.VISIBLE) {
ThreadUtils.postToUiThread(new Runnable() {
public void run() {
mLayerView.getLayerMarginsAnimator().showMargins(false);
@ -923,7 +938,7 @@ abstract public class BrowserApp extends GeckoApp
mDynamicToolbarCanScroll = true;
}
final View toolbarLayout = mBrowserToolbar;
final View toolbarLayout = mViewFlipper;
final int marginTop = Math.round(aMetrics.marginTop);
ThreadUtils.postToUiThread(new Runnable() {
public void run() {
@ -958,8 +973,8 @@ abstract public class BrowserApp extends GeckoApp
public void refreshToolbarHeight() {
int height = 0;
if (mBrowserToolbar != null) {
height = mBrowserToolbar.getHeight();
if (mViewFlipper != null) {
height = mViewFlipper.getHeight();
}
if (!isDynamicToolbarEnabled() || isHomePagerVisible()) {
@ -992,9 +1007,9 @@ abstract public class BrowserApp extends GeckoApp
@Override
public void run() {
if (aShow) {
mBrowserToolbar.show();
mViewFlipper.setVisibility(View.VISIBLE);
} else {
mBrowserToolbar.hide();
mViewFlipper.setVisibility(View.GONE);
if (hasTabsSideBar()) {
hideTabs();
}
@ -1010,8 +1025,8 @@ abstract public class BrowserApp extends GeckoApp
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
mBrowserToolbar.show();
mBrowserToolbar.requestFocusFromTouch();
mViewFlipper.setVisibility(View.VISIBLE);
mViewFlipper.requestFocusFromTouch();
}
});
}
@ -1974,13 +1989,13 @@ abstract public class BrowserApp extends GeckoApp
@Override
public void run() {
if (fullscreen) {
mBrowserToolbar.hide();
mViewFlipper.setVisibility(View.GONE);
if (isDynamicToolbarEnabled()) {
mLayerView.getLayerMarginsAnimator().hideMargins(true);
mLayerView.getLayerMarginsAnimator().setMaxMargins(0, 0, 0, 0);
}
} else {
mBrowserToolbar.show();
mViewFlipper.setVisibility(View.VISIBLE);
if (isDynamicToolbarEnabled()) {
mLayerView.getLayerMarginsAnimator().showMargins(true);
mLayerView.getLayerMarginsAnimator().setMaxMargins(0, mToolbarHeight, 0, 0);
@ -2461,4 +2476,38 @@ abstract public class BrowserApp extends GeckoApp
Log.w(LOGTAG, "No candidate updater found; ignoring launch request.");
return false;
}
/* Implementing ActionModeCompat.Presenter */
@Override
public void startActionModeCompat(final ActionModeCompat.Callback callback) {
// If actionMode is null, we're not currently showing one. Flip to the action mode view
if (mActionMode == null) {
mViewFlipper.showNext();
LayerMarginsAnimator margins = mLayerView.getLayerMarginsAnimator();
margins.setMaxMargins(0, mViewFlipper.getHeight(), 0, 0);
margins.setMarginsPinned(true);
margins.showMargins(false);
} else {
// Otherwise, we're already showing an action mode. Just finish it and show the new one
mActionMode.finish();
}
mActionMode = new ActionModeCompat(BrowserApp.this, callback, mActionBar);
if (callback.onCreateActionMode(mActionMode, mActionMode.getMenu())) {
mActionMode.invalidate();
}
}
/* Implementing ActionModeCompat.Presenter */
@Override
public void endActionModeCompat() {
if (mActionMode == null) {
return;
}
mActionMode.finish();
mActionMode = null;
mLayerView.getLayerMarginsAnimator().setMarginsPinned(false);
mViewFlipper.showPrevious();
}
}

View File

@ -372,3 +372,8 @@ just addresses the organization to follow, e.g. "This site is run by " -->
<!ENTITY exit_guest_session_title "&brandShortName; will now restart">
<!ENTITY exit_guest_session_text "The browsing data from this session will be deleted.">
<!-- These are only used for accessiblity for the done and overflow-menu buttons in the actionbar.
They are never shown to users -->
<!ENTITY actionbar_menu "Menu">
<!ENTITY actionbar_done "Done">

View File

@ -66,7 +66,7 @@ public class GeckoMenu extends ListView
*/
public static interface ActionItemBarPresenter {
// Add an action-item.
public void addActionItem(View actionItem);
public boolean addActionItem(View actionItem);
// Remove an action-item.
public void removeActionItem(View actionItem);
@ -151,7 +151,7 @@ public class GeckoMenu extends ListView
mItems.add(menuItem);
}
private void addActionItem(final GeckoMenuItem menuItem) {
private boolean addActionItem(final GeckoMenuItem menuItem) {
menuItem.setOnShowAsActionChangedListener(this);
if (mActionItems.size() == 0 &&
@ -173,6 +173,8 @@ public class GeckoMenu extends ListView
mActionItems.put(menuItem, actionView);
mActionItemBarPresenter.addActionItem(actionView);
mItems.add(menuItem);
return true;
}
@Override
@ -224,6 +226,12 @@ public class GeckoMenu extends ListView
mAdapter.clear();
mItems.clear();
if (mActionItemBarPresenter != null) {
for (View item : mActionItems.values()) {
mActionItemBarPresenter.removeActionItem(item);
}
}
mActionItems.clear();
}
@ -266,7 +274,7 @@ public class GeckoMenu extends ListView
@Override
public boolean hasVisibleItems() {
for (GeckoMenuItem menuItem : mItems) {
if (menuItem.isVisible())
if (menuItem.isVisible() && !mActionItems.containsKey(menuItem))
return true;
}
@ -362,10 +370,11 @@ public class GeckoMenu extends ListView
public void onShowAsActionChanged(GeckoMenuItem item, boolean isActionItem) {
removeItem(item.getItemId());
if (isActionItem)
addActionItem(item);
else
addItem(item);
if (isActionItem && addActionItem(item)) {
return;
}
addItem(item);
}
public void onItemChanged(GeckoMenuItem item) {
@ -476,11 +485,12 @@ public class GeckoMenu extends ListView
}
@Override
public void addActionItem(View actionItem) {
public boolean addActionItem(View actionItem) {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(actionItem.getLayoutParams());
params.weight = 1.0f;
actionItem.setLayoutParams(params);
addView(actionItem);
return true;
}
@Override

View File

@ -82,6 +82,8 @@ if CONFIG['MOZ_WEBRTC']:
gbjar = add_java_jar('gecko-browser')
gbjar.sources += [
'ActionModeCompat.java',
'ActionModeCompatView.java',
'ActivityHandlerHelper.java',
'AlertNotification.java',
'animation/AnimatorProxy.java',
@ -404,6 +406,8 @@ ANDROID_RESFILES += [
'resources/drawable-hdpi-v11/ic_menu_share.png',
'resources/drawable-hdpi-v11/ic_menu_tools.png',
'resources/drawable-hdpi-v11/ic_status_logo.png',
'resources/drawable-hdpi/ab_done.png',
'resources/drawable-hdpi/ab_stacked_transparent_light_holo.9.png',
'resources/drawable-hdpi/abouthome_thumbnail.png',
'resources/drawable-hdpi/alert_addon.png',
'resources/drawable-hdpi/alert_app.png',
@ -461,6 +465,7 @@ ANDROID_RESFILES += [
'resources/drawable-hdpi/menu_item_check.png',
'resources/drawable-hdpi/menu_item_more.png',
'resources/drawable-hdpi/menu_item_uncheck.png',
'resources/drawable-hdpi/menu_light.png',
'resources/drawable-hdpi/menu_panel_bg.9.png',
'resources/drawable-hdpi/menu_pb.png',
'resources/drawable-hdpi/menu_popup_arrow_bottom.png',
@ -542,6 +547,8 @@ ANDROID_RESFILES += [
'resources/drawable-mdpi-v11/ic_menu_share.png',
'resources/drawable-mdpi-v11/ic_menu_tools.png',
'resources/drawable-mdpi-v11/ic_status_logo.png',
'resources/drawable-mdpi/ab_done.png',
'resources/drawable-mdpi/ab_stacked_transparent_light_holo.9.png',
'resources/drawable-mdpi/abouthome_thumbnail.png',
'resources/drawable-mdpi/alert_addon.png',
'resources/drawable-mdpi/alert_app.png',
@ -602,6 +609,7 @@ ANDROID_RESFILES += [
'resources/drawable-mdpi/menu_item_check.png',
'resources/drawable-mdpi/menu_item_more.png',
'resources/drawable-mdpi/menu_item_uncheck.png',
'resources/drawable-mdpi/menu_light.png',
'resources/drawable-mdpi/menu_panel_bg.9.png',
'resources/drawable-mdpi/menu_pb.png',
'resources/drawable-mdpi/menu_popup_arrow_bottom.png',
@ -678,6 +686,8 @@ ANDROID_RESFILES += [
'resources/drawable-xhdpi-v11/ic_menu_share.png',
'resources/drawable-xhdpi-v11/ic_menu_tools.png',
'resources/drawable-xhdpi-v11/ic_status_logo.png',
'resources/drawable-xhdpi/ab_done.png',
'resources/drawable-xhdpi/ab_stacked_transparent_light_holo.9.png',
'resources/drawable-xhdpi/abouthome_thumbnail.png',
'resources/drawable-xhdpi/alert_addon.png',
'resources/drawable-xhdpi/alert_app.png',
@ -733,6 +743,7 @@ ANDROID_RESFILES += [
'resources/drawable-xhdpi/menu_item_check.png',
'resources/drawable-xhdpi/menu_item_more.png',
'resources/drawable-xhdpi/menu_item_uncheck.png',
'resources/drawable-xhdpi/menu_light.png',
'resources/drawable-xhdpi/menu_panel_bg.9.png',
'resources/drawable-xhdpi/menu_pb.png',
'resources/drawable-xhdpi/menu_popup_arrow_bottom.png',
@ -830,6 +841,7 @@ ANDROID_RESFILES += [
'resources/layout-xlarge-v11/home_history_tabs_indicator.xml',
'resources/layout-xlarge-v11/remote_tabs_child.xml',
'resources/layout-xlarge-v11/remote_tabs_group.xml',
'resources/layout/actionbar.xml',
'resources/layout/arrow_popup.xml',
'resources/layout/autocomplete_list.xml',
'resources/layout/autocomplete_list_item.xml',

Binary file not shown.

After

Width:  |  Height:  |  Size: 737 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 915 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<org.mozilla.gecko.ActionModeCompatView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/actionbar"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
style="@style/GeckoActionBar">
<LinearLayout android:layout_height="fill_parent"
android:layout_width="fill_parent"
style="@style/GeckoActionBar">
<Button android:id="@+id/actionmode_title"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
style="@style/GeckoActionBar.Title"/>
<!-- Draw a separator to the left of the title -->
<View android:layout_height="fill_parent"
android:layout_width="1dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:background="@android:color/darker_gray"/>
<LinearLayout android:id="@+id/actionbar_buttons"
android:layout_height="fill_parent"
android:layout_width="0dip"
android:layout_weight="1"
style="@style/GeckoActionBar.Buttons"/>
<ImageButton android:id="@+id/actionbar_menu"
android:layout_height="fill_parent"
android:layout_width="@dimen/browser_toolbar_icon_width"
style="@style/GeckoActionBar.Button.MenuButton"/>
</LinearLayout>
</org.mozilla.gecko.ActionModeCompatView>

View File

@ -67,13 +67,25 @@
view. To make sure the EditText is not the first focusable view in
the root view, BrowserToolbar should be specified as low in the
view hierarchy as possible. -->
<org.mozilla.gecko.toolbar.BrowserToolbar
android:id="@id/browser_toolbar"
style="@style/BrowserToolbar"
<ViewFlipper android:id="@+id/browser_actionbar"
android:layout_width="fill_parent"
android:layout_height="@dimen/browser_toolbar_height"
android:clickable="true"
android:focusable="true"/>
android:focusable="true">
<org.mozilla.gecko.toolbar.BrowserToolbar
android:id="@id/browser_toolbar"
style="@style/BrowserToolbar"
android:layout_width="fill_parent"
android:layout_height="@dimen/browser_toolbar_height"
android:clickable="true"
android:focusable="true"/>
<include layout="@layout/actionbar"
android:id="@+id/actionbar"/>
</ViewFlipper>
</view>

View File

@ -74,4 +74,20 @@
<item name="android:textColor">#FF000000</item>
</style>
<style name="GeckoActionBar" parent="@android:style/Widget.Holo.Light.ActionMode">
<item name="android:background">@drawable/ab_stacked_transparent_light_holo</item>
</style>
<style name="GeckoActionBar.Title" parent="@android:style/TextAppearance.Holo.Widget.ActionBar.Title">
<item name="android:drawableLeft">?android:attr/actionModeCloseDrawable</item>
<item name="android:background">@android:color/transparent</item>
<item name="android:paddingLeft">15dp</item>
<item name="android:paddingRight">15dp</item>
</style>
<style name="GeckoActionBar.Button.MenuButton" parent="android:style/Widget.Holo.Light.ActionButton.Overflow">
<item name="android:scaleType">center</item>
<item name="android:background">@android:color/transparent</item>
</style>
</resources>

View File

@ -540,4 +540,37 @@
<item name="android:layout_gravity">center_vertical</item>
</style>
<style name="GeckoActionBar">
<item name="android:background">@drawable/ab_stacked_transparent_light_holo</item>
</style>
<style name="GeckoActionBar.Title">
<item name="android:gravity">center_vertical</item>
<item name="android:minWidth">0dp</item>
<item name="android:background">@android:color/transparent</item>
<item name="android:textAppearance">@style/TextAppearance.Medium</item>
<item name="android:drawableLeft">@drawable/ab_done</item>
<item name="android:paddingLeft">15dp</item>
<item name="android:paddingRight">15dp</item>
<item name="android:contentDescription">@string/actionbar_done</item>
</style>
<style name="GeckoActionBar.Button" parent="Widget.MenuItemActionBar">
<item name="android:background">@android:color/transparent</item>
<item name="android:gravity">center</item>
</style>
<style name="GeckoActionBar.Button.MenuButton">
<item name="android:scaleType">center</item>
<item name="android:src">@drawable/menu_light</item>
<item name="android:contentDescription">@string/actionbar_menu</item>
<item name="android:background">@android:color/transparent</item>
</style>
<style name="GeckoActionBar.Buttons">
<item name="android:background">@android:color/transparent</item>
<item name="android:textColor">@color/text_color_primary</item>
<item name="android:gravity">right</item>
</style>
</resources>

View File

@ -82,6 +82,7 @@
<item name="topSitesGridViewStyle">@style/Widget.TopSitesGridView</item>
<item name="topSitesThumbnailViewStyle">@style/Widget.TopSitesThumbnailView</item>
<item name="homeListViewStyle">@style/Widget.HomeListView</item>
<item name="menuItemDefaultStyle">@style/Widget.MenuItemDefault</item>
</style>
<style name="Gecko.Preferences" parent="GeckoPreferencesBase"/>

View File

@ -350,4 +350,8 @@
<string name="exit_guest_session_title">&exit_guest_session_title;</string>
<string name="exit_guest_session_text">&exit_guest_session_text;</string>
<string name="actionbar_menu">&actionbar_menu;</string>
<string name="actionbar_done">&actionbar_done;</string>
</resources>

View File

@ -1761,8 +1761,9 @@ public class BrowserToolbar extends GeckoRelativeLayout
}
@Override
public void addActionItem(View actionItem) {
public boolean addActionItem(View actionItem) {
mActionItemBar.addView(actionItem);
return true;
}
@Override

View File

@ -65,6 +65,9 @@ public class GeckoPopupMenu implements GeckoMenu.Callback,
mMenuPopup = new MenuPopup(context);
mMenuPanel = new MenuPanel(context, null);
mMenuPanel.addView(mMenu);
mMenuPopup.setPanelView(mMenuPanel);
setAnchor(anchor);
}
@ -95,8 +98,6 @@ public class GeckoPopupMenu implements GeckoMenu.Callback,
if (menuRes > 0) {
mMenuInflater.inflate(menuRes, mMenu);
}
mMenuPanel.addView(mMenu);
mMenuPopup.setPanelView(mMenuPanel);
}
/**