Bug 909434 - Add ability to drag urlbar, preffed off. r=wesj

This commit is contained in:
wesj 2015-01-29 10:43:40 -08:00
parent fe80563048
commit 066e4e3043
12 changed files with 587 additions and 36 deletions

View File

@ -287,4 +287,7 @@ public class AppConstants {
//#else
false;
//#endif
public static final boolean MOZ_DRAGGABLE_URLBAR = false;
}

View File

@ -259,6 +259,175 @@ public class BrowserApp extends GeckoApp
private final DynamicToolbar mDynamicToolbar = new DynamicToolbar();
private DragHelper mDragHelper;
private class DragHelper implements OuterLayout.DragCallback {
private int[] mToolbarLocation = new int[2]; // to avoid creation every time we need to check for toolbar location.
// When dragging horizontally, the area of mainlayout between left drag bound and right drag bound can
// be dragged. A touch on the right of that area will automatically close the view.
private int mStatusBarHeight;
public DragHelper() {
// If a layout round happens from the root, the offset placed by viewdraghelper gets forgotten and
// main layout gets replaced to offset 0.
((MainLayout) mMainLayout).setLayoutInterceptor(new LayoutInterceptor() {
@Override
public void onLayout() {
if (mRootLayout.isMoving()) {
mRootLayout.restoreTargetViewPosition();
}
}
});
}
@Override
public void onDragProgress(float progress) {
mBrowserToolbar.setToolBarButtonsAlpha(1.0f - progress);
mTabsPanel.translateInRange(progress);
}
@Override
public View getViewToDrag() {
return mMainLayout;
}
/**
* Since pressing the tabs button slides the main layout, whereas draghelper changes its offset, here we
* restore the position of mainlayout as if it was opened by pressing the button. This allows the closing
* mechanism to work.
*/
@Override
public void startDrag(boolean wasOpen) {
if (wasOpen) {
mTabsPanel.setHWLayerEnabled(true);
mMainLayout.offsetTopAndBottom(getDragRange());
mMainLayout.scrollTo(0, 0);
} else {
prepareTabsToShow();
mBrowserToolbar.hideVirtualKeyboard();
}
mBrowserToolbar.setContextMenuEnabled(false);
}
@Override
public void stopDrag(boolean stoppingToOpen) {
if (stoppingToOpen) {
mTabsPanel.setHWLayerEnabled(false);
mMainLayout.offsetTopAndBottom(-getDragRange());
mMainLayout.scrollTo(0, -getDragRange());
} else {
mTabsPanel.hideImmediately();
mTabsPanel.setHWLayerEnabled(false);
}
// Re-enabling context menu only while stopping to close.
if (stoppingToOpen) {
mBrowserToolbar.setContextMenuEnabled(false);
} else {
mBrowserToolbar.setContextMenuEnabled(true);
}
}
@Override
public int getDragRange() {
return mTabsPanel.getVerticalPanelHeight();
}
@Override
public int getOrderedChildIndex(int index) {
// See ViewDragHelper's findTopChildUnder method. ViewDragHelper looks for the topmost view in z order
// to understand what needs to be dragged. Here we are tampering Toast's index in case it's hidden,
// otherwise draghelper would try to drag it.
int mainLayoutIndex = mRootLayout.indexOfChild(mMainLayout);
if (index > mainLayoutIndex && (mToast == null || !mToast.isVisible())) {
return mainLayoutIndex;
} else {
return index;
}
}
@Override
public boolean canDrag(MotionEvent event) {
if (!AppConstants.MOZ_DRAGGABLE_URLBAR) {
return false;
}
// if no current tab is active.
if (Tabs.getInstance().getSelectedTab() == null) {
return false;
}
// currently disabled for tablets.
if (HardwareUtils.isTablet()) {
return false;
}
// not enabled in editing mode.
if (mBrowserToolbar.isEditing()) {
return false;
}
return isInToolbarBounds((int) event.getRawY());
}
@Override
public boolean canInterceptEventWhileOpen(MotionEvent event) {
if (event.getActionMasked() != MotionEvent.ACTION_DOWN) {
return false;
}
// Need to check if are intercepting a touch on main layout since we might hit a visible toast.
if (mRootLayout.findTopChildUnder(event) == mMainLayout &&
isInToolbarBounds((int) event.getRawY())) {
return true;
}
return false;
}
private boolean isInToolbarBounds(int y) {
mBrowserToolbar.getLocationOnScreen(mToolbarLocation);
final int upperLimit = mToolbarLocation[1] + mBrowserToolbar.getMeasuredHeight();
final int lowerLimit = mToolbarLocation[1];
return (y > lowerLimit && y < upperLimit);
}
public void prepareTabsToShow() {
if (ensureTabsPanelExists()) {
// If we've just inflated the tabs panel, only show it once the current
// layout pass is done to avoid displayed temporary UI states during
// relayout.
final ViewTreeObserver vto = mTabsPanel.getViewTreeObserver();
if (vto.isAlive()) {
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mTabsPanel.getViewTreeObserver().removeGlobalOnLayoutListener(this);
prepareTabsToShow();
}
});
}
} else {
mTabsPanel.prepareToDrag();
}
}
public int getLowerLimit() {
return getStatusBarHeight();
}
private int getStatusBarHeight() {
if (mStatusBarHeight != 0) {
return mStatusBarHeight;
}
final int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
mStatusBarHeight = getResources().getDimensionPixelSize(resourceId);
return mStatusBarHeight;
}
Log.e(LOGTAG, "Unable to find statusbar height");
return 0;
}
}
@Override
public View onCreateView(final String name, final Context context, final AttributeSet attrs) {
final View view;
@ -658,6 +827,9 @@ public class BrowserApp extends GeckoApp
}
});
mDragHelper = new DragHelper();
mRootLayout.setDraggableCallback(mDragHelper);
// Set the maximum bits-per-pixel the favicon system cares about.
IconDirectoryEntry.setMaxBPP(GeckoAppShell.getScreenDepth());
}
@ -1358,6 +1530,7 @@ public class BrowserApp extends GeckoApp
invalidateOptionsMenu();
if (mTabsPanel != null) {
mRootLayout.reset();
updateSideBarState();
mTabsPanel.refresh();
}
@ -1381,6 +1554,10 @@ public class BrowserApp extends GeckoApp
});
}
private boolean isSideBar() {
return (HardwareUtils.isTablet() && getOrientation() == Configuration.ORIENTATION_LANDSCAPE);
}
private void updateSideBarState() {
if (NewTabletUI.isEnabled(this)) {
return;
@ -1389,7 +1566,7 @@ public class BrowserApp extends GeckoApp
if (mMainLayoutAnimator != null)
mMainLayoutAnimator.stop();
boolean isSideBar = (HardwareUtils.isTablet() && getOrientation() == Configuration.ORIENTATION_LANDSCAPE);
boolean isSideBar = isSideBar();
final int sidebarWidth = getResources().getDimensionPixelSize(R.dimen.tabs_sidebar_width);
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) mTabsPanel.getLayoutParams();
@ -1401,6 +1578,7 @@ public class BrowserApp extends GeckoApp
mMainLayout.scrollTo(mainLayoutScrollX, 0);
mTabsPanel.setIsSideBar(isSideBar);
mRootLayout.updateDragHelperParameters();
}
@Override
@ -1732,7 +1910,7 @@ public class BrowserApp extends GeckoApp
@Override
public void onGlobalLayout() {
mTabsPanel.getViewTreeObserver().removeGlobalOnLayoutListener(this);
mTabsPanel.show(panel);
showTabs(panel);
}
});
}
@ -1821,10 +1999,13 @@ public class BrowserApp extends GeckoApp
if (!areTabsShown()) {
mTabsPanel.setVisibility(View.INVISIBLE);
mTabsPanel.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
mRootLayout.setClosed();
mBrowserToolbar.setContextMenuEnabled(true);
} else {
// Cancel editing mode to return to page content when the TabsPanel closes. We cancel
// it here because there are graphical glitches if it's canceled while it's visible.
mBrowserToolbar.cancelEdit();
mRootLayout.setOpen();
}
mTabsPanel.finishTabsAnimation();

