diff options
22 files changed, 420 insertions, 283 deletions
diff --git a/res/drawable-hdpi/active_page.png b/res/drawable-hdpi/active_page.png Binary files differnew file mode 100644 index 000000000..ce2d5b169 --- /dev/null +++ b/res/drawable-hdpi/active_page.png diff --git a/res/drawable-hdpi/inactive_page.png b/res/drawable-hdpi/inactive_page.png Binary files differnew file mode 100644 index 000000000..2186f519a --- /dev/null +++ b/res/drawable-hdpi/inactive_page.png diff --git a/res/drawable-mdpi/active_page.png b/res/drawable-mdpi/active_page.png Binary files differnew file mode 100644 index 000000000..9e23eccb0 --- /dev/null +++ b/res/drawable-mdpi/active_page.png diff --git a/res/drawable-mdpi/inactive_page.png b/res/drawable-mdpi/inactive_page.png Binary files differnew file mode 100644 index 000000000..9468a62ed --- /dev/null +++ b/res/drawable-mdpi/inactive_page.png diff --git a/res/drawable-xhdpi/active_page.png b/res/drawable-xhdpi/active_page.png Binary files differnew file mode 100644 index 000000000..c43e67c40 --- /dev/null +++ b/res/drawable-xhdpi/active_page.png diff --git a/res/drawable-xhdpi/inactive_page.png b/res/drawable-xhdpi/inactive_page.png Binary files differnew file mode 100644 index 000000000..ae3f9885b --- /dev/null +++ b/res/drawable-xhdpi/inactive_page.png diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml index 6dfbf21a5..8ee1413ee 100644 --- a/res/layout-land/launcher.xml +++ b/res/layout-land/launcher.xml @@ -45,9 +45,7 @@ launcher:cellCountY="@integer/cell_count_y" launcher:pageSpacing="@dimen/workspace_page_spacing" launcher:scrollIndicatorPaddingLeft="@dimen/qsb_bar_height" - launcher:scrollIndicatorPaddingRight="@dimen/button_bar_height"> - - </com.android.launcher3.Workspace> + launcher:scrollIndicatorPaddingRight="@dimen/button_bar_height" /> <include android:id="@+id/qsb_divider" @@ -57,21 +55,6 @@ android:layout_marginStart="@dimen/qsb_bar_height" android:layout_gravity="start" /> - <include - android:id="@+id/dock_divider" - layout="@layout/workspace_divider" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_marginEnd="@dimen/button_bar_height" - android:layout_gravity="end" /> - - <include - android:id="@+id/paged_view_indicator" - layout="@layout/scroll_indicator" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="bottom" /> - <include layout="@layout/hotseat" android:id="@+id/hotseat" android:layout_width="@dimen/button_bar_height_plus_padding" diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml index 30eba1c7d..0fee045fc 100644 --- a/res/layout-port/launcher.xml +++ b/res/layout-port/launcher.xml @@ -33,20 +33,12 @@ <!-- Keep these behind the workspace so that they are not visible when we go into AllApps --> <include - android:id="@+id/dock_divider" - layout="@layout/workspace_divider" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/button_bar_height" - android:layout_gravity="bottom" /> - - <include - android:id="@+id/paged_view_indicator" - layout="@layout/scroll_indicator" + android:id="@+id/page_indicator" + layout="@layout/page_indicator" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="bottom" - android:layout_marginBottom="@dimen/button_bar_height" /> + android:layout_gravity="bottom|center_horizontal" + android:layout_marginBottom="@dimen/button_bar_height_plus_padding" /> <!-- The workspace contains 5 screens of cells --> <com.android.launcher3.Workspace @@ -62,6 +54,7 @@ launcher:cellCountX="@integer/cell_count_x" launcher:cellCountY="@integer/cell_count_y" launcher:pageSpacing="@dimen/workspace_page_spacing" + launcher:pageIndicator="@id/page_indicator" launcher:scrollIndicatorPaddingLeft="@dimen/workspace_divider_padding_left" launcher:scrollIndicatorPaddingRight="@dimen/workspace_divider_padding_right"> </com.android.launcher3.Workspace> diff --git a/res/layout-sw600dp-land/launcher.xml b/res/layout-sw600dp-land/launcher.xml new file mode 100644 index 000000000..8e45028b8 --- /dev/null +++ b/res/layout-sw600dp-land/launcher.xml @@ -0,0 +1,108 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2007 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- Full screen view projects under the status bar and contains the background --> +<FrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" + + android:id="@+id/launcher" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@drawable/workspace_bg"> + + <com.android.launcher3.DragLayer + android:id="@+id/drag_layer" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:fitsSystemWindows="true"> + + <include + android:id="@+id/page_indicator" + layout="@layout/page_indicator" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="bottom|center_horizontal" /> + + <!-- The workspace contains 5 screens of cells --> + <com.android.launcher3.Workspace + android:id="@+id/workspace" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_gravity="center" + android:paddingStart="@dimen/workspace_left_padding" + android:paddingEnd="@dimen/workspace_right_padding" + android:paddingTop="@dimen/workspace_top_padding" + android:paddingBottom="@dimen/workspace_bottom_padding" + launcher:defaultScreen="@integer/config_workspaceDefaultScreen" + launcher:cellCountX="@integer/cell_count_x" + launcher:cellCountY="@integer/cell_count_y" + launcher:pageSpacing="@dimen/workspace_page_spacing" + launcher:pageIndicator="@id/page_indicator" + launcher:scrollIndicatorPaddingLeft="@dimen/qsb_bar_height" + launcher:scrollIndicatorPaddingRight="@dimen/button_bar_height" /> + + <include + android:id="@+id/qsb_divider" + layout="@layout/workspace_divider" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_marginStart="@dimen/qsb_bar_height" + android:layout_gravity="start" /> + + <include layout="@layout/hotseat" + android:id="@+id/hotseat" + android:layout_width="@dimen/button_bar_height_plus_padding" + android:layout_height="match_parent" + android:layout_gravity="end" /> + + <include + android:id="@+id/qsb_bar" + layout="@layout/qsb_bar" /> + + <!-- The Workspace cling must appear under the AppsCustomizePagedView below to ensure + that it is still visible during the transition to AllApps and doesn't overlay on + top of that view. --> + <include layout="@layout/workspace_cling" + android:id="@+id/workspace_cling" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:visibility="gone" /> + + <include layout="@layout/folder_cling" + android:id="@+id/folder_cling" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:visibility="gone" /> + + <com.android.launcher3.DrawableStateProxyView + android:id="@+id/voice_button_proxy" + android:layout_width="@dimen/qsb_bar_height" + android:layout_height="@dimen/app_icon_size" + android:layout_gravity="top|start" + android:layout_marginTop="64dp" + android:clickable="true" + android:onClick="onClickVoiceButton" + android:importantForAccessibility="no" + launcher:sourceViewId="@+id/voice_button" /> + + <include layout="@layout/apps_customize_pane" + android:id="@+id/apps_customize_pane" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:visibility="invisible" /> + </com.android.launcher3.DragLayer> +</FrameLayout> diff --git a/res/layout-sw720dp/launcher.xml b/res/layout-sw720dp/launcher.xml index dff3b2641..852d1ec21 100644 --- a/res/layout-sw720dp/launcher.xml +++ b/res/layout-sw720dp/launcher.xml @@ -33,19 +33,11 @@ <!-- Keep these behind the workspace so that they are not visible when we go into AllApps --> <include - android:id="@+id/dock_divider" - layout="@layout/workspace_divider" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/button_bar_height_plus_padding" - android:layout_gravity="bottom|center_horizontal" /> - - <include - android:id="@+id/paged_view_indicator" - layout="@layout/scroll_indicator" + android:id="@+id/page_indicator" + layout="@layout/page_indicator" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="bottom" + android:layout_gravity="bottom|center_horizontal" android:layout_marginBottom="@dimen/button_bar_height_plus_padding" /> <!-- The workspace contains 5 screens of cells --> @@ -62,6 +54,7 @@ launcher:cellCountX="@integer/cell_count_x" launcher:cellCountY="@integer/cell_count_y" launcher:pageSpacing="@dimen/workspace_page_spacing" + launcher:pageIndicator="@id/page_indicator" launcher:scrollIndicatorPaddingLeft="@dimen/workspace_divider_padding_left" launcher:scrollIndicatorPaddingRight="@dimen/workspace_divider_padding_right"> </com.android.launcher3.Workspace> diff --git a/res/layout/apps_customize_pane.xml b/res/layout/apps_customize_pane.xml index 7efe48638..c64b7cead 100644 --- a/res/layout/apps_customize_pane.xml +++ b/res/layout/apps_customize_pane.xml @@ -55,6 +55,7 @@ android:id="@+id/apps_customize_pane_content" android:layout_width="match_parent" android:layout_height="match_parent" + android:layout_marginBottom="@dimen/apps_customize_page_indicator_height" android:layout_gravity="center" launcher:maxAppCellCountX="@integer/apps_customize_maxCellCountX" launcher:maxAppCellCountY="@integer/apps_customize_maxCellCountY" @@ -70,20 +71,21 @@ launcher:widgetCountY="@integer/apps_customize_widget_cell_count_y" launcher:clingFocusedX="@integer/apps_customize_cling_focused_x" launcher:clingFocusedY="@integer/apps_customize_cling_focused_y" - launcher:maxGap="@dimen/workspace_max_gap" /> + launcher:maxGap="@dimen/workspace_max_gap" + launcher:pageIndicator="@+id/page_indicator" /> <FrameLayout android:id="@+id/animation_buffer" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FF000000" android:visibility="gone" /> - <include - android:id="@+id/paged_view_indicator" - layout="@layout/scroll_indicator" + android:id="@+id/page_indicator" + layout="@layout/page_indicator" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="bottom" /> + android:layout_gravity="bottom|center_horizontal" + android:layout_marginBottom="@dimen/apps_customize_page_indicator_margin" /> </FrameLayout> </LinearLayout> diff --git a/res/layout/page_indicator.xml b/res/layout/page_indicator.xml new file mode 100644 index 000000000..8aae752c5 --- /dev/null +++ b/res/layout/page_indicator.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<com.android.launcher3.PageIndicator + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" + android:animateLayoutChanges="true"> +</com.android.launcher3.PageIndicator> diff --git a/res/layout/page_indicator_marker.xml b/res/layout/page_indicator_marker.xml new file mode 100644 index 000000000..0260e7e4e --- /dev/null +++ b/res/layout/page_indicator_marker.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<com.android.launcher3.PageIndicatorMarker + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" + android:layout_width="wrap_content" + android:layout_height="wrap_content"> + <ImageView + android:id="@+id/inactive" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:src="@drawable/inactive_page" + /> + <ImageView + android:id="@+id/active" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:src="@drawable/active_page" + android:alpha="0" + /> +</com.android.launcher3.PageIndicatorMarker> diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 0c37e3ce9..154508379 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -97,6 +97,8 @@ <attr name="pageLayoutPaddingRight" format="dimension" /> <!-- The space between adjacent pages of the PagedView. --> <attr name="pageSpacing" format="dimension" /> + <!-- The page indicator for this workspace --> + <attr name="pageIndicator" format="reference" /> <!-- The padding for the scroll indicator area --> <attr name="scrollIndicatorPaddingLeft" format="dimension" /> <attr name="scrollIndicatorPaddingRight" format="dimension" /> diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 3fe53d274..2bfb31cc7 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -77,6 +77,10 @@ <dimen name="apps_customize_widget_cell_width_gap">10dp</dimen> <dimen name="apps_customize_widget_cell_height_gap">8dp</dimen> + <!-- The AppsCustomize page indicator --> + <dimen name="apps_customize_page_indicator_height">12dp</dimen> + <dimen name="apps_customize_page_indicator_margin">4dp</dimen> + <!-- height of the bottom row of controls --> <dimen name="button_bar_height">62dip</dimen> <!-- Because portal animations go beyond the bounds of an icon, we need diff --git a/src/com/android/launcher3/AppsCustomizeTabHost.java b/src/com/android/launcher3/AppsCustomizeTabHost.java index 51d2fba17..9868e8ba5 100644 --- a/src/com/android/launcher3/AppsCustomizeTabHost.java +++ b/src/com/android/launcher3/AppsCustomizeTabHost.java @@ -178,13 +178,9 @@ public class AppsCustomizeTabHost extends TabHost implements LauncherTransitiona } private void onTabChangedStart() { - mAppsCustomizePane.hideScrollingIndicator(false); } private void reloadCurrentPage() { - if (!LauncherAppState.getInstance().isScreenLarge()) { - mAppsCustomizePane.flashScrollingIndicator(true); - } mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage()); mAppsCustomizePane.requestFocus(); } @@ -370,9 +366,6 @@ public class AppsCustomizeTabHost extends TabHost implements LauncherTransitiona if (toWorkspace) { // Going from All Apps -> Workspace setVisibilityOfSiblingsWithLowerZOrder(VISIBLE); - // Stop the scrolling indicator - we don't want All Apps to be invalidating itself - // during the transition, especially since it has a hardware layer set on it - mAppsCustomizePane.cancelScrollingIndicatorAnimations(); } else { // Going from Workspace -> All Apps mContent.setVisibility(VISIBLE); @@ -380,10 +373,6 @@ public class AppsCustomizeTabHost extends TabHost implements LauncherTransitiona // Make sure the current page is loaded (we start loading the side pages after the // transition to prevent slowing down the animation) mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage(), true); - - if (!LauncherAppState.getInstance().isScreenLarge()) { - mAppsCustomizePane.showScrollingIndicator(true); - } } if (mResetAfterTransition) { @@ -421,10 +410,6 @@ public class AppsCustomizeTabHost extends TabHost implements LauncherTransitiona // prevent slowing down the animation) mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage()); - if (!LauncherAppState.getInstance().isScreenLarge()) { - mAppsCustomizePane.hideScrollingIndicator(false); - } - // Going from Workspace -> All Apps // NOTE: We should do this at the end since we check visibility state in some of the // cling initialization/dismiss code above. diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index d1284d85b..d46deb2cb 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -203,7 +203,6 @@ public class Launcher extends Activity private Workspace mWorkspace; private View mQsbDivider; - private View mDockDivider; private View mLauncherView; private DragLayer mDragLayer; private DragController mDragController; @@ -982,7 +981,6 @@ public class Launcher extends Activity mDragLayer = (DragLayer) findViewById(R.id.drag_layer); mWorkspace = (Workspace) mDragLayer.findViewById(R.id.workspace); mQsbDivider = findViewById(R.id.qsb_divider); - mDockDivider = findViewById(R.id.dock_divider); mLauncherView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); mWorkspaceBackgroundDrawable = getResources().getDrawable(R.drawable.workspace_bg); @@ -2666,8 +2664,6 @@ public class Launcher extends Activity if (mWorkspace != null && !springLoaded && !LauncherAppState.getInstance().isScreenLarge()) { - // Hide the workspace scrollbar - mWorkspace.hideScrollingIndicator(true); hideDockDivider(); } if (!animationCancelled) { @@ -2736,8 +2732,6 @@ public class Launcher extends Activity toView.bringToFront(); if (!springLoaded && !LauncherAppState.getInstance().isScreenLarge()) { - // Hide the workspace scrollbar - mWorkspace.hideScrollingIndicator(true); hideDockDivider(); // Hide the search bar @@ -2825,9 +2819,6 @@ public class Launcher extends Activity fromView.setVisibility(View.GONE); dispatchOnLauncherTransitionEnd(fromView, animated, true); dispatchOnLauncherTransitionEnd(toView, animated, true); - if (mWorkspace != null) { - mWorkspace.hideScrollingIndicator(false); - } if (onCompleteRunnable != null) { onCompleteRunnable.run(); } @@ -2851,7 +2842,6 @@ public class Launcher extends Activity dispatchOnLauncherTransitionPrepare(toView, animated, true); dispatchOnLauncherTransitionStart(toView, animated, true); dispatchOnLauncherTransitionEnd(toView, animated, true); - mWorkspace.hideScrollingIndicator(false); } } @@ -2905,8 +2895,6 @@ public class Launcher extends Activity } } - mWorkspace.flashScrollingIndicator(animated); - // Change the state *after* we've called all the transition code mState = State.WORKSPACE; @@ -2984,26 +2972,22 @@ public class Launcher extends Activity } void hideDockDivider() { - if (mQsbDivider != null && mDockDivider != null) { + if (mQsbDivider != null) { mQsbDivider.setVisibility(View.INVISIBLE); - mDockDivider.setVisibility(View.INVISIBLE); } } void showDockDivider(boolean animated) { - if (mQsbDivider != null && mDockDivider != null) { + if (mQsbDivider != null) { mQsbDivider.setVisibility(View.VISIBLE); - mDockDivider.setVisibility(View.VISIBLE); if (mDividerAnimator != null) { mDividerAnimator.cancel(); mQsbDivider.setAlpha(1f); - mDockDivider.setAlpha(1f); mDividerAnimator = null; } if (animated) { mDividerAnimator = LauncherAnimUtils.createAnimatorSet(); - mDividerAnimator.playTogether(LauncherAnimUtils.ofFloat(mQsbDivider, "alpha", 1f), - LauncherAnimUtils.ofFloat(mDockDivider, "alpha", 1f)); + mDividerAnimator.playTogether(LauncherAnimUtils.ofFloat(mQsbDivider, "alpha", 1f)); int duration = 0; if (mSearchDropTargetBar != null) { duration = mSearchDropTargetBar.getTransitionInDuration(); diff --git a/src/com/android/launcher3/PageIndicator.java b/src/com/android/launcher3/PageIndicator.java new file mode 100644 index 000000000..ecaa8f544 --- /dev/null +++ b/src/com/android/launcher3/PageIndicator.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.LayoutTransition; +import android.content.ComponentName; +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import com.android.launcher3.R; + +import java.util.ArrayList; + +public class PageIndicator extends LinearLayout { + @SuppressWarnings("unused") + private static final String TAG = "PageIndicator"; + + private LayoutInflater mLayoutInflater; + + public PageIndicator(Context context) { + this(context, null); + } + + public PageIndicator(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public PageIndicator(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + mLayoutInflater = LayoutInflater.from(context); + + LayoutTransition transition = getLayoutTransition(); + transition.setDuration(250); + } + + void addMarker(int index) { + index = Math.max(0, Math.min(index, getChildCount())); + View marker = mLayoutInflater.inflate(R.layout.page_indicator_marker, this, false); + addView(marker, index); + } + void addMarkers(int count) { + for (int i = 0; i < count; ++i) { + addMarker(Integer.MAX_VALUE); + } + } + + void removeMarker(int index) { + if (getChildCount() > 0) { + index = Math.max(0, Math.min(index, getChildCount() - 1)); + removeViewAt(index); + } + } + void removeAllMarkers() { + while (getChildCount() > 0) { + removeMarker(Integer.MAX_VALUE); + } + } + + void setActiveMarker(int index) { + for (int i = 0; i < getChildCount(); ++i) { + PageIndicatorMarker marker = (PageIndicatorMarker) getChildAt(i); + if (index == i) { + marker.activate(); + } else { + marker.inactivate(); + } + } + } +} diff --git a/src/com/android/launcher3/PageIndicatorMarker.java b/src/com/android/launcher3/PageIndicatorMarker.java new file mode 100644 index 000000000..852ee518f --- /dev/null +++ b/src/com/android/launcher3/PageIndicatorMarker.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3; + +import android.animation.LayoutTransition; +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 com.android.launcher3.R; + +public class PageIndicatorMarker extends FrameLayout { + @SuppressWarnings("unused") + private static final String TAG = "PageIndicator"; + + private static final int MARKER_FADE_DURATION = 150; + + private View mActiveMarker; + private View mInactiveMarker; + + public PageIndicatorMarker(Context context) { + this(context, null); + } + + public PageIndicatorMarker(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public PageIndicatorMarker(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + protected void onFinishInflate() { + mActiveMarker = findViewById(R.id.active); + mInactiveMarker = findViewById(R.id.inactive); + } + + public void activate() { + mActiveMarker.animate().alpha(1f) + .setDuration(MARKER_FADE_DURATION).start(); + mInactiveMarker.animate().alpha(0f) + .setDuration(MARKER_FADE_DURATION).start(); + } + public void inactivate() { + mInactiveMarker.animate().alpha(1f) + .setDuration(MARKER_FADE_DURATION).start(); + mActiveMarker.animate().alpha(0f) + .setDuration(MARKER_FADE_DURATION).start(); + } +} diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java index 275195b71..81a842e35 100644 --- a/src/com/android/launcher3/PagedView.java +++ b/src/com/android/launcher3/PagedView.java @@ -192,18 +192,9 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc protected boolean mAllowLongPress = true; - // Scrolling indicator - private ValueAnimator mScrollIndicatorAnimator; - private View mScrollIndicator; - private int mScrollIndicatorPaddingLeft; - private int mScrollIndicatorPaddingRight; - private boolean mHasScrollIndicator = true; - private boolean mShouldShowScrollIndicator = false; - private boolean mShouldShowScrollIndicatorImmediately = false; - protected static final int sScrollIndicatorFadeInDuration = 150; - protected static final int sScrollIndicatorFadeOutDuration = 650; - protected static final int sScrollIndicatorFlashDuration = 650; - private boolean mScrollingPaused = false; + // Page Indicator + private int mPageIndicatorViewId; + private PageIndicator mPageIndicator; // The viewport whether the pages are to be contained (the actual view may be larger than the // viewport) @@ -296,10 +287,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc R.styleable.PagedView_pageLayoutWidthGap, 0); mPageLayoutHeightGap = a.getDimensionPixelSize( R.styleable.PagedView_pageLayoutHeightGap, 0); - mScrollIndicatorPaddingLeft = - a.getDimensionPixelSize(R.styleable.PagedView_scrollIndicatorPaddingLeft, 0); - mScrollIndicatorPaddingRight = - a.getDimensionPixelSize(R.styleable.PagedView_scrollIndicatorPaddingRight, 0); + mPageIndicatorViewId = a.getResourceId(R.styleable.PagedView_pageIndicator, -1); a.recycle(); setHapticFeedbackEnabled(false); @@ -332,6 +320,21 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc setOnHierarchyChangeListener(this); } + protected void onAttachedToWindow() { + // Hook up the page indicator + ViewGroup parent = (ViewGroup) getParent(); + if (mPageIndicator == null && mPageIndicatorViewId > -1) { + mPageIndicator = (PageIndicator) parent.findViewById(mPageIndicatorViewId); + mPageIndicator.removeAllMarkers(); + mPageIndicator.addMarkers(getChildCount()); + } + } + + protected void onDetachedFromWindow() { + // Unhook the page indicator + mPageIndicator = null; + } + void setDeleteDropTarget(View v) { mDeleteDropTarget = v; } @@ -473,8 +476,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc */ void pauseScrolling() { mScroller.forceFinished(true); - cancelScrollingIndicatorAnimations(); - mScrollingPaused = true; } /** @@ -482,7 +483,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc * @see #pauseScrolling() */ void resumeScrolling() { - mScrollingPaused = false; } /** * Sets the current page. @@ -499,8 +499,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc mForceScreenScrolled = true; mCurrentPage = Math.max(0, Math.min(currentPage, getPageCount() - 1)); - updateCurrentPageScroll(); - updateScrollingIndicator(); notifyPageSwitchListener(); invalidate(); } @@ -509,6 +507,11 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc if (mPageSwitchListener != null) { mPageSwitchListener.onPageSwitch(getPageAt(mCurrentPage), mCurrentPage); } + + // Update the page indicator (when we aren't reordering) + if (mPageIndicator != null && !isReordering(false)) { + mPageIndicator.setActiveMarker(getNextPage()); + } } protected void pageBeginMoving() { if (!mIsPageMoving) { @@ -750,8 +753,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc } } - updateScrollingIndicatorPosition(); - if (childCount > 0) { final int index = isLayoutRtl() ? 0 : childCount - 1; mMaxScrollX = getChildOffset(index) - getRelativeChildOffset(index); @@ -814,9 +815,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc } protected void screenScrolled(int screenCenter) { - if (isScrollingIndicatorEnabled()) { - updateScrollingIndicator(); - } boolean isInOverscroll = mOverScrollX < 0 || mOverScrollX > mMaxScrollX; if (mFadeInAdjacentScreens && !isInOverscroll) { @@ -834,6 +832,12 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc @Override public void onChildViewAdded(View parent, View child) { + // Update the page indicator, we don't update the page indicator as we + // add/remove pages + if (mPageIndicator != null && !isReordering(false)) { + mPageIndicator.addMarker(indexOfChild(child)); + } + // This ensures that when children are added, they get the correct transforms / alphas // in accordance with any scroll effects. mForceScreenScrolled = true; @@ -849,6 +853,46 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc invalidateCachedOffsets(); } + private void removeMarkerForView(int index) { + // Update the page indicator, we don't update the page indicator as we + // add/remove pages + if (mPageIndicator != null && !isReordering(false)) { + mPageIndicator.removeMarker(index); + } + } + + @Override + public void removeView(View v) { + // XXX: We should find a better way to hook into this before the view + // gets removed form its parent... + removeMarkerForView(indexOfChild(v)); + super.removeView(v); + } + @Override + public void removeViewInLayout(View v) { + // XXX: We should find a better way to hook into this before the view + // gets removed form its parent... + removeMarkerForView(indexOfChild(v)); + super.removeViewInLayout(v); + } + @Override + public void removeViewAt(int index) { + // XXX: We should find a better way to hook into this before the view + // gets removed form its parent... + removeViewAt(index); + super.removeViewAt(index); + } + @Override + public void removeAllViewsInLayout() { + // Update the page indicator, we don't update the page indicator as we + // add/remove pages + if (mPageIndicator != null) { + mPageIndicator.removeAllMarkers(); + } + + super.removeAllViewsInLayout(); + } + protected void invalidateCachedOffsets() { int count = getChildCount(); if (count == 0) { @@ -1605,6 +1649,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc addView(mDragView, pageUnderPointIndex); onAddView(mDragView, pageUnderPointIndex); mSidePageHoverIndex = -1; + mPageIndicator.setActiveMarker(getNextPage()); } }; postDelayed(mSidePageHoverRunnable, REORDERING_SIDE_PAGE_HOVER_TIMEOUT); @@ -2172,153 +2217,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc } } - protected View getScrollingIndicator() { - // We use mHasScrollIndicator to prevent future lookups if there is no sibling indicator - // found - if (mHasScrollIndicator && mScrollIndicator == null) { - ViewGroup parent = (ViewGroup) getParent(); - if (parent != null) { - mScrollIndicator = (View) (parent.findViewById(R.id.paged_view_indicator)); - mHasScrollIndicator = mScrollIndicator != null; - if (mHasScrollIndicator) { - mScrollIndicator.setVisibility(View.VISIBLE); - } - } - } - return mScrollIndicator; - } - - protected boolean isScrollingIndicatorEnabled() { - return true; - } - - Runnable hideScrollingIndicatorRunnable = new Runnable() { - @Override - public void run() { - hideScrollingIndicator(false); - } - }; - - protected void flashScrollingIndicator(boolean animated) { - removeCallbacks(hideScrollingIndicatorRunnable); - showScrollingIndicator(!animated); - postDelayed(hideScrollingIndicatorRunnable, sScrollIndicatorFlashDuration); - } - - protected void showScrollingIndicator(boolean immediately) { - mShouldShowScrollIndicator = true; - mShouldShowScrollIndicatorImmediately = true; - if (getChildCount() <= 1) return; - if (!isScrollingIndicatorEnabled()) return; - - mShouldShowScrollIndicator = false; - getScrollingIndicator(); - if (mScrollIndicator != null) { - // Fade the indicator in - updateScrollingIndicatorPosition(); - mScrollIndicator.setVisibility(View.VISIBLE); - cancelScrollingIndicatorAnimations(); - if (immediately) { - mScrollIndicator.setAlpha(1f); - } else { - mScrollIndicatorAnimator = ObjectAnimator.ofFloat(mScrollIndicator, "alpha", 1f); - mScrollIndicatorAnimator.setDuration(sScrollIndicatorFadeInDuration); - mScrollIndicatorAnimator.start(); - } - } - } - - protected void cancelScrollingIndicatorAnimations() { - if (mScrollIndicatorAnimator != null) { - mScrollIndicatorAnimator.cancel(); - } - } - - protected void hideScrollingIndicator(boolean immediately) { - if (getChildCount() <= 1) return; - if (!isScrollingIndicatorEnabled()) return; - - getScrollingIndicator(); - if (mScrollIndicator != null) { - // Fade the indicator out - updateScrollingIndicatorPosition(); - cancelScrollingIndicatorAnimations(); - if (immediately) { - mScrollIndicator.setVisibility(View.INVISIBLE); - mScrollIndicator.setAlpha(0f); - } else { - mScrollIndicatorAnimator = ObjectAnimator.ofFloat(mScrollIndicator, "alpha", 0f); - mScrollIndicatorAnimator.setDuration(sScrollIndicatorFadeOutDuration); - mScrollIndicatorAnimator.addListener(new AnimatorListenerAdapter() { - private boolean cancelled = false; - @Override - public void onAnimationCancel(android.animation.Animator animation) { - cancelled = true; - } - @Override - public void onAnimationEnd(Animator animation) { - if (!cancelled) { - mScrollIndicator.setVisibility(View.INVISIBLE); - } - } - }); - mScrollIndicatorAnimator.start(); - } - } - } - - /** - * To be overridden by subclasses to determine whether the scroll indicator should stretch to - * fill its space on the track or not. - */ - protected boolean hasElasticScrollIndicator() { - return true; - } - - private void updateScrollingIndicator() { - if (getChildCount() <= 1) return; - if (!isScrollingIndicatorEnabled()) return; - - getScrollingIndicator(); - if (mScrollIndicator != null) { - updateScrollingIndicatorPosition(); - } - if (mShouldShowScrollIndicator) { - showScrollingIndicator(mShouldShowScrollIndicatorImmediately); - } - } - - private void updateScrollingIndicatorPosition() { - final boolean isRtl = isLayoutRtl(); - if (!isScrollingIndicatorEnabled()) return; - if (mScrollIndicator == null) return; - int numPages = getChildCount(); - int pageWidth = getViewportWidth(); - int lastChildIndex = Math.max(0, getChildCount() - 1); - int maxScrollX = getChildOffset(lastChildIndex) - getRelativeChildOffset(lastChildIndex); - int trackWidth = pageWidth - mScrollIndicatorPaddingLeft - mScrollIndicatorPaddingRight; - int indicatorWidth = mScrollIndicator.getMeasuredWidth() - - mScrollIndicator.getPaddingLeft() - mScrollIndicator.getPaddingRight(); - - float scrollPos = isRtl ? mMaxScrollX - getScrollX() : getScrollX(); - float offset = Math.max(0f, Math.min(1f, (float) scrollPos / mMaxScrollX)); - if (isRtl) { - offset = 1f - offset; - } - int indicatorSpace = trackWidth / numPages; - int indicatorPos = (int) (offset * (trackWidth - indicatorSpace)) + mScrollIndicatorPaddingLeft; - if (hasElasticScrollIndicator()) { - if (mScrollIndicator.getMeasuredWidth() != indicatorSpace) { - mScrollIndicator.getLayoutParams().width = indicatorSpace; - mScrollIndicator.requestLayout(); - } - } else { - int indicatorCenterOffset = indicatorSpace / 2 - indicatorWidth / 2; - indicatorPos += indicatorCenterOffset; - } - mScrollIndicator.setTranslationX(indicatorPos); - } - // Animate the drag view back to the original position void animateDragViewToOriginalPosition() { if (mDragView != null) { diff --git a/src/com/android/launcher3/PagedViewWithDraggableItems.java b/src/com/android/launcher3/PagedViewWithDraggableItems.java index 8f10ecfa5..2a29c33f3 100644 --- a/src/com/android/launcher3/PagedViewWithDraggableItems.java +++ b/src/com/android/launcher3/PagedViewWithDraggableItems.java @@ -167,12 +167,4 @@ public abstract class PagedViewWithDraggableItems extends PagedView cancelDragging(); super.onDetachedFromWindow(); } - - /** Show the scrolling indicators when we move the page */ - protected void onPageBeginMoving() { - showScrollingIndicator(false); - } - protected void onPageEndMoving() { - hideScrollingIndicator(false); - } } diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index d9582adfb..47d8ec8c7 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -329,6 +329,7 @@ public class Workspace extends SmoothPagedView cellCountX = a.getInt(R.styleable.Workspace_cellCountX, cellCountX); cellCountY = a.getInt(R.styleable.Workspace_cellCountY, cellCountY); mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1); + a.recycle(); setOnHierarchyChangeListener(this); @@ -870,9 +871,6 @@ public class Workspace extends SmoothPagedView ((CellLayout) getPageAt(i)).setShortcutAndWidgetAlpha(1f); } } - - // Show the scroll indicator as you pan the page - showScrollingIndicator(false); } protected void onPageEndMoving() { @@ -896,11 +894,6 @@ public class Workspace extends SmoothPagedView if (LauncherAppState.getInstance().isScreenLarge()) { hideOutlines(); } - - // Hide the scroll indicator as you pan the page - if (!mDragController.isDragging()) { - hideScrollingIndicator(false); - } } if (mDelayedResizeRunnable != null) { @@ -1853,7 +1846,6 @@ public class Workspace extends SmoothPagedView public void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace) { mIsSwitchingState = true; updateChildrenLayersEnabled(false); - cancelScrollingIndicatorAnimations(); } @Override @@ -2070,9 +2062,6 @@ public class Workspace extends SmoothPagedView mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(), DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect, scale); b.recycle(); - - // Show the scrolling indicator when you pick up an item - showScrollingIndicator(false); } void addApplicationShortcut(ShortcutInfo info, CellLayout target, long container, long screenId, @@ -2353,11 +2342,13 @@ public class Workspace extends SmoothPagedView // cell also contains a shortcut, then create a folder with the two shortcuts. if (!mInScrollArea && createUserFolderIfNecessary(cell, container, dropTargetLayout, mTargetCell, distance, false, d.dragView, null)) { + stripEmptyScreens(); return; } if (addToExistingFolderIfNecessary(cell, dropTargetLayout, mTargetCell, distance, d, false)) { + stripEmptyScreens(); return; } @@ -3463,9 +3454,6 @@ public class Workspace extends SmoothPagedView } mDragOutline = null; mDragInfo = null; - - // Hide the scrolling indicator after you pick up an item - hideScrollingIndicator(false); } void updateItemLocationsInDatabase(CellLayout cl) { @@ -4025,18 +4013,11 @@ public class Workspace extends SmoothPagedView } void setFadeForOverScroll(float fade) { - if (!isScrollingIndicatorEnabled()) return; - mOverscrollFade = fade; float reducedFade = 0.5f + 0.5f * (1 - fade); final ViewGroup parent = (ViewGroup) getParent(); final ImageView qsbDivider = (ImageView) (parent.findViewById(R.id.qsb_divider)); - final ImageView dockDivider = (ImageView) (parent.findViewById(R.id.dock_divider)); - final View scrollIndicator = getScrollingIndicator(); - cancelScrollingIndicatorAnimations(); if (qsbDivider != null) qsbDivider.setAlpha(reducedFade); - if (dockDivider != null) dockDivider.setAlpha(reducedFade); - scrollIndicator.setAlpha(1 - fade); } } |