author | Martyn Haigh <mhaigh@mozilla.org> |
Tue, 01 Sep 2015 13:57:44 +0100 | |
changeset 260391 | 6ddd2771e1643911cedf92e8714da1fa26c1e74a |
parent 260390 | 7499a1b1ea7c771fe8dffb60322a3d60be7fd2ae |
child 260392 | 4aa12ff974247beecc4b131ddd6299f774163025 |
push id | 64495 |
push user | ryanvm@gmail.com |
push date | Wed, 02 Sep 2015 01:16:33 +0000 |
treeherder | mozilla-inbound@e747377d86eb [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mcomella |
bugs | 1193745 |
milestone | 43.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/mobile/android/base/BrowserApp.java +++ b/mobile/android/base/BrowserApp.java @@ -444,18 +444,16 @@ public class BrowserApp extends GeckoApp } } @Override public View onCreateView(final String name, final Context context, final AttributeSet attrs) { final View view; if (BrowserToolbar.class.getName().equals(name)) { view = BrowserToolbar.create(context, attrs); - } else if (TabsPanel.TabsLayout.class.getName().equals(name)) { - view = TabsPanel.createTabsLayout(context, attrs); } else { view = super.onCreateView(name, context, attrs); } return view; } @Override public void onTabChanged(Tab tab, Tabs.TabEvents msg, Object data) {
--- a/mobile/android/base/moz.build +++ b/mobile/android/base/moz.build @@ -465,17 +465,16 @@ gbjar.sources += [ 'tabs/TabHistoryController.java', 'tabs/TabHistoryFragment.java', 'tabs/TabHistoryItemRow.java', 'tabs/TabHistoryPage.java', 'tabs/TabPanelBackButton.java', 'tabs/TabsGridLayout.java', 'tabs/TabsLayoutAdapter.java', 'tabs/TabsLayoutItemView.java', - 'tabs/TabsListLayout.java', 'tabs/TabsPanel.java', 'tabs/TabsPanelThumbnailView.java', 'Telemetry.java', 'TelemetryContract.java', 'TextSelection.java', 'TextSelectionHandle.java', 'ThumbnailHelper.java', 'tiles/Tile.java',
--- a/mobile/android/base/resources/layout/private_tabs_panel.xml +++ b/mobile/android/base/resources/layout/private_tabs_panel.xml @@ -9,17 +9,17 @@ <ImageView android:id="@+id/private_tabs_empty" android:layout_height="wrap_content" android:layout_width="wrap_content" android:src="@drawable/private_masq" android:layout_gravity="center"/> <!-- Note: for an unknown reason, scrolling in the TabsLayout does not work unless it is laid out after the empty view. --> - <view class="org.mozilla.gecko.tabs.TabsPanel$TabsLayout" + <org.mozilla.gecko.tabs.TabsGridLayout android:id="@+id/private_tabs_layout" style="@style/TabsLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:choiceMode="singleChoice" gecko:tabs="tabs_private"/> </merge>
--- a/mobile/android/base/resources/layout/tabs_layout_item_view.xml +++ b/mobile/android/base/resources/layout/tabs_layout_item_view.xml @@ -11,19 +11,19 @@ android:layout_height="wrap_content" android:gravity="center" android:orientation="vertical"> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:duplicateParentState="true" - android:paddingLeft="@dimen/tablet_tab_highlight_stroke_width" - android:paddingRight="@dimen/tablet_tab_highlight_stroke_width" - android:paddingBottom="@dimen/tablet_tab_highlight_stroke_width"> + android:paddingLeft="@dimen/tab_highlight_stroke_width" + android:paddingRight="@dimen/tab_highlight_stroke_width" + android:paddingBottom="@dimen/tab_highlight_stroke_width"> <org.mozilla.gecko.widget.FadedSingleColorTextView android:id="@+id/title" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_weight="1.0" style="@style/TabLayoutItemTextAppearance" android:textSize="14sp" @@ -57,20 +57,20 @@ </LinearLayout> <!-- We set state_private on this View dynamically in TabsGridLayout. --> <org.mozilla.gecko.widget.TabThumbnailWrapper android:id="@+id/wrapper" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:padding="@dimen/tablet_tab_highlight_stroke_width" + android:padding="@dimen/tab_highlight_stroke_width" android:background="@drawable/tab_thumbnail" android:duplicateParentState="true"> <org.mozilla.gecko.tabs.TabsPanelThumbnailView android:id="@+id/thumbnail" - android:layout_width="@dimen/tablet_tab_thumbnail_width" - android:layout_height="@dimen/tablet_tab_thumbnail_height" + android:layout_width="@dimen/tab_thumbnail_width" + android:layout_height="@dimen/tab_thumbnail_height" /> </org.mozilla.gecko.widget.TabThumbnailWrapper> </org.mozilla.gecko.tabs.TabsLayoutItemView>
--- a/mobile/android/base/resources/layout/tabs_panel_default.xml +++ b/mobile/android/base/resources/layout/tabs_panel_default.xml @@ -61,17 +61,17 @@ </RelativeLayout> <FrameLayout android:id="@+id/tabs_container" android:layout_width="match_parent" android:layout_height="match_parent"> - <view class="org.mozilla.gecko.tabs.TabsPanel$TabsLayout" + <org.mozilla.gecko.tabs.TabsGridLayout android:id="@+id/normal_tabs" style="@style/TabsLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:choiceMode="singleChoice" android:visibility="gone" gecko:tabs="tabs_normal"/>
--- a/mobile/android/base/resources/values-land/dimens.xml +++ b/mobile/android/base/resources/values-land/dimens.xml @@ -4,10 +4,10 @@ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> <resources> <!-- Remote Tabs static view top padding. Less in landscape on phones. --> <dimen name="home_remote_tabs_top_padding">16dp</dimen> <dimen name="page_group_height">64dp</dimen> - <dimen name="tablet_tab_panel_grid_padding">48dp</dimen> + <dimen name="tab_panel_grid_padding">48dp</dimen> </resources>
new file mode 100644 --- /dev/null +++ b/mobile/android/base/resources/values-sw240dp/dimens.xml @@ -0,0 +1,10 @@ +<?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/. --> + +<resources> + <dimen name="tab_panel_column_width">143dip</dimen> + <dimen name="tab_thumbnail_height">100dip</dimen> + <dimen name="tab_thumbnail_width">135dip</dimen> +</resources>
new file mode 100644 --- /dev/null +++ b/mobile/android/base/resources/values-sw400dp/dimens.xml @@ -0,0 +1,10 @@ +<?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/. --> + +<resources> + <dimen name="tab_panel_column_width">174dip</dimen> + <dimen name="tab_thumbnail_height">120dip</dimen> + <dimen name="tab_thumbnail_width">168dip</dimen> +</resources>
--- a/mobile/android/base/resources/values-xlarge-land-v11/dimens.xml +++ b/mobile/android/base/resources/values-xlarge-land-v11/dimens.xml @@ -1,10 +1,10 @@ <?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/. --> <resources> - <dimen name="tablet_tab_panel_grid_padding">64dp</dimen> + <dimen name="tab_panel_grid_padding">64dp</dimen> </resources>
--- a/mobile/android/base/resources/values-xlarge-v11/dimens.xml +++ b/mobile/android/base/resources/values-xlarge-v11/dimens.xml @@ -1,11 +1,11 @@ <?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/. --> <resources> <dimen name="panel_grid_view_column_width">250dp</dimen> - <dimen name="tablet_tab_panel_grid_padding">48dp</dimen> + <dimen name="tab_panel_grid_padding">48dp</dimen> </resources>
--- a/mobile/android/base/resources/values/dimens.xml +++ b/mobile/android/base/resources/values/dimens.xml @@ -125,39 +125,37 @@ <dimen name="menu_popup_width">256dp</dimen> <dimen name="nav_button_border_width">1dp</dimen> <dimen name="prompt_service_group_padding_size">32dp</dimen> <dimen name="prompt_service_icon_size">36dp</dimen> <dimen name="prompt_service_icon_text_padding">10dp</dimen> <dimen name="prompt_service_inputs_padding">16dp</dimen> <dimen name="prompt_service_left_right_text_with_icon_padding">10dp</dimen> <dimen name="prompt_service_top_bottom_text_with_icon_padding">8dp</dimen> - <dimen name="tab_thumbnail_height">90dp</dimen> - <dimen name="tab_thumbnail_width">160dp</dimen> <dimen name="tabs_panel_indicator_width">60dp</dimen> <dimen name="tabs_panel_button_width">48dp</dimen> <dimen name="tabs_strip_height">48dp</dimen> <dimen name="tabs_strip_button_width">100dp</dimen> <dimen name="tabs_strip_button_padding">18dp</dimen> <dimen name="tabs_strip_shadow_size">1dp</dimen> <dimen name="tabs_layout_horizontal_height">156dp</dimen> <dimen name="text_selection_handle_width">47dp</dimen> <dimen name="text_selection_handle_height">58dp</dimen> <dimen name="text_selection_handle_shadow">11dp</dimen> <dimen name="validation_message_height">50dp</dimen> <dimen name="validation_message_margin_top">6dp</dimen> - <dimen name="tablet_tab_thumbnail_width">168dp</dimen> - <dimen name="tablet_tab_thumbnail_height">140dp</dimen> - <dimen name="tablet_tab_panel_column_width">178dp</dimen> - <dimen name="tablet_tab_panel_grid_padding">19dp</dimen> - <dimen name="tablet_tab_panel_grid_vspacing">21dp</dimen> - <dimen name="tablet_tab_panel_grid_padding_top">24dp</dimen> + <dimen name="tab_thumbnail_width">121dp</dimen> + <dimen name="tab_thumbnail_height">90dp</dimen> + <dimen name="tab_panel_column_width">129dp</dimen> + <dimen name="tab_panel_grid_padding">20dp</dimen> + <dimen name="tab_panel_grid_vspacing">20dp</dimen> + <dimen name="tab_panel_grid_padding_top">19dp</dimen> - <dimen name="tablet_tab_highlight_stroke_width">5dp</dimen> + <dimen name="tab_highlight_stroke_width">4dp</dimen> <!-- PageActionButtons dimensions --> <dimen name="page_action_button_width">32dp</dimen> <!-- Banner --> <dimen name="home_banner_height">72dp</dimen> <dimen name="home_banner_close_width">42dp</dimen> <dimen name="home_banner_icon_height">48dip</dimen>
--- a/mobile/android/base/resources/values/styles.xml +++ b/mobile/android/base/resources/values/styles.xml @@ -200,19 +200,19 @@ <style name="Widget.TabsGridLayout" parent="Widget.GridView"> <item name="android:layout_width">match_parent</item> <item name="android:layout_height">match_parent</item> <item name="android:paddingTop">0dp</item> <item name="android:stretchMode">spacingWidth</item> <item name="android:scrollbarStyle">outsideOverlay</item> <item name="android:gravity">center</item> <item name="android:numColumns">auto_fit</item> - <item name="android:columnWidth">@dimen/tablet_tab_panel_column_width</item> + <item name="android:columnWidth">@dimen/tab_panel_column_width</item> <item name="android:horizontalSpacing">2dp</item> - <item name="android:verticalSpacing">@dimen/tablet_tab_panel_grid_vspacing</item> + <item name="android:verticalSpacing">@dimen/tab_panel_grid_vspacing</item> <item name="android:drawSelectorOnTop">true</item> <item name="android:clipToPadding">false</item> </style> <style name="Widget.BookmarkItemView" parent="Widget.TwoLinePageRow"/> <style name="Widget.BookmarksListView" parent="Widget.HomeListView"/>
--- a/mobile/android/base/tabs/PrivateTabsPanel.java +++ b/mobile/android/base/tabs/PrivateTabsPanel.java @@ -8,58 +8,51 @@ package org.mozilla.gecko.tabs; import org.mozilla.gecko.R; import org.mozilla.gecko.tabs.TabsPanel.CloseAllPanelView; import org.mozilla.gecko.tabs.TabsPanel.TabsLayout; import android.content.Context; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; -import android.view.ViewGroup; import android.widget.FrameLayout; -import android.widget.LinearLayout; /** * A container that wraps the private tabs {@link android.widget.AdapterView} and empty * {@link android.view.View} to manage both of their visibility states by changing the visibility of * this container as calling {@link android.widget.AdapterView#setVisibility} does not affect the * empty View's visibility. */ class PrivateTabsPanel extends FrameLayout implements CloseAllPanelView { private final TabsLayout tabsLayout; - public PrivateTabsPanel(Context context, AttributeSet attrs) { + public PrivateTabsPanel(final Context context, final AttributeSet attrs) { super(context, attrs); LayoutInflater.from(context).inflate(R.layout.private_tabs_panel, this); tabsLayout = (TabsLayout) findViewById(R.id.private_tabs_layout); final View emptyTabsFrame = findViewById(R.id.private_tabs_empty); tabsLayout.setEmptyView(emptyTabsFrame); } @Override - public void setTabsPanel(TabsPanel panel) { + public void setTabsPanel(final TabsPanel panel) { tabsLayout.setTabsPanel(panel); } @Override public void show() { tabsLayout.show(); setVisibility(View.VISIBLE); } @Override public void hide() { setVisibility(View.GONE); tabsLayout.hide(); } @Override - public boolean shouldExpand() { - return tabsLayout.shouldExpand(); - } - - @Override public void closeAll() { tabsLayout.closeAll(); } }
--- a/mobile/android/base/tabs/TabsGridLayout.java +++ b/mobile/android/base/tabs/TabsGridLayout.java @@ -1,30 +1,31 @@ /* -*- 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.tabs; +import org.mozilla.gecko.AppConstants; import org.mozilla.gecko.GeckoAppShell; import org.mozilla.gecko.GeckoEvent; import org.mozilla.gecko.R; import org.mozilla.gecko.Tab; import org.mozilla.gecko.Tabs; import org.mozilla.gecko.animation.PropertyAnimator; -import org.mozilla.gecko.animation.ViewHelper; import org.mozilla.gecko.tabs.TabsPanel.TabsLayout; import org.mozilla.gecko.widget.themed.ThemedRelativeLayout; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.PointF; import android.graphics.Rect; +import android.os.Build; import android.util.AttributeSet; import android.util.SparseArray; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewTreeObserver; @@ -33,70 +34,68 @@ import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.Button; import android.widget.GridView; import com.nineoldandroids.animation.Animator; import com.nineoldandroids.animation.AnimatorSet; import com.nineoldandroids.animation.ObjectAnimator; import com.nineoldandroids.animation.PropertyValuesHolder; import com.nineoldandroids.animation.ValueAnimator; +import com.nineoldandroids.view.ViewHelper; import java.util.ArrayList; import java.util.List; /** - * A tabs layout implementation for the tablet redesign (bug 1014156). - * Expected to replace TabsListLayout once complete. + * A tabs layout implementation for the tablet redesign (bug 1014156) and later ported to mobile (bug 1193745). */ class TabsGridLayout extends GridView implements TabsLayout, Tabs.OnTabsChangedListener { private static final String LOGTAG = "Gecko" + TabsGridLayout.class.getSimpleName(); public static final int ANIM_DELAY_MULTIPLE_MS = 20; private static final int ANIM_TIME_MS = 200; private static final DecelerateInterpolator ANIM_INTERPOLATOR = new DecelerateInterpolator(); - private final Context mContext; - private final SparseArray<PointF> mTabLocations = new SparseArray<PointF>(); - private final boolean mIsPrivate; - private final TabsLayoutAdapter mTabsAdapter; - private final int mColumnWidth; - private TabsPanel mTabsPanel; + private final SparseArray<PointF> tabLocations = new SparseArray<PointF>(); + private final boolean isPrivate; + private final TabsLayoutAdapter tabsAdapter; + private final int columnWidth; + private TabsPanel tabsPanel; private int lastSelectedTabId; - public TabsGridLayout(Context context, AttributeSet attrs) { + public TabsGridLayout(final Context context, final AttributeSet attrs) { super(context, attrs, R.attr.tabGridLayoutViewStyle); - mContext = context; TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TabsLayout); - mIsPrivate = (a.getInt(R.styleable.TabsLayout_tabs, 0x0) == 1); + isPrivate = (a.getInt(R.styleable.TabsLayout_tabs, 0x0) == 1); a.recycle(); - mTabsAdapter = new TabsGridLayoutAdapter(mContext); - setAdapter(mTabsAdapter); + tabsAdapter = new TabsGridLayoutAdapter(context); + setAdapter(tabsAdapter); setRecyclerListener(new RecyclerListener() { @Override public void onMovedToScrapHeap(View view) { TabsLayoutItemView item = (TabsLayoutItemView) view; item.setThumbnail(null); } }); // The clipToPadding setting in the styles.xml doesn't seem to be working (bug 1101784) // so lets set it manually in code for the moment as it's needed for the padding animation setClipToPadding(false); final Resources resources = getResources(); - mColumnWidth = resources.getDimensionPixelSize(R.dimen.tablet_tab_panel_column_width); + columnWidth = resources.getDimensionPixelSize(R.dimen.tab_panel_column_width); - final int padding = resources.getDimensionPixelSize(R.dimen.tablet_tab_panel_grid_padding); - final int paddingTop = resources.getDimensionPixelSize(R.dimen.tablet_tab_panel_grid_padding_top); + final int padding = resources.getDimensionPixelSize(R.dimen.tab_panel_grid_padding); + final int paddingTop = resources.getDimensionPixelSize(R.dimen.tab_panel_grid_padding_top); // Lets set double the top padding on the bottom so that the last row shows up properly! // Your demise, GridView, cannot come fast enough. final int paddingBottom = paddingTop * 2; setPadding(padding, paddingTop, padding, paddingBottom); setOnItemClickListener(new OnItemClickListener() { @@ -109,45 +108,46 @@ class TabsGridLayout extends GridView }); TabSwipeGestureListener mSwipeListener = new TabSwipeGestureListener(); setOnTouchListener(mSwipeListener); setOnScrollListener(mSwipeListener.makeScrollListener()); } private void populateTabLocations(final Tab removedTab) { - mTabLocations.clear(); + tabLocations.clear(); final int firstPosition = getFirstVisiblePosition(); final int lastPosition = getLastVisiblePosition(); final int numberOfColumns = getNumColumns(); final int childCount = getChildCount(); - final int removedPosition = mTabsAdapter.getPositionForTab(removedTab); + final int removedPosition = tabsAdapter.getPositionForTab(removedTab); for (int x = 1, i = (removedPosition - firstPosition) + 1; i < childCount; i++, x++) { final View child = getChildAt(i); if (child != null) { // Reset the transformations here in case the user is swiping tabs away fast and they swipe a tab // before the last animation has finished (bug 1179195). resetTransforms(child); - mTabLocations.append(x, new PointF(child.getX(), child.getY())); + + tabLocations.append(x, new PointF(child.getX(), child.getY())); } } final boolean firstChildOffScreen = ((firstPosition > 0) || getChildAt(0).getY() < 0); final boolean lastChildVisible = (lastPosition - childCount == firstPosition - 1); final boolean oneItemOnLastRow = (lastPosition % numberOfColumns == 0); if (firstChildOffScreen && lastChildVisible && oneItemOnLastRow) { // We need to set the view's bottom padding to prevent a sudden jump as the // last item in the row is being removed. We then need to remove the padding // via a sweet animation final int removedHeight = getChildAt(0).getMeasuredHeight(); final int verticalSpacing = - getResources().getDimensionPixelOffset(R.dimen.tablet_tab_panel_grid_vspacing); + getResources().getDimensionPixelOffset(R.dimen.tab_panel_grid_vspacing); ValueAnimator paddingAnimator = ValueAnimator.ofInt(getPaddingBottom() + removedHeight + verticalSpacing, getPaddingBottom()); paddingAnimator.setDuration(ANIM_TIME_MS * 2); paddingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { @@ -155,68 +155,65 @@ class TabsGridLayout extends GridView } }); paddingAnimator.start(); } } @Override public void setTabsPanel(TabsPanel panel) { - mTabsPanel = panel; + tabsPanel = panel; } @Override public void show() { setVisibility(View.VISIBLE); Tabs.getInstance().refreshThumbnails(); Tabs.registerOnTabsChangedListener(this); refreshTabsData(); Tab currentlySelectedTab = Tabs.getInstance().getSelectedTab(); if (lastSelectedTabId != currentlySelectedTab.getId()) { - smoothScrollToPosition(mTabsAdapter.getPositionForTab(currentlySelectedTab)); + smoothScrollToPosition(tabsAdapter.getPositionForTab(currentlySelectedTab)); } } @Override public void hide() { lastSelectedTabId = Tabs.getInstance().getSelectedTab().getId(); setVisibility(View.GONE); Tabs.unregisterOnTabsChangedListener(this); GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Tab:Screenshot:Cancel", "")); - mTabsAdapter.clear(); - } - - @Override - public boolean shouldExpand() { - return true; + tabsAdapter.clear(); } private void autoHidePanel() { - mTabsPanel.autoHidePanel(); + tabsPanel.autoHidePanel(); } @Override public void onTabChanged(Tab tab, Tabs.TabEvents msg, Object data) { switch (msg) { case ADDED: // Refresh the list to make sure the new tab is added in the right position. refreshTabsData(); break; case CLOSED: - if (mTabsAdapter.getCount() > 0) { + + // This is limited to >= ICS as animations on GB devices are generally pants + if (Build.VERSION.SDK_INT >= 11 && tabsAdapter.getCount() > 0) { animateRemoveTab(tab); } final Tabs tabsInstance = Tabs.getInstance(); - if (mTabsAdapter.removeTab(tab)) { - if (tab.isPrivate() == mIsPrivate && mTabsAdapter.getCount() > 0) { - int selected = mTabsAdapter.getPositionForTab(tabsInstance.getSelectedTab()); + if (tabsAdapter.removeTab(tab)) { + if (tab.isPrivate() == isPrivate && tabsAdapter.getCount() > 0) { + int selected = tabsAdapter.getPositionForTab(tabsInstance.getSelectedTab()); updateSelectedStyle(selected); } if (!tab.isPrivate()) { // Make sure we always have at least one normal tab final Iterable<Tab> tabs = tabsInstance.getTabsInOrder(); boolean removedTabIsLastNormalTab = true; for (Tab singleTab : tabs) { if (!singleTab.isPrivate()) { @@ -235,58 +232,63 @@ class TabsGridLayout extends GridView // Update the selected position, then fall through... updateSelectedPosition(); case UNSELECTED: // We just need to update the style for the unselected tab... case THUMBNAIL: case TITLE: case RECORDING_CHANGE: case AUDIO_PLAYING_CHANGE: - View view = getChildAt(mTabsAdapter.getPositionForTab(tab) - getFirstVisiblePosition()); + View view = getChildAt(tabsAdapter.getPositionForTab(tab) - getFirstVisiblePosition()); if (view == null) return; ((TabsLayoutItemView) view).assignValues(tab); break; } } // Updates the selected position in the list so that it will be scrolled to the right place. private void updateSelectedPosition() { - int selected = mTabsAdapter.getPositionForTab(Tabs.getInstance().getSelectedTab()); + int selected = tabsAdapter.getPositionForTab(Tabs.getInstance().getSelectedTab()); updateSelectedStyle(selected); if (selected != -1) { setSelection(selected); } } /** * Updates the selected/unselected style for the tabs. * * @param selected position of the selected tab */ private void updateSelectedStyle(int selected) { - for (int i = 0; i < mTabsAdapter.getCount(); i++) { - setItemChecked(i, (i == selected)); + for (int i = 0; i < tabsAdapter.getCount(); i++) { + // setItemChecked doesn't exist until API 11, despite what the API docs say! + if (AppConstants.Versions.feature11Plus) { + setItemChecked(i, (i == selected)); + } else { + setSelection(i); + } } } private void refreshTabsData() { // Store a different copy of the tabs, so that we don't have to worry about // accidentally updating it on the wrong thread. ArrayList<Tab> tabData = new ArrayList<>(); Iterable<Tab> allTabs = Tabs.getInstance().getTabsInOrder(); for (Tab tab : allTabs) { - if (tab.isPrivate() == mIsPrivate) + if (tab.isPrivate() == isPrivate) tabData.add(tab); } - mTabsAdapter.setTabs(tabData); + tabsAdapter.setTabs(tabData); updateSelectedPosition(); } private void resetTransforms(View view) { ViewHelper.setAlpha(view, 1); ViewHelper.setTranslationX(view, 0); ViewHelper.setTranslationY(view, 0); @@ -301,36 +303,36 @@ class TabsGridLayout extends GridView if (getChildCount() == 0) { return; } final Iterable<Tab> tabs = Tabs.getInstance().getTabsInOrder(); for (Tab tab : tabs) { // In the normal panel we want to close all tabs (both private and normal), // but in the private panel we only want to close private tabs. - if (!mIsPrivate || tab.isPrivate()) { + if (!isPrivate || tab.isPrivate()) { Tabs.getInstance().closeTab(tab, false); } } } private View getViewForTab(Tab tab) { - final int position = mTabsAdapter.getPositionForTab(tab); + final int position = tabsAdapter.getPositionForTab(tab); return getChildAt(position - getFirstVisiblePosition()); } void closeTab(View v) { TabsLayoutItemView itemView = (TabsLayoutItemView) v.getTag(); Tab tab = Tabs.getInstance().getTab(itemView.getTabId()); Tabs.getInstance().closeTab(tab, true); } private void animateRemoveTab(final Tab removedTab) { - final int removedPosition = mTabsAdapter.getPositionForTab(removedTab); + final int removedPosition = tabsAdapter.getPositionForTab(removedTab); final View removedView = getViewForTab(removedTab); // The removed position might not have a matching child view // when it's not within the visible range of positions in the strip. if (removedView == null) { return; } @@ -353,22 +355,22 @@ class TabsGridLayout extends GridView PropertyValuesHolder translateX, translateY; for (int x = 0, i = removedPosition - firstPosition; i < childCount; i++, x++) { final View child = getChildAt(i); ObjectAnimator animator; if (i % numberOfColumns == numberOfColumns - 1) { // Animate X & Y - translateX = PropertyValuesHolder.ofFloat("translationX", -(mColumnWidth * numberOfColumns), 0); + translateX = PropertyValuesHolder.ofFloat("translationX", -(columnWidth * numberOfColumns), 0); translateY = PropertyValuesHolder.ofFloat("translationY", removedHeight, 0); animator = ObjectAnimator.ofPropertyValuesHolder(child, translateX, translateY); } else { // Just animate X - translateX = PropertyValuesHolder.ofFloat("translationX", mColumnWidth, 0); + translateX = PropertyValuesHolder.ofFloat("translationX", columnWidth, 0); animator = ObjectAnimator.ofPropertyValuesHolder(child, translateX); } animator.setStartDelay(x * ANIM_DELAY_MULTIPLE_MS); childAnimators.add(animator); } final AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether(childAnimators); @@ -377,30 +379,31 @@ class TabsGridLayout extends GridView animatorSet.start(); // Set the starting position of the child views - because we are delaying the start // of the animation, we need to prevent the items being drawn in their final position // prior to the animation starting for (int x = 1, i = (removedPosition - firstPosition) + 1; i < childCount; i++, x++) { final View child = getChildAt(i); - final PointF targetLocation = mTabLocations.get(x + 1); + final PointF targetLocation = tabLocations.get(x + 1); if (targetLocation == null) { continue; } child.setX(targetLocation.x); child.setY(targetLocation.y); } return true; } }); } + private void animateCancel(final View view) { PropertyAnimator animator = new PropertyAnimator(ANIM_TIME_MS); animator.attach(view, PropertyAnimator.Property.ALPHA, 1); animator.attach(view, PropertyAnimator.Property.TRANSLATION_X, 0); animator.addPropertyAnimationListener(new PropertyAnimator.PropertyAnimationListener() { @Override public void onPropertyAnimationStart() { @@ -431,17 +434,17 @@ class TabsGridLayout extends GridView }; } @Override TabsLayoutItemView newView(int position, ViewGroup parent) { final TabsLayoutItemView item = super.newView(position, parent); item.setCloseOnClickListener(mCloseClickListener); - ((ThemedRelativeLayout) item.findViewById(R.id.wrapper)).setPrivateMode(mIsPrivate); + ((ThemedRelativeLayout) item.findViewById(R.id.wrapper)).setPrivateMode(isPrivate); return item; } @Override public void bindView(TabsLayoutItemView view, Tab tab) { super.bindView(view, tab);
deleted file mode 100644 --- a/mobile/android/base/tabs/TabsListLayout.java +++ /dev/null @@ -1,660 +0,0 @@ -/* -*- 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.tabs; - -import java.util.ArrayList; -import java.util.List; - -import org.mozilla.gecko.animation.PropertyAnimator.Property; -import org.mozilla.gecko.animation.PropertyAnimator; -import org.mozilla.gecko.animation.ViewHelper; -import org.mozilla.gecko.GeckoAppShell; -import org.mozilla.gecko.GeckoEvent; -import org.mozilla.gecko.R; -import org.mozilla.gecko.Tab; -import org.mozilla.gecko.tabs.TabsPanel.TabsLayout; -import org.mozilla.gecko.Tabs; -import org.mozilla.gecko.util.ThreadUtils; -import org.mozilla.gecko.widget.themed.ThemedRelativeLayout; -import org.mozilla.gecko.widget.TwoWayView; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Rect; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.VelocityTracker; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewConfiguration; -import android.widget.Button; - -class TabsListLayout extends TwoWayView - implements TabsLayout, - Tabs.OnTabsChangedListener { - private static final String LOGTAG = "Gecko" + TabsListLayout.class.getSimpleName(); - - private final Context mContext; - private TabsPanel mTabsPanel; - - final private boolean mIsPrivate; - - private final TabsLayoutAdapter mTabsAdapter; - - private final List<View> mPendingClosedTabs; - private int mCloseAnimationCount; - private int mCloseAllAnimationCount; - - private final TabSwipeGestureListener mSwipeListener; - - // Time to animate non-flinged tabs of screen, in milliseconds - private static final int ANIMATION_DURATION = 250; - - // Time between starting successive tab animations in closeAllTabs. - private static final int ANIMATION_CASCADE_DELAY = 75; - - private int mOriginalSize; - - public TabsListLayout(Context context, AttributeSet attrs) { - super(context, attrs); - mContext = context; - - mPendingClosedTabs = new ArrayList<View>(); - - setItemsCanFocus(true); - - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TabsLayout); - mIsPrivate = (a.getInt(R.styleable.TabsLayout_tabs, 0x0) == 1); - a.recycle(); - - mTabsAdapter = new TabsListLayoutAdapter(mContext); - setAdapter(mTabsAdapter); - - mSwipeListener = new TabSwipeGestureListener(); - setOnTouchListener(mSwipeListener); - setOnScrollListener(mSwipeListener.makeScrollListener()); - - setRecyclerListener(new RecyclerListener() { - @Override - public void onMovedToScrapHeap(View view) { - TabsLayoutItemView item = (TabsLayoutItemView) view; - item.setThumbnail(null); - item.setCloseVisible(true); - } - }); - } - - private class TabsListLayoutAdapter extends TabsLayoutAdapter { - private final Button.OnClickListener mCloseOnClickListener; - public TabsListLayoutAdapter (Context context) { - super(context, R.layout.tabs_layout_item_view); - - mCloseOnClickListener = new Button.OnClickListener() { - @Override - public void onClick(View v) { - // The view here is the close button, which has a reference - // to the parent TabsLayoutItemView in it's tag, hence the getTag() call - TabsLayoutItemView item = (TabsLayoutItemView) v.getTag(); - final int pos = (isVertical() ? item.getWidth() : 0 - item.getHeight()); - animateClose(item, pos); - } - }; - } - - @Override - public TabsLayoutItemView newView(int position, ViewGroup parent) { - TabsLayoutItemView item = super.newView(position, parent); - - item.setCloseOnClickListener(mCloseOnClickListener); - ((ThemedRelativeLayout) item.findViewById(R.id.wrapper)).setPrivateMode(mIsPrivate); - - return item; - } - - @Override - public void bindView(TabsLayoutItemView view, Tab tab) { - super.bindView(view, tab); - - // If we're recycling this view, there's a chance it was transformed during - // the close animation. Remove any of those properties. - resetTransforms(view); - } - - } - - @Override - public void setTabsPanel(TabsPanel panel) { - mTabsPanel = panel; - } - - @Override - public void show() { - setVisibility(View.VISIBLE); - Tabs.getInstance().refreshThumbnails(); - Tabs.registerOnTabsChangedListener(this); - refreshTabsData(); - } - - @Override - public void hide() { - setVisibility(View.GONE); - Tabs.unregisterOnTabsChangedListener(this); - GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Tab:Screenshot:Cancel","")); - mTabsAdapter.clear(); - } - - @Override - public boolean shouldExpand() { - return isVertical(); - } - - private void autoHidePanel() { - mTabsPanel.autoHidePanel(); - } - - @Override - public void onTabChanged(Tab tab, Tabs.TabEvents msg, Object data) { - switch (msg) { - case ADDED: - // Refresh the list to make sure the new tab is added in the right position. - refreshTabsData(); - break; - - case CLOSED: - if (tab.isPrivate() == mIsPrivate && mTabsAdapter.getCount() > 0) { - if (mTabsAdapter.removeTab(tab)) { - int selected = mTabsAdapter.getPositionForTab(Tabs.getInstance().getSelectedTab()); - updateSelectedStyle(selected); - } - } - break; - - case SELECTED: - // Update the selected position, then fall through... - updateSelectedPosition(); - case UNSELECTED: - // We just need to update the style for the unselected tab... - case THUMBNAIL: - case TITLE: - case RECORDING_CHANGE: - case AUDIO_PLAYING_CHANGE: - View view = getChildAt(mTabsAdapter.getPositionForTab(tab) - getFirstVisiblePosition()); - if (view == null) - return; - - TabsLayoutItemView item = (TabsLayoutItemView) view; - item.assignValues(tab); - break; - } - } - - // Updates the selected position in the list so that it will be scrolled to the right place. - private void updateSelectedPosition() { - int selected = mTabsAdapter.getPositionForTab(Tabs.getInstance().getSelectedTab()); - updateSelectedStyle(selected); - - if (selected != -1) { - setSelection(selected); - } - } - - /** - * Updates the selected/unselected style for the tabs. - * - * @param selected position of the selected tab - */ - private void updateSelectedStyle(int selected) { - for (int i = 0; i < mTabsAdapter.getCount(); i++) { - setItemChecked(i, (i == selected)); - } - } - - private void refreshTabsData() { - // Store a different copy of the tabs, so that we don't have to worry about - // accidentally updating it on the wrong thread. - ArrayList<Tab> tabData = new ArrayList<Tab>(); - - Iterable<Tab> allTabs = Tabs.getInstance().getTabsInOrder(); - for (Tab tab : allTabs) { - if (tab.isPrivate() == mIsPrivate) - tabData.add(tab); - } - - mTabsAdapter.setTabs(tabData); - updateSelectedPosition(); - } - - public void resetTransforms(View view) { - ViewHelper.setAlpha(view, 1); - - if (isVertical()) { - ViewHelper.setTranslationX(view, 0); - } else { - ViewHelper.setTranslationY(view, 0); - } - - // We only need to reset the height or width after individual tab close animations. - if (mOriginalSize != 0) { - if (isVertical()) { - ViewHelper.setHeight(view, mOriginalSize); - } else { - ViewHelper.setWidth(view, mOriginalSize); - } - } - } - - private boolean isVertical() { - return (getOrientation().compareTo(TwoWayView.Orientation.VERTICAL) == 0); - } - - @Override - public void closeAll() { - final int childCount = getChildCount(); - - // Just close the panel if there are no tabs to close. - if (childCount == 0) { - autoHidePanel(); - return; - } - - // Disable the view so that gestures won't interfere wth the tab close animation. - setEnabled(false); - - // Delay starting each successive animation to create a cascade effect. - int cascadeDelay = 0; - - for (int i = childCount - 1; i >= 0; i--) { - final View view = getChildAt(i); - final PropertyAnimator animator = new PropertyAnimator(ANIMATION_DURATION); - animator.attach(view, Property.ALPHA, 0); - - if (isVertical()) { - animator.attach(view, Property.TRANSLATION_X, view.getWidth()); - } else { - animator.attach(view, Property.TRANSLATION_Y, view.getHeight()); - } - - mCloseAllAnimationCount++; - - animator.addPropertyAnimationListener(new PropertyAnimator.PropertyAnimationListener() { - @Override - public void onPropertyAnimationStart() { } - - @Override - public void onPropertyAnimationEnd() { - mCloseAllAnimationCount--; - if (mCloseAllAnimationCount > 0) { - return; - } - - // Hide the panel after the animation is done. - autoHidePanel(); - - // Re-enable the view after the animation is done. - TabsListLayout.this.setEnabled(true); - - // Then actually close all the tabs. - final Iterable<Tab> tabs = Tabs.getInstance().getTabsInOrder(); - for (Tab tab : tabs) { - // In the normal panel we want to close all tabs (both private and normal), - // but in the private panel we only want to close private tabs. - if (!mIsPrivate || tab.isPrivate()) { - Tabs.getInstance().closeTab(tab, false); - } - } - } - }); - - ThreadUtils.getUiHandler().postDelayed(new Runnable() { - @Override - public void run() { - animator.start(); - } - }, cascadeDelay); - - cascadeDelay += ANIMATION_CASCADE_DELAY; - } - } - - private void animateClose(final View view, int pos) { - PropertyAnimator animator = new PropertyAnimator(ANIMATION_DURATION); - animator.attach(view, Property.ALPHA, 0); - - if (isVertical()) - animator.attach(view, Property.TRANSLATION_X, pos); - else - animator.attach(view, Property.TRANSLATION_Y, pos); - - mCloseAnimationCount++; - mPendingClosedTabs.add(view); - - animator.addPropertyAnimationListener(new PropertyAnimator.PropertyAnimationListener() { - @Override - public void onPropertyAnimationStart() { } - @Override - public void onPropertyAnimationEnd() { - mCloseAnimationCount--; - if (mCloseAnimationCount > 0) - return; - - for (View pendingView : mPendingClosedTabs) { - animateFinishClose(pendingView); - } - - mPendingClosedTabs.clear(); - } - }); - - if (mTabsAdapter.getCount() == 1) - autoHidePanel(); - - animator.start(); - } - - private void animateFinishClose(final View view) { - PropertyAnimator animator = new PropertyAnimator(ANIMATION_DURATION); - - final boolean isVertical = isVertical(); - if (isVertical) - animator.attach(view, Property.HEIGHT, 1); - else - animator.attach(view, Property.WIDTH, 1); - - final int tabId = ((TabsLayoutItemView) view).getTabId(); - - // Caching this assumes that all rows are the same height - if (mOriginalSize == 0) { - mOriginalSize = (isVertical ? view.getHeight() : view.getWidth()); - } - - animator.addPropertyAnimationListener(new PropertyAnimator.PropertyAnimationListener() { - @Override - public void onPropertyAnimationStart() { } - @Override - public void onPropertyAnimationEnd() { - Tabs tabs = Tabs.getInstance(); - Tab tab = tabs.getTab(tabId); - tabs.closeTab(tab, true); - } - }); - - animator.start(); - } - - private void animateCancel(final View view) { - PropertyAnimator animator = new PropertyAnimator(ANIMATION_DURATION); - animator.attach(view, Property.ALPHA, 1); - - if (isVertical()) - animator.attach(view, Property.TRANSLATION_X, 0); - else - animator.attach(view, Property.TRANSLATION_Y, 0); - - - animator.addPropertyAnimationListener(new PropertyAnimator.PropertyAnimationListener() { - @Override - public void onPropertyAnimationStart() { } - @Override - public void onPropertyAnimationEnd() { - TabsLayoutItemView tab = (TabsLayoutItemView) view; - tab.setCloseVisible(true); - } - }); - - animator.start(); - } - - private class TabSwipeGestureListener implements View.OnTouchListener { - // same value the stock browser uses for after drag animation velocity in pixels/sec - // http://androidxref.com/4.0.4/xref/packages/apps/Browser/src/com/android/browser/NavTabScroller.java#61 - private static final float MIN_VELOCITY = 750; - - private final int mSwipeThreshold; - private final int mMinFlingVelocity; - - private final int mMaxFlingVelocity; - private VelocityTracker mVelocityTracker; - - private int mListWidth = 1; - private int mListHeight = 1; - - private View mSwipeView; - private Runnable mPendingCheckForTap; - - private float mSwipeStartX; - private float mSwipeStartY; - private boolean mSwiping; - private boolean mEnabled; - - public TabSwipeGestureListener() { - mEnabled = true; - - ViewConfiguration vc = ViewConfiguration.get(TabsListLayout.this.getContext()); - mSwipeThreshold = vc.getScaledTouchSlop(); - mMinFlingVelocity = (int) (getContext().getResources().getDisplayMetrics().density * MIN_VELOCITY); - mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity(); - } - - public void setEnabled(boolean enabled) { - mEnabled = enabled; - } - - public TwoWayView.OnScrollListener makeScrollListener() { - return new TwoWayView.OnScrollListener() { - @Override - public void onScrollStateChanged(TwoWayView twoWayView, int scrollState) { - setEnabled(scrollState != TwoWayView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); - } - - @Override - public void onScroll(TwoWayView twoWayView, int i, int i1, int i2) { - } - }; - } - - @Override - public boolean onTouch(View view, MotionEvent e) { - if (!mEnabled) - return false; - - if (mListWidth < 2 || mListHeight < 2) { - mListWidth = TabsListLayout.this.getWidth(); - mListHeight = TabsListLayout.this.getHeight(); - } - - switch (e.getActionMasked()) { - case MotionEvent.ACTION_DOWN: { - // Check if we should set pressed state on the - // touched view after a standard delay. - triggerCheckForTap(); - - final float x = e.getRawX(); - final float y = e.getRawY(); - - // Find out which view is being touched - mSwipeView = findViewAt(x, y); - - if (mSwipeView != null) { - mSwipeStartX = e.getRawX(); - mSwipeStartY = e.getRawY(); - - mVelocityTracker = VelocityTracker.obtain(); - mVelocityTracker.addMovement(e); - } - - view.onTouchEvent(e); - return true; - } - - case MotionEvent.ACTION_UP: { - if (mSwipeView == null) - break; - - cancelCheckForTap(); - mSwipeView.setPressed(false); - - if (!mSwiping) { - TabsLayoutItemView item = (TabsLayoutItemView) mSwipeView; - Tabs.getInstance().selectTab(item.getTabId()); - autoHidePanel(); - - mVelocityTracker.recycle(); - mVelocityTracker = null; - break; - } - - mVelocityTracker.addMovement(e); - mVelocityTracker.computeCurrentVelocity(1000, mMaxFlingVelocity); - - float velocityX = Math.abs(mVelocityTracker.getXVelocity()); - float velocityY = Math.abs(mVelocityTracker.getYVelocity()); - - boolean dismiss = false; - boolean dismissDirection = false; - int dismissTranslation = 0; - - if (isVertical()) { - float deltaX = ViewHelper.getTranslationX(mSwipeView); - - if (Math.abs(deltaX) > mListWidth / 2) { - dismiss = true; - dismissDirection = (deltaX > 0); - } else if (mMinFlingVelocity <= velocityX && velocityX <= mMaxFlingVelocity - && velocityY < velocityX) { - dismiss = mSwiping && (deltaX * mVelocityTracker.getXVelocity() > 0); - dismissDirection = (mVelocityTracker.getXVelocity() > 0); - } - - dismissTranslation = (dismissDirection ? mListWidth : -mListWidth); - } else { - float deltaY = ViewHelper.getTranslationY(mSwipeView); - - if (Math.abs(deltaY) > mListHeight / 2) { - dismiss = true; - dismissDirection = (deltaY > 0); - } else if (mMinFlingVelocity <= velocityY && velocityY <= mMaxFlingVelocity - && velocityX < velocityY) { - dismiss = mSwiping && (deltaY * mVelocityTracker.getYVelocity() > 0); - dismissDirection = (mVelocityTracker.getYVelocity() > 0); - } - - dismissTranslation = (dismissDirection ? mListHeight : -mListHeight); - } - - if (dismiss) - animateClose(mSwipeView, dismissTranslation); - else - animateCancel(mSwipeView); - - mVelocityTracker.recycle(); - mVelocityTracker = null; - mSwipeView = null; - - mSwipeStartX = 0; - mSwipeStartY = 0; - mSwiping = false; - - break; - } - - case MotionEvent.ACTION_MOVE: { - if (mSwipeView == null || mVelocityTracker == null) - break; - - mVelocityTracker.addMovement(e); - - final boolean isVertical = isVertical(); - - float deltaX = e.getRawX() - mSwipeStartX; - float deltaY = e.getRawY() - mSwipeStartY; - float delta = (isVertical ? deltaX : deltaY); - - boolean isScrollingX = Math.abs(deltaX) > mSwipeThreshold; - boolean isScrollingY = Math.abs(deltaY) > mSwipeThreshold; - boolean isSwipingToClose = (isVertical ? isScrollingX : isScrollingY); - - // If we're actually swiping, make sure we don't - // set pressed state on the swiped view. - if (isScrollingX || isScrollingY) - cancelCheckForTap(); - - if (isSwipingToClose) { - mSwiping = true; - TabsListLayout.this.requestDisallowInterceptTouchEvent(true); - - ((TabsLayoutItemView) mSwipeView).setCloseVisible(false); - - // Stops listview from highlighting the touched item - // in the list when swiping. - MotionEvent cancelEvent = MotionEvent.obtain(e); - cancelEvent.setAction(MotionEvent.ACTION_CANCEL | - (e.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT)); - TabsListLayout.this.onTouchEvent(cancelEvent); - cancelEvent.recycle(); - } - - if (mSwiping) { - if (isVertical) - ViewHelper.setTranslationX(mSwipeView, delta); - else - ViewHelper.setTranslationY(mSwipeView, delta); - - ViewHelper.setAlpha(mSwipeView, Math.max(0.1f, Math.min(1f, - 1f - 2f * Math.abs(delta) / (isVertical ? mListWidth : mListHeight)))); - - return true; - } - - break; - } - } - - return false; - } - - private View findViewAt(float rawX, float rawY) { - Rect rect = new Rect(); - - int[] listViewCoords = new int[2]; - TabsListLayout.this.getLocationOnScreen(listViewCoords); - - int x = (int) rawX - listViewCoords[0]; - int y = (int) rawY - listViewCoords[1]; - - for (int i = 0; i < TabsListLayout.this.getChildCount(); i++) { - View child = TabsListLayout.this.getChildAt(i); - child.getHitRect(rect); - - if (rect.contains(x, y)) - return child; - } - - return null; - } - - private void triggerCheckForTap() { - if (mPendingCheckForTap == null) - mPendingCheckForTap = new CheckForTap(); - - TabsListLayout.this.postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout()); - } - - private void cancelCheckForTap() { - if (mPendingCheckForTap == null) - return; - - TabsListLayout.this.removeCallbacks(mPendingCheckForTap); - } - - private class CheckForTap implements Runnable { - @Override - public void run() { - if (!mSwiping && mSwipeView != null && mEnabled) - mSwipeView.setPressed(true); - } - } - } -}
--- a/mobile/android/base/tabs/TabsPanel.java +++ b/mobile/android/base/tabs/TabsPanel.java @@ -50,35 +50,26 @@ public class TabsPanel extends LinearLay NORMAL_TABS, PRIVATE_TABS, } public interface PanelView { void setTabsPanel(TabsPanel panel); void show(); void hide(); - boolean shouldExpand(); } public interface CloseAllPanelView extends PanelView { void closeAll(); } public interface TabsLayout extends CloseAllPanelView { void setEmptyView(View view); } - public static View createTabsLayout(final Context context, final AttributeSet attrs) { - if (HardwareUtils.isTablet()) { - return new TabsGridLayout(context, attrs); - } else { - return new TabsListLayout(context, attrs); - } - } - public interface TabsLayoutChangeListener { void onTabsLayoutChange(int width, int height); } private final Context mContext; private final GeckoApp mActivity; private final LightweightTheme mTheme; private RelativeLayout mHeader; @@ -427,20 +418,16 @@ public class TabsPanel extends LinearLay mActivity.autoHideTabs(); } @Override public boolean isShown() { return mVisible; } - public Panel getCurrentPanel() { - 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 {