View File

@ -161,8 +161,9 @@ public abstract class GeckoApp
// after a version upgrade.
private static final int CLEANUP_DEFERRAL_SECONDS = 15;
protected RelativeLayout mRootLayout;
protected OuterLayout mRootLayout;
protected RelativeLayout mMainLayout;
protected RelativeLayout mGeckoLayout;
private View mCameraView;
private OrientationEventListener mCameraOrientationEventListener;
@ -1267,7 +1268,7 @@ public abstract class GeckoApp
setContentView(getLayout());
// Set up Gecko layout.
mRootLayout = (RelativeLayout) findViewById(R.id.root_layout);
mRootLayout = (OuterLayout) findViewById(R.id.root_layout);
mGeckoLayout = (RelativeLayout) findViewById(R.id.gecko_layout);
mMainLayout = (RelativeLayout) findViewById(R.id.main_layout);
@ -2393,11 +2394,24 @@ public abstract class GeckoApp
public static class MainLayout extends RelativeLayout {
private TouchEventInterceptor mTouchEventInterceptor;
private MotionEventInterceptor mMotionEventInterceptor;
private LayoutInterceptor mLayoutInterceptor;
public MainLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (mLayoutInterceptor != null) {
mLayoutInterceptor.onLayout();
}
}
public void setLayoutInterceptor(LayoutInterceptor interceptor) {
mLayoutInterceptor = interceptor;
}
public void setTouchEventInterceptor(TouchEventInterceptor interceptor) {
mTouchEventInterceptor = interceptor;
}

