diff options
17 files changed, 345 insertions, 85 deletions
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml index f711274fc..4576e4d06 100644 --- a/res/layout-port/launcher.xml +++ b/res/layout-port/launcher.xml @@ -57,12 +57,10 @@ <!-- Keep these behind the workspace so that they are not visible when we go into AllApps --> - <include + <com.android.launcher3.pageindicators.PageIndicatorLine android:id="@+id/page_indicator" - layout="@layout/page_indicator" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal" /> + android:layout_width="match_parent" + android:layout_height="1dp" /> <include android:id="@+id/app_info_drop_target_bar" diff --git a/res/layout-sw720dp/launcher.xml b/res/layout-sw720dp/launcher.xml index 780d6454b..0f755d8e1 100644 --- a/res/layout-sw720dp/launcher.xml +++ b/res/layout-sw720dp/launcher.xml @@ -64,11 +64,10 @@ <!-- Keep these behind the workspace so that they are not visible when we go into AllApps --> - <include android:id="@+id/page_indicator" - layout="@layout/page_indicator" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal" /> + <com.android.launcher3.pageindicators.PageIndicatorLine + android:id="@+id/page_indicator" + android:layout_width="match_parent" + android:layout_height="1dp" /> <include layout="@layout/widgets_view" android:id="@+id/widgets_view" diff --git a/res/layout/page_indicator.xml b/res/layout/page_indicator.xml index 68fe3dd60..5655159e3 100644 --- a/res/layout/page_indicator.xml +++ b/res/layout/page_indicator.xml @@ -13,9 +13,9 @@ See the License for the specific language governing permissions and limitations under the License. --> -<com.android.launcher3.PageIndicator +<com.android.launcher3.pageindicators.PageIndicatorDots xmlns:android="http://schemas.android.com/apk/res/android" xmlns:launcher="http://schemas.android.com/apk/res-auto" android:animateLayoutChanges="true" launcher:windowSize="@integer/config_maxNumberOfPageIndicatorsToShow"> -</com.android.launcher3.PageIndicator> +</com.android.launcher3.pageindicators.PageIndicatorDots> diff --git a/res/layout/page_indicator_marker.xml b/res/layout/page_indicator_marker.xml index 564a95811..357a76186 100644 --- a/res/layout/page_indicator_marker.xml +++ b/res/layout/page_indicator_marker.xml @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. --> -<com.android.launcher3.PageIndicatorMarker +<com.android.launcher3.pageindicators.PageIndicatorDot xmlns:android="http://schemas.android.com/apk/res/android" xmlns:launcher="http://schemas.android.com/apk/res-auto" android:layout_width="12dp" @@ -36,4 +36,4 @@ android:scaleX="0.5" android:scaleY="0.5" /> -</com.android.launcher3.PageIndicatorMarker> +</com.android.launcher3.pageindicators.PageIndicatorDot> diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 6d8efaa34..2eb9b910f 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -32,7 +32,7 @@ </declare-styleable> <!-- Page Indicator specific attributes. --> - <declare-styleable name="PageIndicator"> + <declare-styleable name="PageIndicatorDots"> <attr name="windowSize" format="integer" /> </declare-styleable> diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 9ab56119f..8d11aaa96 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -537,7 +537,6 @@ public class DeviceProfile { lp = (FrameLayout.LayoutParams) pageIndicator.getLayoutParams(); lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; lp.width = LayoutParams.WRAP_CONTENT; - lp.height = LayoutParams.WRAP_CONTENT; lp.bottomMargin = hotseatBarHeightPx; pageIndicator.setLayoutParams(lp); } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 0a8e1e65f..e93068ed2 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -112,6 +112,8 @@ import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.logging.LoggerUtils; import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.model.WidgetsModel; +import com.android.launcher3.pageindicators.PageIndicator; +import com.android.launcher3.pageindicators.PageIndicatorLine; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.logging.FileLog; @@ -224,7 +226,7 @@ public class Launcher extends Activity @Thunk Workspace mWorkspace; private View mLauncherView; - private View mPageIndicators; + private PageIndicatorLine mPageIndicator; @Thunk DragLayer mDragLayer; private DragController mDragController; @@ -501,6 +503,7 @@ public class Launcher extends Activity if (mExtractedColors != null && Utilities.isNycOrAbove()) { mExtractedColors.load(this); mHotseat.updateColor(mExtractedColors, !mPaused); + mPageIndicator.updateColor(mExtractedColors); } } @@ -1327,7 +1330,7 @@ public class Launcher extends Activity mFocusHandler = (FocusIndicatorView) findViewById(R.id.focus_indicator); mDragLayer = (DragLayer) findViewById(R.id.drag_layer); mWorkspace = (Workspace) mDragLayer.findViewById(R.id.workspace); - mPageIndicators = mDragLayer.findViewById(R.id.page_indicator); + mPageIndicator = (PageIndicatorLine) mDragLayer.findViewById(R.id.page_indicator); mLauncherView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION @@ -4530,7 +4533,7 @@ public class Launcher extends Activity void showWorkspaceSearchAndHotseat() { if (mWorkspace != null) mWorkspace.setAlpha(1f); if (mHotseat != null) mHotseat.setAlpha(1f); - if (mPageIndicators != null) mPageIndicators.setAlpha(1f); + if (mPageIndicator != null) mPageIndicator.setAlpha(1f); if (mSearchDropTargetBar != null) mSearchDropTargetBar.animateToState( SearchDropTargetBar.State.SEARCH_BAR, 0); } @@ -4538,7 +4541,7 @@ public class Launcher extends Activity void hideWorkspaceSearchAndHotseat() { if (mWorkspace != null) mWorkspace.setAlpha(0f); if (mHotseat != null) mHotseat.setAlpha(0f); - if (mPageIndicators != null) mPageIndicators.setAlpha(0f); + if (mPageIndicator != null) mPageIndicator.setAlpha(0f); if (mSearchDropTargetBar != null) mSearchDropTargetBar.animateToState( SearchDropTargetBar.State.INVISIBLE, 0); } diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java index e1cb08220..02e894b7f 100644 --- a/src/com/android/launcher3/PagedView.java +++ b/src/com/android/launcher3/PagedView.java @@ -49,8 +49,11 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.Interpolator; + +import com.android.launcher3.pageindicators.PageIndicator; import com.android.launcher3.util.LauncherEdgeEffect; import com.android.launcher3.util.Thunk; + import java.util.ArrayList; /** @@ -254,8 +257,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc mPageIndicator = (PageIndicator) grandParent.findViewById(mPageIndicatorViewId); mPageIndicator.removeAllMarkers(true); - ArrayList<PageIndicator.PageMarkerResources> markers = - new ArrayList<PageIndicator.PageMarkerResources>(); + ArrayList<PageIndicator.PageMarkerResources> markers = new ArrayList<>(); for (int i = 0; i < getChildCount(); ++i) { markers.add(getPageIndicatorMarker(i)); } @@ -264,9 +266,9 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc OnClickListener listener = getPageIndicatorClickListener(); if (listener != null) { - mPageIndicator.setOnClickListener(listener); + mPageIndicator.getView().setOnClickListener(listener); } - mPageIndicator.setContentDescription(getPageIndicatorDescription()); + mPageIndicator.getView().setContentDescription(getPageIndicatorDescription()); } } @@ -355,7 +357,8 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc return mPageIndicator; } protected PageIndicator.PageMarkerResources getPageIndicatorMarker(int pageIndex) { - return new PageIndicator.PageMarkerResources(); + return new PageIndicator.PageMarkerResources(R.drawable.ic_pageindicator_current, + R.drawable.ic_pageindicator_default); } /** @@ -430,7 +433,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc Math.min(newPage, mTempVisiblePagesRange[1])); } // Ensure that it is clamped by the actual set of children in all cases - validatedPage = Utilities.boundInRange(validatedPage, 0, getPageCount() - 1); + validatedPage = Utilities.boundToRange(validatedPage, 0, getPageCount() - 1); return validatedPage; } @@ -475,7 +478,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc private void updatePageIndicator() { // Update the page indicator (when we aren't reordering) if (mPageIndicator != null) { - mPageIndicator.setContentDescription(getPageIndicatorDescription()); + mPageIndicator.getView().setContentDescription(getPageIndicatorDescription()); if (!isReordering(false)) { mPageIndicator.setActiveMarker(getNextPage()); } @@ -931,12 +934,16 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc } @Thunk void updateMaxScrollX() { + mMaxScrollX = computeMaxScrollX(); + } + + protected int computeMaxScrollX() { int childCount = getChildCount(); if (childCount > 0) { final int index = mIsRtl ? 0 : childCount - 1; - mMaxScrollX = getScrollForPage(index); + return getScrollForPage(index); } else { - mMaxScrollX = 0; + return 0; } } diff --git a/src/com/android/launcher3/PinchAnimationManager.java b/src/com/android/launcher3/PinchAnimationManager.java index c8c8fa4c8..477b92cc0 100644 --- a/src/com/android/launcher3/PinchAnimationManager.java +++ b/src/com/android/launcher3/PinchAnimationManager.java @@ -194,7 +194,7 @@ public class PinchAnimationManager { animateShowHideView(INDEX_HOTSEAT, mLauncher.getHotseat(), show); if (mWorkspace.getPageIndicator() != null) { // There aren't page indicators in landscape mode on phones, hence the null check. - animateShowHideView(INDEX_PAGE_INDICATOR, mWorkspace.getPageIndicator(), show); + animateShowHideView(INDEX_PAGE_INDICATOR, mWorkspace.getPageIndicator().getView(), show); } } diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index 53522fb83..e3b959b39 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -798,7 +798,14 @@ public final class Utilities { * If value is less than lowerBound, return lowerBound; else if value is greater than upperBound, * return upperBound; else return value unchanged. */ - public static int boundInRange(int value, int lowerBound, int upperBound) { + public static int boundToRange(int value, int lowerBound, int upperBound) { + return Math.max(lowerBound, Math.min(value, upperBound)); + } + + /** + * @see #boundToRange(int, int, int). + */ + public static float boundToRange(float value, float lowerBound, float upperBound) { return Math.max(lowerBound, Math.min(value, upperBound)); } diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 616c3560e..386e01634 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -73,6 +73,7 @@ import com.android.launcher3.dragndrop.SpringLoadedDragController; import com.android.launcher3.folder.Folder; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.logging.UserEventDispatcher; +import com.android.launcher3.pageindicators.PageIndicator; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.userevent.nano.LauncherLogProto.Target; import com.android.launcher3.util.LongArrayMap; @@ -1273,6 +1274,22 @@ public class Workspace extends PagedView } @Override + protected void onScrollChanged(int l, int t, int oldl, int oldt) { + super.onScrollChanged(l, t, oldl, oldt); + + // Update the page indicator progress. + boolean isTransitioning = mIsSwitchingState + || (getLayoutTransition() != null && getLayoutTransition().isRunning()); + if (mPageIndicator != null && !isTransitioning) { + showPageIndicatorAtCurrentScroll(); + } + } + + private void showPageIndicatorAtCurrentScroll() { + mPageIndicator.setProgress((float) getScrollX() / computeMaxScrollX()); + } + + @Override protected void overScroll(float amount) { boolean shouldOverScroll = (amount <= 0 && (!hasCustomContent() || mIsRtl)) || (amount >= 0 && (!hasCustomContent() || !mIsRtl)); @@ -1325,7 +1342,7 @@ public class Workspace extends PagedView // different effects based on device performance. On at least one relatively high-end // device I've tried, translating the launcher causes things to get quite laggy. setTranslationAndAlpha(mLauncher.getSearchDropTargetBar(), transX, alpha); - setTranslationAndAlpha(getPageIndicator(), transX, alpha); + setTranslationAndAlpha(getPageIndicator().getView(), transX, alpha); setTranslationAndAlpha(getChildAt(getCurrentPage()), transX, alpha); setTranslationAndAlpha(mLauncher.getHotseat(), transX, alpha); @@ -1538,7 +1555,7 @@ public class Workspace extends PagedView } if (getPageIndicator() != null) { - getPageIndicator().setTranslationX(translationX); + getPageIndicator().getView().setTranslationX(translationX); } if (mCustomContentCallbacks != null) { @@ -1587,8 +1604,10 @@ public class Workspace extends PagedView // attach to window OnClickListener listener = getPageIndicatorClickListener(); if (listener != null) { - getPageIndicator().setOnClickListener(listener); + getPageIndicator().getView().setOnClickListener(listener); } + + showPageIndicatorAtCurrentScroll(); } // Update wallpaper dimensions if they were changed since last onResume @@ -1739,8 +1758,8 @@ public class Workspace extends PagedView super.getVisiblePages(range); if (mForceDrawAdjacentPages) { // In overview mode, make sure that the two side pages are visible. - range[0] = Utilities.boundInRange(getCurrentPage() - 1, numCustomPages(), range[1]); - range[1] = Utilities.boundInRange(getCurrentPage() + 1, range[0], getPageCount() - 1); + range[0] = Utilities.boundToRange(getCurrentPage() - 1, numCustomPages(), range[1]); + range[1] = Utilities.boundToRange(getCurrentPage() + 1, range[0], getPageCount() - 1); } } @@ -2006,6 +2025,9 @@ public class Workspace extends PagedView updateChildrenLayersEnabled(false); showCustomContentIfNecessary(); mForceDrawAdjacentPages = false; + if (mState == State.NORMAL || mState == State.SPRING_LOADED) { + showPageIndicatorAtCurrentScroll(); + } } void updateCustomContentVisibility() { diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java index c0eb7eda3..60070a810 100644 --- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java +++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java @@ -288,7 +288,7 @@ public class WorkspaceStateTransitionAnimation { float finalBackgroundAlpha = (states.stateIsSpringLoaded || states.stateIsOverview) ? 1.0f : 0f; float finalHotseatAlpha = (states.stateIsNormal || states.stateIsSpringLoaded) ? 1f : 0f; - float finalPageIndicatorAlpha = states.stateIsNormal ? 1f : 0f; + float finalPageIndicatorAlpha = finalHotseatAlpha; float finalOverviewPanelAlpha = states.stateIsOverview ? 1f : 0f; float finalWorkspaceTranslationY = 0; @@ -357,7 +357,7 @@ public class WorkspaceStateTransitionAnimation { final ViewGroup overviewPanel = mLauncher.getOverviewPanel(); final View hotseat = mLauncher.getHotseat(); - final View pageIndicator = mWorkspace.getPageIndicator(); + final View pageIndicator = mWorkspace.getPageIndicator().getView(); if (animated) { LauncherViewPropertyAnimator scale = new LauncherViewPropertyAnimator(mWorkspace); scale.scaleX(mNewScale) diff --git a/src/com/android/launcher3/folder/FolderPagedView.java b/src/com/android/launcher3/folder/FolderPagedView.java index 1af148584..e1a143165 100644 --- a/src/com/android/launcher3/folder/FolderPagedView.java +++ b/src/com/android/launcher3/folder/FolderPagedView.java @@ -39,8 +39,8 @@ import com.android.launcher3.ItemInfo; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherModel; -import com.android.launcher3.PageIndicator; -import com.android.launcher3.PageIndicator.PageMarkerResources; +import com.android.launcher3.pageindicators.PageIndicatorDots; +import com.android.launcher3.pageindicators.PageIndicator.PageMarkerResources; import com.android.launcher3.PagedView; import com.android.launcher3.R; import com.android.launcher3.ShortcutAndWidgetContainer; @@ -103,7 +103,7 @@ public class FolderPagedView extends PagedView { private FocusIndicatorView mFocusIndicatorView; private PagedFolderKeyEventListener mKeyListener; - private PageIndicator mPageIndicator; + private PageIndicatorDots mPageIndicator; public FolderPagedView(Context context, AttributeSet attrs) { super(context, attrs); @@ -128,7 +128,7 @@ public class FolderPagedView extends PagedView { mFolder = folder; mFocusIndicatorView = (FocusIndicatorView) folder.findViewById(R.id.focus_indicator); mKeyListener = new PagedFolderKeyEventListener(folder); - mPageIndicator = (PageIndicator) folder.findViewById(R.id.folder_page_indicator); + mPageIndicator = (PageIndicatorDots) folder.findViewById(R.id.folder_page_indicator); } /** diff --git a/src/com/android/launcher3/pageindicators/PageIndicator.java b/src/com/android/launcher3/pageindicators/PageIndicator.java new file mode 100644 index 000000000..6348b123b --- /dev/null +++ b/src/com/android/launcher3/pageindicators/PageIndicator.java @@ -0,0 +1,31 @@ +package com.android.launcher3.pageindicators; + +import android.view.View; + +import java.util.ArrayList; + +public interface PageIndicator { + View getView(); + void setProgress(float progress); + + void removeAllMarkers(boolean allowAnimations); + void addMarkers(ArrayList<PageMarkerResources> markers, boolean allowAnimations); + void setActiveMarker(int activePage); + void addMarker(int pageIndex, PageMarkerResources pageIndicatorMarker, boolean allowAnimations); + void removeMarker(int pageIndex, boolean allowAnimations); + void updateMarker(int pageIndex, PageMarkerResources pageIndicatorMarker); + + /** + * Contains two resource ids for each page indicator marker (e.g. dots): + * one for when the page is active and one for when the page is inactive. + */ + class PageMarkerResources { + int activeId; + int inactiveId; + + public PageMarkerResources(int aId, int iaId) { + activeId = aId; + inactiveId = iaId; + } + } +} diff --git a/src/com/android/launcher3/PageIndicatorMarker.java b/src/com/android/launcher3/pageindicators/PageIndicatorDot.java index 7bf21dd90..5ed342695 100644 --- a/src/com/android/launcher3/PageIndicatorMarker.java +++ b/src/com/android/launcher3/pageindicators/PageIndicatorDot.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.launcher3; +package com.android.launcher3.pageindicators; import android.content.Context; import android.content.res.Resources; @@ -22,7 +22,9 @@ import android.util.AttributeSet; import android.widget.FrameLayout; import android.widget.ImageView; -public class PageIndicatorMarker extends FrameLayout { +import com.android.launcher3.R; + +public class PageIndicatorDot extends FrameLayout { @SuppressWarnings("unused") private static final String TAG = "PageIndicator"; @@ -32,15 +34,15 @@ public class PageIndicatorMarker extends FrameLayout { private ImageView mInactiveMarker; private boolean mIsActive = false; - public PageIndicatorMarker(Context context) { + public PageIndicatorDot(Context context) { this(context, null); } - public PageIndicatorMarker(Context context, AttributeSet attrs) { + public PageIndicatorDot(Context context, AttributeSet attrs) { this(context, attrs, 0); } - public PageIndicatorMarker(Context context, AttributeSet attrs, int defStyle) { + public PageIndicatorDot(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } diff --git a/src/com/android/launcher3/PageIndicator.java b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java index 8adbf8d01..a488f028a 100644 --- a/src/com/android/launcher3/PageIndicator.java +++ b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java @@ -14,19 +14,22 @@ * limitations under the License. */ -package com.android.launcher3; +package com.android.launcher3.pageindicators; import android.animation.LayoutTransition; import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.LayoutInflater; +import android.view.View; import android.view.ViewDebug; import android.widget.LinearLayout; +import com.android.launcher3.R; + import java.util.ArrayList; -public class PageIndicator extends LinearLayout { +public class PageIndicatorDots extends LinearLayout implements PageIndicator { @SuppressWarnings("unused") private static final String TAG = "PageIndicator"; // Want this to look good? Keep it odd @@ -36,38 +39,23 @@ public class PageIndicator extends LinearLayout { private int[] mWindowRange = new int[2]; private int mMaxWindowSize; - private ArrayList<PageIndicatorMarker> mMarkers = - new ArrayList<PageIndicatorMarker>(); + private ArrayList<PageIndicatorDot> mMarkers = new ArrayList<>(); @ViewDebug.ExportedProperty(category = "launcher") private int mActiveMarkerIndex; - public static class PageMarkerResources { - int activeId; - int inactiveId; - - public PageMarkerResources() { - activeId = R.drawable.ic_pageindicator_current; - inactiveId = R.drawable.ic_pageindicator_default; - } - public PageMarkerResources(int aId, int iaId) { - activeId = aId; - inactiveId = iaId; - } - } - - public PageIndicator(Context context) { + public PageIndicatorDots(Context context) { this(context, null); } - public PageIndicator(Context context, AttributeSet attrs) { + public PageIndicatorDots(Context context, AttributeSet attrs) { this(context, attrs, 0); } - public PageIndicator(Context context, AttributeSet attrs, int defStyle) { + public PageIndicatorDots(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); TypedArray a = context.obtainStyledAttributes(attrs, - R.styleable.PageIndicator, defStyle, 0); - mMaxWindowSize = a.getInteger(R.styleable.PageIndicator_windowSize, 15); + R.styleable.PageIndicatorDots, defStyle, 0); + mMaxWindowSize = a.getInteger(R.styleable.PageIndicatorDots_windowSize, 15); mWindowRange[0] = 0; mWindowRange[1] = 0; mLayoutInflater = LayoutInflater.from(context); @@ -94,7 +82,7 @@ public class PageIndicator extends LinearLayout { transition.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING); } - void offsetWindowCenterTo(int activeIndex, boolean allowAnimations) { + public void offsetWindowCenterTo(int activeIndex, boolean allowAnimations) { if (activeIndex < 0) { new Throwable().printStackTrace(); } @@ -116,7 +104,7 @@ public class PageIndicator extends LinearLayout { // Remove all the previous children that are no longer in the window for (int i = getChildCount() - 1; i >= 0; --i) { - PageIndicatorMarker marker = (PageIndicatorMarker) getChildAt(i); + PageIndicatorDot marker = (PageIndicatorDot) getChildAt(i); int markerIndex = mMarkers.indexOf(marker); if (markerIndex < windowStart || markerIndex >= windowEnd) { removeView(marker); @@ -125,7 +113,7 @@ public class PageIndicator extends LinearLayout { // Add all the new children that belong in the window for (int i = 0; i < mMarkers.size(); ++i) { - PageIndicatorMarker marker = (PageIndicatorMarker) mMarkers.get(i); + PageIndicatorDot marker = (PageIndicatorDot) mMarkers.get(i); if (windowStart <= i && i < windowEnd) { if (indexOfChild(marker) < 0) { addView(marker, i - windowStart); @@ -161,58 +149,75 @@ public class PageIndicator extends LinearLayout { mWindowRange[1] = windowEnd; } - void addMarker(int index, PageMarkerResources marker, boolean allowAnimations) { + @Override + public void addMarker(int index, PageMarkerResources marker, boolean allowAnimations) { index = Math.max(0, Math.min(index, mMarkers.size())); - PageIndicatorMarker m = - (PageIndicatorMarker) mLayoutInflater.inflate(R.layout.page_indicator_marker, + PageIndicatorDot m = + (PageIndicatorDot) mLayoutInflater.inflate(R.layout.page_indicator_marker, this, false); m.setMarkerDrawables(marker.activeId, marker.inactiveId); mMarkers.add(index, m); offsetWindowCenterTo(mActiveMarkerIndex, allowAnimations); } - void addMarkers(ArrayList<PageMarkerResources> markers, boolean allowAnimations) { + + @Override + public void addMarkers(ArrayList<PageMarkerResources> markers, boolean allowAnimations) { for (int i = 0; i < markers.size(); ++i) { addMarker(Integer.MAX_VALUE, markers.get(i), allowAnimations); } } - void updateMarker(int index, PageMarkerResources marker) { - PageIndicatorMarker m = mMarkers.get(index); + @Override + public void updateMarker(int index, PageMarkerResources marker) { + PageIndicatorDot m = mMarkers.get(index); m.setMarkerDrawables(marker.activeId, marker.inactiveId); } - void removeMarker(int index, boolean allowAnimations) { + @Override + public void removeMarker(int index, boolean allowAnimations) { if (mMarkers.size() > 0) { index = Math.max(0, Math.min(mMarkers.size() - 1, index)); mMarkers.remove(index); offsetWindowCenterTo(mActiveMarkerIndex, allowAnimations); } } - void removeAllMarkers(boolean allowAnimations) { + + @Override + public View getView() { + return this; + } + + @Override + public void setProgress(float progress) { + } + + @Override + public void removeAllMarkers(boolean allowAnimations) { while (mMarkers.size() > 0) { removeMarker(Integer.MAX_VALUE, allowAnimations); } } - void setActiveMarker(int index) { + @Override + public void setActiveMarker(int index) { // Center the active marker mActiveMarkerIndex = index; offsetWindowCenterTo(index, false); } - void dumpState(String txt) { + private void dumpState(String txt) { System.out.println(txt); System.out.println("\tmMarkers: " + mMarkers.size()); for (int i = 0; i < mMarkers.size(); ++i) { - PageIndicatorMarker m = mMarkers.get(i); + PageIndicatorDot m = mMarkers.get(i); System.out.println("\t\t(" + i + ") " + m); } System.out.println("\twindow: [" + mWindowRange[0] + ", " + mWindowRange[1] + "]"); System.out.println("\tchildren: " + getChildCount()); for (int i = 0; i < getChildCount(); ++i) { - PageIndicatorMarker m = (PageIndicatorMarker) getChildAt(i); + PageIndicatorDot m = (PageIndicatorDot) getChildAt(i); System.out.println("\t\t(" + i + ") " + m); } System.out.println("\tactive: " + mActiveMarkerIndex); diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorLine.java b/src/com/android/launcher3/pageindicators/PageIndicatorLine.java new file mode 100644 index 000000000..449bf0609 --- /dev/null +++ b/src/com/android/launcher3/pageindicators/PageIndicatorLine.java @@ -0,0 +1,187 @@ +package com.android.launcher3.pageindicators; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.os.Handler; +import android.os.Looper; +import android.support.v4.graphics.ColorUtils; +import android.util.AttributeSet; +import android.util.Log; +import android.util.Property; +import android.view.View; +import android.view.ViewConfiguration; + +import com.android.launcher3.Utilities; +import com.android.launcher3.dynamicui.ExtractedColors; + +import java.util.ArrayList; + +/** + * A PageIndicator that briefly shows a fraction of a line when moving between pages. + * + * The fraction is 1 / number of pages and the position is based on the progress of the page scroll. + */ +public class PageIndicatorLine extends View implements PageIndicator { + private static final String TAG = "PageIndicatorLine"; + + private static final int LINE_FADE_DURATION = ViewConfiguration.getScrollBarFadeDuration(); + private static final int LINE_FADE_DELAY = ViewConfiguration.getScrollDefaultDelay(); + public static final int WHITE_ALPHA = (int) (0.70f * 255); + public static final int BLACK_ALPHA = (int) (0.65f * 255); + + private final Handler mHandler = new Handler(Looper.getMainLooper()); + + private ValueAnimator mLineAlphaAnimator; + private int mAlpha = 0; + private float mProgress = 0f; + private int mNumPages = 1; + private Paint mLinePaint; + + private Property<Paint, Integer> mPaintAlphaProperty + = new Property<Paint, Integer>(Integer.class, "paint_alpha") { + @Override + public Integer get(Paint paint) { + return paint.getAlpha(); + } + + @Override + public void set(Paint paint, Integer alpha) { + paint.setAlpha(alpha); + invalidate(); + } + }; + + private Runnable mHideLineRunnable = new Runnable() { + @Override + public void run() { + animateLineToAlpha(0); + } + }; + + public PageIndicatorLine(Context context) { + this(context, null); + } + + public PageIndicatorLine(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public PageIndicatorLine(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + mLinePaint = new Paint(); + mLinePaint.setAlpha(0); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + if (mNumPages == 0) { + return; + } + + int availableWidth = canvas.getWidth(); + int lineWidth = availableWidth / mNumPages; + int lineLeft = (int) (mProgress * (availableWidth - lineWidth)); + int lineRight = lineLeft + lineWidth; + canvas.drawRect(lineLeft, 0, lineRight, canvas.getHeight(), mLinePaint); + } + + @Override + public View getView() { + return this; + } + + @Override + public void setProgress(float progress) { + if (getAlpha() == 0) { + return; + } + progress = Utilities.boundToRange(progress, 0f, 1f); + animateLineToAlpha(mAlpha); + mProgress = progress; + invalidate(); + + // Hide after a brief period. + mHandler.removeCallbacksAndMessages(null); + mHandler.postDelayed(mHideLineRunnable, LINE_FADE_DELAY); + } + + @Override + public void removeAllMarkers(boolean allowAnimations) { + mNumPages = 0; + } + + @Override + public void addMarkers(ArrayList<PageMarkerResources> markers, boolean allowAnimations) { + mNumPages += markers.size(); + } + + @Override + public void setActiveMarker(int activePage) { + } + + @Override + public void addMarker(int pageIndex, PageMarkerResources pageIndicatorMarker, + boolean allowAnimations) { + mNumPages++; + } + + @Override + public void removeMarker(int pageIndex, boolean allowAnimations) { + mNumPages--; + } + + @Override + public void updateMarker(int pageIndex, PageMarkerResources pageIndicatorMarker) { + } + + /** + * The line's color will be: + * - mostly opaque white if the hotseat is white (ignoring alpha) + * - mostly opaque black if the hotseat is black (ignoring alpha) + */ + public void updateColor(ExtractedColors extractedColors) { + int originalLineAlpha = mLinePaint.getAlpha(); + int color = extractedColors.getColor(ExtractedColors.HOTSEAT_INDEX, Color.TRANSPARENT); + if (color != Color.TRANSPARENT) { + color = ColorUtils.setAlphaComponent(color, 255); + if (color == Color.BLACK) { + mAlpha = BLACK_ALPHA; + } else if (color == Color.WHITE) { + mAlpha = WHITE_ALPHA; + } else { + Log.e(TAG, "Setting workspace page indicators to an unsupported color: #" + + Integer.toHexString(color)); + } + mLinePaint.setColor(color); + mLinePaint.setAlpha(originalLineAlpha); + } + } + + private void animateLineToAlpha(int alpha) { + if (mLineAlphaAnimator != null) { + // An animation is already running, so ignore the new animation request unless we are + // trying to hide the line, in which case we always allow the animation. + if (alpha != 0) { + return; + } + mLineAlphaAnimator.cancel(); + } + mLineAlphaAnimator = ObjectAnimator.ofInt(mLinePaint, mPaintAlphaProperty, alpha); + mLineAlphaAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mLineAlphaAnimator = null; + } + }); + mLineAlphaAnimator.setDuration(LINE_FADE_DURATION); + mLineAlphaAnimator.start(); + } +} |