View File

@ -0,0 +1,11 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* 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;
public interface LayoutInterceptor {
public void onLayout();
}

View File

@ -0,0 +1,254 @@
/* 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 android.content.Context;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;
/* Outerlayout is the container layout of all the main views. It allows mainlayout to be dragged while targeting
the toolbar and it's responsible for handling the dragprocess. It relies on ViewDragHelper to ease the drag process.
*/
public class OuterLayout extends RelativeLayout {
private final double AUTO_OPEN_SPEED_LIMIT = 800.0;
private ViewDragHelper mDragHelper;
private int mDraggingBorder;
private int mDragRange;
private boolean mIsOpen = false;
private int mDraggingState = ViewDragHelper.STATE_IDLE;
private DragCallback mDragCallback;
public static interface DragCallback {
public void startDrag(boolean wasOpen);
public void stopDrag(boolean stoppingToOpen);
public int getDragRange();
public int getOrderedChildIndex(int index);
public boolean canDrag(MotionEvent event);
public boolean canInterceptEventWhileOpen(MotionEvent event);
public void onDragProgress(float progress);
public View getViewToDrag();
public int getLowerLimit();
}
private class DragHelperCallback extends ViewDragHelper.Callback {
@Override
public void onViewDragStateChanged(int newState) {
if (newState == mDraggingState) { // no change
return;
}
// if the view stopped moving.
if ((mDraggingState == ViewDragHelper.STATE_DRAGGING || mDraggingState == ViewDragHelper.STATE_SETTLING) &&
newState == ViewDragHelper.STATE_IDLE) {
final float rangeToCheck = mDragRange;
final float lowerLimit = mDragCallback.getLowerLimit();
if (mDraggingBorder == lowerLimit) {
mIsOpen = false;
mDragCallback.onDragProgress(0);
} else if (mDraggingBorder == rangeToCheck) {
mIsOpen = true;
mDragCallback.onDragProgress(1);
}
mDragCallback.stopDrag(mIsOpen);
}
// The view was previuosly moving.
if (newState == ViewDragHelper.STATE_DRAGGING && !isMoving()) {
mDragCallback.startDrag(mIsOpen);
updateRanges();
}
mDraggingState = newState;
}
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
mDraggingBorder = top;
final float progress = Math.min(1, ((float) top) / mDragRange);
mDragCallback.onDragProgress(progress);
}
@Override
public int getViewVerticalDragRange(View child) {
return mDragRange;
}
@Override
public int getOrderedChildIndex(int index) {
return mDragCallback.getOrderedChildIndex(index);
}
@Override
public boolean tryCaptureView(View view, int i) {
return (view.getId() == mDragCallback.getViewToDrag().getId());
}
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
return top;
}
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
final float rangeToCheck = mDragRange;
final float speedToCheck = yvel;
if (mDraggingBorder == mDragCallback.getLowerLimit()) {
return;
}
if (mDraggingBorder == rangeToCheck) {
return;
}
boolean settleToOpen = false;
// Speed has priority over position.
if (speedToCheck > AUTO_OPEN_SPEED_LIMIT) {
settleToOpen = true;
} else if (speedToCheck < -AUTO_OPEN_SPEED_LIMIT) {
settleToOpen = false;
} else if (mDraggingBorder > rangeToCheck / 2) {
settleToOpen = true;
} else if (mDraggingBorder < rangeToCheck / 2) {
settleToOpen = false;
}
final int settleDestX;
final int settleDestY;
if (settleToOpen) {
settleDestX = 0;
settleDestY = mDragRange;
} else {
settleDestX = 0;
settleDestY = mDragCallback.getLowerLimit();
}
if(mDragHelper.settleCapturedViewAt(settleDestX, settleDestY)) {
ViewCompat.postInvalidateOnAnimation(OuterLayout.this);
}
}
}
public OuterLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
private void updateRanges() {
// Need to wait for the tabs to show in order to fetch the right sizes.
mDragRange = mDragCallback.getDragRange() + mDragCallback.getLowerLimit();
}
private void updateOrientation() {
mDragHelper.setEdgeTrackingEnabled(0);
}
@Override
protected void onFinishInflate() {
mDragHelper = ViewDragHelper.create(this, 1.0f, new DragHelperCallback());
mIsOpen = false;
super.onFinishInflate();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (mDragCallback.canDrag(event)) {
if (mDragHelper.shouldInterceptTouchEvent(event)) {
return true;
}
}
// Because while open the target layout is translated and draghelper does not catch it.
if (mIsOpen && mDragCallback.canInterceptEventWhileOpen(event)) {
return true;
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// touch events can be passed to the helper if we target the toolbar or we are already dragging.
if (mDragCallback.canDrag(event) || mDraggingState == ViewDragHelper.STATE_DRAGGING) {
mDragHelper.processTouchEvent(event);
}
return true;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// The first time fennec is started, tabs might not have been created while we drag. In that case we need
// an arbitrary range to start dragging that will be updated as soon as the tabs are created.
if (mDragRange == 0) {
mDragRange = h / 2;
}
super.onSizeChanged(w, h, oldw, oldh);
}
@Override
public void computeScroll() { // needed for automatic settling.
if (mDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
/**
* To be called when closing the tabs from outside (i.e. when touching the main layout).
*/
public void setClosed() {
mIsOpen = false;
mDragHelper.abort();
}
/**
* To be called when opening the tabs from outside (i.e. when clicking on the tabs button).
*/
public void setOpen() {
mIsOpen = true;
mDragHelper.abort();
}
public void setDraggableCallback(DragCallback dragCallback) {
mDragCallback = dragCallback;
updateOrientation();
}
// If a change happens while we are dragging, we abort the dragging and set to open state.
public void reset() {
updateOrientation();
if (isMoving()) {
mDragHelper.abort();
if (mDragCallback != null) {
mDragCallback.stopDrag(false);
mDragCallback.onDragProgress(0f);
}
}
}
public void updateDragHelperParameters() {
mDragRange = mDragCallback.getDragRange() + mDragCallback.getLowerLimit();
updateOrientation();
}
public boolean isMoving() {
return (mDraggingState == ViewDragHelper.STATE_DRAGGING ||
mDraggingState == ViewDragHelper.STATE_SETTLING);
}
public boolean isOpen() {
return mIsOpen;
}
public View findTopChildUnder(MotionEvent event) {
return mDragHelper.findTopChildUnder((int) event.getX(), (int) event.getY());
}
public void restoreTargetViewPosition() {
mDragCallback.getViewToDrag().offsetTopAndBottom(mDraggingBorder);
}
}

View File

@ -333,6 +333,7 @@ gbjar.sources += [
'InputMethods.java',
'IntentHelper.java',
'JavaAddonManager.java',
'LayoutInterceptor.java',
'LocaleManager.java',
'Locales.java',
'lwt/LightweightTheme.java',
@ -356,6 +357,7 @@ gbjar.sources += [
'NotificationService.java',
'NSSBridge.java',
'OrderedBroadcastHelper.java',
'OuterLayout.java',
'preferences/AlignRightLinkPreference.java',
'preferences/AndroidImport.java',
'preferences/AndroidImportPreference.java',

View File

@ -3,7 +3,7 @@
- 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/. -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
<org.mozilla.gecko.OuterLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:gecko="http://schemas.android.com/apk/res-auto"
android:id="@+id/root_layout"
android:layout_width="match_parent"
@ -134,4 +134,4 @@
android:layout="@layout/button_toast"
style="@style/Toast"/>
</RelativeLayout>
</org.mozilla.gecko.OuterLayout>

View File

@ -192,6 +192,8 @@
<dimen name="tab_history_bg_width">2dp</dimen>
<dimen name="tab_history_border_padding">2dp</dimen>
<dimen name="horizontal_drag_area">256dp</dimen>
<!-- Find-In-Page dialog dimensions. -->
<dimen name="find_in_page_text_margin_left">5dip</dimen>
<dimen name="find_in_page_text_margin_right">12dip</dimen>

View File

@ -14,6 +14,8 @@ import org.mozilla.gecko.R;
import org.mozilla.gecko.Telemetry;
import org.mozilla.gecko.TelemetryContract;
import org.mozilla.gecko.animation.PropertyAnimator;
import org.mozilla.gecko.Tab;
import org.mozilla.gecko.Tabs;
import org.mozilla.gecko.animation.ViewHelper;
import org.mozilla.gecko.lwt.LightweightTheme;
import org.mozilla.gecko.lwt.LightweightThemeDrawable;
@ -393,15 +395,40 @@ public class TabsPanel extends LinearLayout
}
public void show(Panel panelToShow) {
if (!isShown())
final boolean showAnimation = !mVisible;
prepareToShow(panelToShow);
if (isSideBar()) {
if (showAnimation) {
dispatchLayoutChange(getWidth(), getHeight());
}
} else {
int height = getVerticalPanelHeight();
dispatchLayoutChange(getWidth(), height);
}
}
public void prepareToDrag() {
Tab selectedTab = Tabs.getInstance().getSelectedTab();
if (selectedTab != null && selectedTab.isPrivate()) {
prepareToShow(TabsPanel.Panel.PRIVATE_TABS);
} else {
prepareToShow(TabsPanel.Panel.NORMAL_TABS);
}
if (mIsSideBar) {
prepareSidebarAnimation(getWidth());
}
}
public void prepareToShow(Panel panelToShow) {
if (!isShown()) {
setVisibility(View.VISIBLE);
}
if (mPanel != null) {
// Hide the old panel.
mPanel.hide();
}
final boolean showAnimation = !mVisible;
mVisible = true;
mCurrentPanel = panelToShow;
@ -431,20 +458,20 @@ public class TabsPanel extends LinearLayout
if (!HardwareUtils.hasMenuButton()) {
mMenuButton.setVisibility(View.VISIBLE);
mMenuButton.setEnabled(true);
mPopupMenu.setAnchor(mMenuButton);
} else {
mPopupMenu.setAnchor(mAddTab);
}
if (isSideBar()) {
if (showAnimation)
dispatchLayoutChange(getWidth(), getHeight());
} else {
int actionBarHeight = mContext.getResources().getDimensionPixelSize(R.dimen.browser_toolbar_height);
int height = actionBarHeight + getTabContainerHeight(mTabsContainer);
dispatchLayoutChange(getWidth(), height);
}
mHeaderVisible = true;
public void hideImmediately() {
mVisible = false;
setVisibility(View.INVISIBLE);
}
public int getVerticalPanelHeight() {
final int actionBarHeight = mContext.getResources().getDimensionPixelSize(R.dimen.browser_toolbar_height);
final int height = actionBarHeight + getTabContainerHeight(mTabsContainer);
return height;
}
public void hide() {
@ -488,6 +515,28 @@ public class TabsPanel extends LinearLayout
return mCurrentPanel;
}
public void setHWLayerEnabled(boolean enabled) {
if (Versions.preHC) {
return;
}
if (enabled) {
mHeader.setLayerType(View.LAYER_TYPE_HARDWARE, null);
mTabsContainer.setLayerType(View.LAYER_TYPE_HARDWARE, null);
} else {
mHeader.setLayerType(View.LAYER_TYPE_NONE, null);
mTabsContainer.setLayerType(View.LAYER_TYPE_NONE, null);
}
}
public void prepareSidebarAnimation(int tabsPanelWidth) {
if (mVisible) {
ViewHelper.setTranslationX(mHeader, -tabsPanelWidth);
ViewHelper.setTranslationX(mTabsContainer, -tabsPanelWidth);
// The footer view is only present on the sidebar, v11+.
ViewHelper.setTranslationX(mFooter, -tabsPanelWidth);
}
}
public void prepareTabsAnimation(PropertyAnimator animator) {
// Not worth doing this on pre-Honeycomb without proper
// hardware accelerated animations.
@ -497,13 +546,7 @@ public class TabsPanel extends LinearLayout
if (mIsSideBar) {
final int tabsPanelWidth = getWidth();
if (mVisible) {
ViewHelper.setTranslationX(mHeader, -tabsPanelWidth);
ViewHelper.setTranslationX(mTabsContainer, -tabsPanelWidth);
// The footer view is only present on the sidebar, v11+.
ViewHelper.setTranslationX(mFooter, -tabsPanelWidth);
}
prepareSidebarAnimation(tabsPanelWidth);
final int translationX = (mVisible ? 0 : -tabsPanelWidth);
animator.attach(mTabsContainer, PropertyAnimator.Property.TRANSLATION_X, translationX);
animator.attach(mHeader, PropertyAnimator.Property.TRANSLATION_X, translationX);
@ -523,8 +566,25 @@ public class TabsPanel extends LinearLayout
animator.attach(mHeader, PropertyAnimator.Property.TRANSLATION_Y, translationY);
}
mHeader.setLayerType(View.LAYER_TYPE_HARDWARE, null);
mTabsContainer.setLayerType(View.LAYER_TYPE_HARDWARE, null);
setHWLayerEnabled(true);
}
public void translateInRange(float progress) {
final Resources resources = getContext().getResources();
if (!mIsSideBar) {
final int toolbarHeight = resources.getDimensionPixelSize(R.dimen.browser_toolbar_height);
final int translationY = (int) - ((1 - progress) * toolbarHeight);
ViewHelper.setTranslationY(mHeader, translationY);
ViewHelper.setTranslationY(mTabsContainer, translationY);
mTabsContainer.setAlpha(progress);
} else {
final int tabsPanelWidth = getWidth();
prepareSidebarAnimation(tabsPanelWidth);
final int translationX = (int) - ((1 - progress) * tabsPanelWidth);
ViewHelper.setTranslationX(mHeader, translationX);
ViewHelper.setTranslationX(mTabsContainer, translationX);
ViewHelper.setTranslationX(mFooter, translationX);
}
}
public void finishTabsAnimation() {
@ -532,10 +592,9 @@ public class TabsPanel extends LinearLayout
return;
}
mHeader.setLayerType(View.LAYER_TYPE_NONE, null);
mTabsContainer.setLayerType(View.LAYER_TYPE_NONE, null);
setHWLayerEnabled(false);
// If the tabs panel is now hidden, call hide() on current panel and unset it as the current panel
// If the tray is now hidden, call hide() on current panel and unset it as the current panel
// to avoid hide() being called again when the layout is opened next.
if (!mVisible && mPanel != null) {
mPanel.hide();

View File

@ -140,6 +140,7 @@ public abstract class BrowserToolbar extends ThemedRelativeLayout
private final int shadowSize;
private final ToolbarPrefs prefs;
private boolean contextMenuEnabled = true;
public abstract boolean isAnimating();
@ -243,8 +244,8 @@ public abstract class BrowserToolbar extends ThemedRelativeLayout
setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
// We don't the context menu while editing
if (isEditing()) {
// We don't the context menu while editing or while dragging
if (isEditing() || !contextMenuEnabled) {
return;
}
@ -569,16 +570,19 @@ public abstract class BrowserToolbar extends ThemedRelativeLayout
menuButton.setNextFocusDownId(nextId);
}
public void hideVirtualKeyboard() {
InputMethodManager imm =
(InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(tabsButton.getWindowToken(), 0);
}
private void toggleTabs() {
if (activity.areTabsShown()) {
if (activity.hasTabsSideBar())
activity.hideTabs();
} else {
// hide the virtual keyboard
InputMethodManager imm =
(InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(tabsButton.getWindowToken(), 0);
hideVirtualKeyboard();
Tab tab = Tabs.getInstance().getSelectedTab();
if (tab != null) {
if (!tab.isPrivate())
@ -673,6 +677,13 @@ public abstract class BrowserToolbar extends ThemedRelativeLayout
}
}
public void setToolBarButtonsAlpha(float alpha) {
ViewHelper.setAlpha(tabsCounter, alpha);
if (hasSoftMenuButton && !HardwareUtils.isTablet()) {
ViewHelper.setAlpha(menuIcon, alpha);
}
}
public void onEditSuggestion(String suggestion) {
if (!isEditing()) {
return;
@ -948,6 +959,10 @@ public abstract class BrowserToolbar extends ThemedRelativeLayout
return drawable;
}
public void setContextMenuEnabled(boolean enabled) {
contextMenuEnabled = enabled;
}
public static class TabEditingState {
// The edited text from the most recent time this tab was unselected.
protected String lastEditingText;

View File

@ -172,6 +172,12 @@ class BrowserToolbarNewTablet extends BrowserToolbarTabletBase {
// Do nothing.
}
@Override
public void setToolBarButtonsAlpha(float alpha) {
// Do nothing;
}
@Override
public void startEditing(final String url, final PropertyAnimator animator) {
// We already know the forward button state - no need to store it here.

View File

@ -173,4 +173,8 @@ public class ButtonToast {
hide(false, ReasonHidden.TIMEOUT);
}
};
public boolean isVisible() {
return (mView.getVisibility() == View.VISIBLE);
}
}