diff options
author | Adam Cohen <adamcohen@google.com> | 2014-10-16 09:49:24 -0700 |
---|---|---|
committer | Adam Cohen <adamcohen@google.com> | 2014-10-22 17:40:39 -0700 |
commit | c2d6e897dbcb96b7b629e42002966368fbda2f95 (patch) | |
tree | 1a9d6e72ac5160709e64e45ffd6de094084f1bec /src/com | |
parent | 1aa3abea279d8b3ead93d704d424757bfe65c2bd (diff) | |
download | android_packages_apps_Trebuchet-c2d6e897dbcb96b7b629e42002966368fbda2f95.tar.gz android_packages_apps_Trebuchet-c2d6e897dbcb96b7b629e42002966368fbda2f95.tar.bz2 android_packages_apps_Trebuchet-c2d6e897dbcb96b7b629e42002966368fbda2f95.zip |
First pass of the Launcher Overlay interface / impl
-> Added simple reference launcher extension
-> Make launcher able to handle a null qsb
Change-Id: Ib1575243cac800a335e95bbf00cdc394bb4741c3
Diffstat (limited to 'src/com')
-rw-r--r-- | src/com/android/launcher3/DragLayer.java | 14 | ||||
-rw-r--r-- | src/com/android/launcher3/Launcher.java | 97 | ||||
-rw-r--r-- | src/com/android/launcher3/LauncherCallbacks.java | 19 | ||||
-rw-r--r-- | src/com/android/launcher3/LauncherExtension.java | 354 | ||||
-rw-r--r-- | src/com/android/launcher3/PagedView.java | 21 | ||||
-rw-r--r-- | src/com/android/launcher3/SearchDropTargetBar.java | 37 | ||||
-rw-r--r-- | src/com/android/launcher3/Workspace.java | 91 |
7 files changed, 595 insertions, 38 deletions
diff --git a/src/com/android/launcher3/DragLayer.java b/src/com/android/launcher3/DragLayer.java index a8a61ea89..ff9072ab4 100644 --- a/src/com/android/launcher3/DragLayer.java +++ b/src/com/android/launcher3/DragLayer.java @@ -89,6 +89,8 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang private Drawable mLeftHoverDrawableActive; private Drawable mRightHoverDrawableActive; + private boolean mBlockTouches = false; + /** * Used to create a new DragLayer from XML. * @@ -185,11 +187,19 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang return false; } + public void setBlockTouch(boolean block) { + mBlockTouches = block; + } + private boolean handleTouchDown(MotionEvent ev, boolean intercept) { Rect hitRect = new Rect(); int x = (int) ev.getX(); int y = (int) ev.getY(); + if (mBlockTouches) { + return true; + } + for (AppWidgetResizeFrame child: mResizeFrames) { child.getHitRect(hitRect); if (hitRect.contains(x, y)) { @@ -332,6 +342,10 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang int x = (int) ev.getX(); int y = (int) ev.getY(); + if (mBlockTouches) { + return true; + } + if (action == MotionEvent.ACTION_DOWN) { if (handleTouchDown(ev, false)) { return true; diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index be845400d..f0129683a 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -86,6 +86,7 @@ import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; import android.view.ViewAnimationUtils; import android.view.ViewGroup; +import android.view.ViewStub; import android.view.ViewTreeObserver; import android.view.Window; import android.view.WindowManager; @@ -227,6 +228,10 @@ public class Launcher extends Activity private boolean mIsSafeModeEnabled; + LauncherOverlayCallbacks mLauncherOverlayCallbacks = new LauncherOverlayCallbacksImpl(); + LauncherOverlay mLauncherOverlay; + ViewGroup mLauncherOverlayView; + static final int APPWIDGET_HOST_ID = 1024; public static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT = 300; private static final int ON_ACTIVITY_RESULT_ANIMATION_DELAY = 500; @@ -506,6 +511,13 @@ public class Launcher extends Activity if (mLauncherCallbacks != null) { mLauncherCallbacks.onCreate(savedInstanceState); + if (mLauncherCallbacks.hasLauncherOverlay()) { + ViewStub stub = (ViewStub) findViewById(R.id.launcher_overlay_stub); + mLauncherOverlayView = (ViewGroup) stub.inflate(); + mLauncherOverlay = mLauncherCallbacks.setLauncherOverlayView(mLauncherOverlayView, + mLauncherOverlayCallbacks); + mWorkspace.setLauncherOverlay(mLauncherOverlay); + } } } @@ -1144,6 +1156,84 @@ public class Launcher extends Activity boolean isScrollingAllowed(); } + public interface LauncherOverlay { + + /** + * Touch interaction leading to overscroll has begun + */ + public void onScrollInteractionBegin(); + + /** + * Touch interaction related to overscroll has ended + */ + public void onScrollInteractionEnd(); + + /** + * Scroll progress, between 0 and 100, when the user scrolls beyond the leftmost + * screen (or in the case of RTL, the rightmost screen). + */ + public void onScrollChange(int progress, boolean rtl); + + /** + * Screen has stopped scrolling + */ + public void onScrollSettled(); + + /** + * This method can be called by the Launcher in order to force the LauncherOverlay + * to exit fully immersive mode. + */ + public void forceExitFullImmersion(); + } + + public interface LauncherOverlayCallbacks { + /** + * This method indicates whether a call to {@link #enterFullImmersion()} will succeed, + * however it doesn't modify any state within the launcher. + */ + public boolean canEnterFullImmersion(); + + /** + * Should be called to tell Launcher that the LauncherOverlay will take over interaction, + * eg. by occupying the full screen and handling all touch events. + * + * @return true if Launcher allows the LauncherOverlay to become fully immersive. In this + * case, Launcher will modify any necessary state and assumes the overlay is + * handling all interaction. If false, the LauncherOverlay should cancel any + * + */ + public boolean enterFullImmersion(); + + /** + * Must be called when exiting fully immersive mode. Indicates to Launcher that it has + * full control over UI and state. + */ + public void exitFullImmersion(); + } + + class LauncherOverlayCallbacksImpl implements LauncherOverlayCallbacks { + + @Override + public boolean canEnterFullImmersion() { + return mState == State.WORKSPACE; + } + + @Override + public boolean enterFullImmersion() { + if (mState == State.WORKSPACE) { + // When fully immersed, disregard any touches which fall through. + mDragLayer.setBlockTouch(true); + return true; + } + return false; + } + + @Override + public void exitFullImmersion() { + mDragLayer.setBlockTouch(false); + } + } + protected boolean hasSettings() { if (mLauncherCallbacks != null) { return mLauncherCallbacks.hasSettings(); @@ -4084,11 +4174,8 @@ public class Launcher extends Activity } public View getQsbBar() { - if (mLauncherCallbacks != null) { - View qsb = mLauncherCallbacks.getQsbBar(); - if (qsb != null) { - return qsb; - } + if (mLauncherCallbacks != null && mLauncherCallbacks.providesSearch()) { + return mLauncherCallbacks.getQsbBar(); } if (mQsb == null) { diff --git a/src/com/android/launcher3/LauncherCallbacks.java b/src/com/android/launcher3/LauncherCallbacks.java index aef2adc7f..e0cfa27ba 100644 --- a/src/com/android/launcher3/LauncherCallbacks.java +++ b/src/com/android/launcher3/LauncherCallbacks.java @@ -6,6 +6,7 @@ import android.graphics.Rect; import android.os.Bundle; import android.view.Menu; import android.view.View; +import android.view.ViewGroup; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -86,4 +87,22 @@ public interface LauncherCallbacks { public boolean overrideWallpaperDimensions(); public boolean isLauncherPreinstalled(); + /** + * Returning true will immediately result in a call to {@link #setLauncherOverlayView(ViewGroup, + * com.android.launcher3.Launcher.LauncherOverlayCallbacks)}. + * + * @return true if this launcher extension will provide an overlay + */ + public boolean hasLauncherOverlay(); + + /** + * Handshake to establish an overlay relationship + * + * @param overlayView Full screen overlay ViewGroup into which custom views can be placed. + * @param callbacks A set of callbacks provided by Launcher in relation to the overlay + * @return an interface used to make requests and notify the Launcher in relation to the overlay + */ + public Launcher.LauncherOverlay setLauncherOverlayView(ViewGroup overlayView, + Launcher.LauncherOverlayCallbacks callbacks); + } diff --git a/src/com/android/launcher3/LauncherExtension.java b/src/com/android/launcher3/LauncherExtension.java new file mode 100644 index 000000000..10bbd357d --- /dev/null +++ b/src/com/android/launcher3/LauncherExtension.java @@ -0,0 +1,354 @@ +package com.android.launcher3; + +import android.animation.Animator; +import android.animation.Animator.AnimatorListener; +import android.animation.AnimatorListenerAdapter; +import android.animation.ObjectAnimator; +import android.content.ComponentName; +import android.content.Intent; +import android.graphics.Rect; +import android.os.Bundle; +import android.view.Menu; +import android.view.View; +import android.view.ViewGroup; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.ArrayList; + +/** + * This class represents a very trivial LauncherExtension. It primarily serves as a simple + * class to exercise the LauncherOverlay interface. + */ +public class LauncherExtension extends Launcher { + + //------ Activity methods -------// + @Override + public void onCreate(Bundle savedInstanceState) { + setLauncherCallbacks(new LauncherExtensionCallbacks()); + super.onCreate(savedInstanceState); + } + + public class LauncherExtensionCallbacks implements LauncherCallbacks { + + LauncherExtensionOverlay mLauncherOverlay = new LauncherExtensionOverlay(); + + @Override + public void preOnCreate() { + } + + @Override + public void onCreate(Bundle savedInstanceState) { + } + + @Override + public void preOnResume() { + } + + @Override + public void onResume() { + } + + @Override + public void onStart() { + } + + @Override + public void onStop() { + } + + @Override + public void onPause() { + } + + @Override + public void onDestroy() { + } + + @Override + public void onSaveInstanceState(Bundle outState) { + } + + @Override + public void onPostCreate(Bundle savedInstanceState) { + } + + @Override + public void onNewIntent(Intent intent) { + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + } + + @Override + public void onWindowFocusChanged(boolean hasFocus) { + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + return false; + } + + @Override + public void dump(String prefix, FileDescriptor fd, PrintWriter w, String[] args) { + } + + @Override + public void onHomeIntent() { + } + + @Override + public boolean handleBackPressed() { + if (mLauncherOverlay.isOverlayPanelShowing()) { + mLauncherOverlay.hideOverlayPanel(); + return true; + } + return false; + } + + @Override + public void onLauncherProviderChange() { + } + + @Override + public void finishBindingItems(boolean upgradePath) { + } + + @Override + public void onClickAllAppsButton(View v) { + } + + @Override + public void bindAllApplications(ArrayList<AppInfo> apps) { + } + + @Override + public void onClickFolderIcon(View v) { + } + + @Override + public void onClickAppShortcut(View v) { + } + + @Override + public void onClickPagedViewIcon(View v) { + } + + @Override + public void onClickWallpaperPicker(View v) { + } + + @Override + public void onClickSettingsButton(View v) { + } + + @Override + public void onClickAddWidgetButton(View v) { + } + + @Override + public void onPageSwitch(View newPage, int newPageIndex) { + } + + @Override + public void onWorkspaceLockedChanged() { + } + + @Override + public void onDragStarted(View view) { + } + + @Override + public void onInteractionBegin() { + } + + @Override + public void onInteractionEnd() { + } + + @Override + public boolean forceDisableVoiceButtonProxy() { + return false; + } + + @Override + public boolean providesSearch() { + return true; + } + + @Override + public boolean startSearch(String initialQuery, boolean selectInitialQuery, + Bundle appSearchData, Rect sourceBounds) { + return false; + } + + @Override + public void startVoice() { + } + + @Override + public boolean hasCustomContentToLeft() { + return false; + } + + @Override + public void populateCustomContentContainer() { + } + + @Override + public View getQsbBar() { + return mLauncherOverlay.getSearchBox(); + } + + @Override + public Intent getFirstRunActivity() { + return null; + } + + @Override + public boolean hasFirstRunActivity() { + return false; + } + + @Override + public boolean hasDismissableIntroScreen() { + return false; + } + + @Override + public View getIntroScreen() { + return null; + } + + @Override + public boolean shouldMoveToDefaultScreenOnHomeIntent() { + return true; + } + + @Override + public boolean hasSettings() { + return false; + } + + @Override + public ComponentName getWallpaperPickerComponent() { + return null; + } + + @Override + public boolean overrideWallpaperDimensions() { + return false; + } + + @Override + public boolean isLauncherPreinstalled() { + return false; + } + + @Override + public boolean hasLauncherOverlay() { + return true; + } + + @Override + public LauncherOverlay setLauncherOverlayView(ViewGroup overlayView, + LauncherOverlayCallbacks callbacks) { + + mLauncherOverlay.setOverlayCallbacks(callbacks); + mLauncherOverlay.setOverlayView(overlayView); + + return mLauncherOverlay; + } + + class LauncherExtensionOverlay implements LauncherOverlay { + LauncherOverlayCallbacks mLauncherOverlayCallbacks; + ViewGroup mOverlayView; + View mSearchBox; + View mSearchOverlay; + boolean mShowOverlayFeedback; + int mProgress; + boolean mOverlayPanelShowing; + + @Override + public void onScrollInteractionBegin() { + if (mLauncherOverlayCallbacks.canEnterFullImmersion()) { + mShowOverlayFeedback = true; + updatePanelOffset(0); + mSearchOverlay.setVisibility(View.VISIBLE); + mSearchOverlay.setLayerType(View.LAYER_TYPE_HARDWARE, null); + } + } + + @Override + public void onScrollChange(int progress, boolean rtl) { + mProgress = progress; + if (mShowOverlayFeedback) { + updatePanelOffset(progress); + } + } + + private void updatePanelOffset(int progress) { + int panelWidth = mSearchOverlay.getMeasuredWidth(); + int offset = (int) ((progress / 100f) * panelWidth); + mSearchOverlay.setTranslationX(- panelWidth + offset); + } + + @Override + public void onScrollInteractionEnd() { + if (mProgress > 25 && mLauncherOverlayCallbacks.enterFullImmersion()) { + ObjectAnimator oa = LauncherAnimUtils.ofFloat(mSearchOverlay, "translationX", 0); + oa.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator arg0) { + mSearchOverlay.setLayerType(View.LAYER_TYPE_NONE, null); + } + }); + oa.start(); + mOverlayPanelShowing = true; + mShowOverlayFeedback = false; + } + } + + @Override + public void onScrollSettled() { + if (mShowOverlayFeedback) { + mSearchOverlay.setVisibility(View.INVISIBLE); + mSearchOverlay.setLayerType(View.LAYER_TYPE_NONE, null); + } + mShowOverlayFeedback = false; + mProgress = 0; + } + + public void hideOverlayPanel() { + mLauncherOverlayCallbacks.exitFullImmersion(); + mSearchOverlay.setVisibility(View.INVISIBLE); + mOverlayPanelShowing = false; + } + + public boolean isOverlayPanelShowing() { + return mOverlayPanelShowing; + } + + @Override + public void forceExitFullImmersion() { + hideOverlayPanel(); + } + + public void setOverlayView(ViewGroup overlayView) { + mOverlayView = (ViewGroup) getLayoutInflater().inflate( + R.layout.launcher_overlay_example, overlayView); + mSearchOverlay = mOverlayView.findViewById(R.id.search_overlay); + mSearchBox = mOverlayView.findViewById(R.id.search_box); + } + + public View getSearchBox() { + return mSearchBox; + } + + public void setOverlayCallbacks(LauncherOverlayCallbacks callbacks) { + mLauncherOverlayCallbacks = callbacks; + } + }; + } +} diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java index 48fc0c98f..7d65f4686 100644 --- a/src/com/android/launcher3/PagedView.java +++ b/src/com/android/launcher3/PagedView.java @@ -204,6 +204,8 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc protected boolean mAllowLongPress = true; + private boolean mWasInOverscroll = false; + // Page Indicator private int mPageIndicatorViewId; private PageIndicator mPageIndicator; @@ -625,6 +627,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc // a method that subclasses can override to add behavior protected void onPageEndMoving() { + mWasInOverscroll = false; } /** @@ -663,6 +666,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc if (isXBeforeFirstPage) { super.scrollTo(0, y); if (mAllowOverScroll) { + mWasInOverscroll = true; if (isRtl) { overScroll(x - mMaxScrollX); } else { @@ -672,6 +676,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc } else if (isXAfterLastPage) { super.scrollTo(mMaxScrollX, y); if (mAllowOverScroll) { + mWasInOverscroll = true; if (isRtl) { overScroll(x); } else { @@ -679,6 +684,10 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc } } } else { + if (mWasInOverscroll) { + overScroll(0); + mWasInOverscroll = false; + } mOverScrollX = x; super.scrollTo(x, y); } @@ -1513,6 +1522,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc mLastMotionXRemainder = 0; mTouchX = getViewportOffsetX() + getScrollX(); mSmoothingTime = System.nanoTime() / NANOTIME_DIV; + onScrollInteractionBegin(); pageBeginMoving(); } } @@ -1752,6 +1762,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc mActivePointerId = ev.getPointerId(0); if (mTouchState == TOUCH_STATE_SCROLLING) { + onScrollInteractionBegin(); pageBeginMoving(); } break; @@ -1940,6 +1951,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc getScrollY(), vX, 0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0); invalidate(); } + onScrollInteractionEnd(); } else if (mTouchState == TOUCH_STATE_PREV_PAGE) { // at this point we have not moved beyond the touch slop // (otherwise mTouchState would be TOUCH_STATE_SCROLLING), so @@ -2025,6 +2037,15 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc mActivePointerId = INVALID_POINTER; } + /** + * Triggered by scrolling via touch + */ + protected void onScrollInteractionBegin() { + } + + protected void onScrollInteractionEnd() { + } + protected void onUnhandledTap(MotionEvent ev) { ((Launcher) getContext()).onClick(this); } diff --git a/src/com/android/launcher3/SearchDropTargetBar.java b/src/com/android/launcher3/SearchDropTargetBar.java index 435dbda1d..6205088c5 100644 --- a/src/com/android/launcher3/SearchDropTargetBar.java +++ b/src/com/android/launcher3/SearchDropTargetBar.java @@ -19,6 +19,7 @@ package com.android.launcher3; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Rect; import android.graphics.drawable.Drawable; @@ -37,7 +38,7 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D private static final int sTransitionOutDuration = 175; private ObjectAnimator mDropTargetBarAnim; - private ObjectAnimator mQSBSearchBarAnim; + private ValueAnimator mQSBSearchBarAnim; private static final AccelerateInterpolator sAccelerateInterpolator = new AccelerateInterpolator(); @@ -70,28 +71,38 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D mInfoDropTarget.setLauncher(launcher); mDeleteDropTarget.setLauncher(launcher); mQSBSearchBar = launcher.getQsbBar(); - if (mEnableDropDownDropTargets) { - mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "translationY", 0, - -mBarHeight); + if (mQSBSearchBar != null) { + if (mEnableDropDownDropTargets) { + mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "translationY", 0, + -mBarHeight); + } else { + mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "alpha", 1f, 0f); + } + setupAnimation(mQSBSearchBarAnim, mQSBSearchBar); } else { - mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "alpha", 1f, 0f); + // Create a no-op animation of the search bar is null + mQSBSearchBarAnim = ValueAnimator.ofFloat(0, 0); + mQSBSearchBarAnim.setDuration(sTransitionInDuration); } - setupAnimation(mQSBSearchBarAnim, mQSBSearchBar); } private void prepareStartAnimation(View v) { // Enable the hw layers before the animation starts (will be disabled in the onAnimationEnd // callback below) - v.setLayerType(View.LAYER_TYPE_HARDWARE, null); + if (v != null) { + v.setLayerType(View.LAYER_TYPE_HARDWARE, null); + } } - private void setupAnimation(ObjectAnimator anim, final View v) { + private void setupAnimation(ValueAnimator anim, final View v) { anim.setInterpolator(sAccelerateInterpolator); anim.setDuration(sTransitionInDuration); anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - v.setLayerType(View.LAYER_TYPE_NONE, null); + if (v != null) { + v.setLayerType(View.LAYER_TYPE_NONE, null); + } } }); } @@ -145,9 +156,9 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D mQSBSearchBarAnim.reverse(); } else { mQSBSearchBarAnim.cancel(); - if (mEnableDropDownDropTargets) { + if (mQSBSearchBar != null && mEnableDropDownDropTargets) { mQSBSearchBar.setTranslationY(0); - } else { + } else if (mQSBSearchBar != null) { mQSBSearchBar.setAlpha(1f); } } @@ -161,9 +172,9 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D mQSBSearchBarAnim.start(); } else { mQSBSearchBarAnim.cancel(); - if (mEnableDropDownDropTargets) { + if (mQSBSearchBar != null && mEnableDropDownDropTargets) { mQSBSearchBar.setTranslationY(-mBarHeight); - } else { + } else if (mQSBSearchBar != null) { mQSBSearchBar.setAlpha(0f); } } diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 2683becf4..8ddb837de 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -67,6 +67,7 @@ import android.widget.TextView; import com.android.launcher3.FolderIcon.FolderRingAnimator; import com.android.launcher3.Launcher.CustomContentCallbacks; +import com.android.launcher3.Launcher.LauncherOverlay; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.compat.PackageInstallerCompat; import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo; @@ -289,6 +290,12 @@ public class Workspace extends SmoothPagedView private boolean mDeferDropAfterUninstall; private boolean mUninstallSuccessful; + // State related to Launcher Overlay + LauncherOverlay mLauncherOverlay; + boolean mScrollInteractionBegan; + boolean mStartedSendingScrollEvents; + boolean mShouldSendPageSettled; + private final Runnable mBindPages = new Runnable() { @Override public void run() { @@ -1249,6 +1256,58 @@ public class Workspace extends SmoothPagedView stripEmptyScreens(); mStripScreensOnPageStopMoving = false; } + + if (mShouldSendPageSettled) { + mLauncherOverlay.onScrollSettled(); + mShouldSendPageSettled = false; + } + } + + protected void onScrollInteractionBegin() { + super.onScrollInteractionEnd(); + mScrollInteractionBegan = true; + } + + protected void onScrollInteractionEnd() { + super.onScrollInteractionEnd(); + mScrollInteractionBegan = false; + if (mStartedSendingScrollEvents) { + mStartedSendingScrollEvents = false; + mLauncherOverlay.onScrollInteractionEnd(); + } + } + + public void setLauncherOverlay(LauncherOverlay overlay) { + mLauncherOverlay = overlay; + } + + @Override + protected void overScroll(float amount) { + boolean isRtl = isLayoutRtl(); + boolean shouldOverScroll = (amount <= 0 && (!hasCustomContent() || isRtl)) || + (amount >= 0 && (!hasCustomContent() || !isRtl)); + + boolean shouldScrollOverlay = (amount <= 0 && mLauncherOverlay != null && !isRtl) || + (amount >= 0 && mLauncherOverlay != null && isRtl); + + if (shouldScrollOverlay) { + if (!mStartedSendingScrollEvents && mScrollInteractionBegan) { + mStartedSendingScrollEvents = true; + mLauncherOverlay.onScrollInteractionBegin(); + mShouldSendPageSettled = true; + } + int screenSize = getViewportWidth(); + float f = (amount / screenSize); + + int progress = (int) Math.abs((f * 100)); + + mLauncherOverlay.onScrollChange(progress, isRtl); + } else if (shouldOverScroll) { + dampedOverScroll(amount); + mOverScrollEffect = acceleratedOverFactor(amount); + } else { + mOverScrollEffect = 0; + } } @Override @@ -1710,18 +1769,6 @@ public class Workspace extends SmoothPagedView } } - @Override - protected void overScroll(float amount) { - boolean shouldOverScroll = (amount < 0 && (!hasCustomContent() || isLayoutRtl())) || - (amount > 0 && (!hasCustomContent() || !isLayoutRtl())); - if (shouldOverScroll) { - dampedOverScroll(amount); - mOverScrollEffect = acceleratedOverFactor(amount); - } else { - mOverScrollEffect = 0; - } - } - protected void onAttachedToWindow() { super.onAttachedToWindow(); mWindowToken = getWindowToken(); @@ -2353,10 +2400,6 @@ public class Workspace extends SmoothPagedView .alpha(finalHotseatAndPageIndicatorAlpha).withLayer(); hotseatAlpha.addListener(new AlphaUpdateListener(hotseat)); - Animator searchBarAlpha = new LauncherViewPropertyAnimator(searchBar) - .alpha(finalSearchBarAlpha).withLayer(); - searchBarAlpha.addListener(new AlphaUpdateListener(searchBar)); - Animator overviewPanelAlpha = new LauncherViewPropertyAnimator(overviewPanel) .alpha(finalOverviewPanelAlpha).withLayer(); overviewPanelAlpha.addListener(new AlphaUpdateListener(overviewPanel)); @@ -2364,11 +2407,9 @@ public class Workspace extends SmoothPagedView // For animation optimations, we may need to provide the Launcher transition // with a set of views on which to force build layers in certain scenarios. hotseat.setLayerType(View.LAYER_TYPE_HARDWARE, null); - searchBar.setLayerType(View.LAYER_TYPE_HARDWARE, null); overviewPanel.setLayerType(View.LAYER_TYPE_HARDWARE, null); if (layerViews != null) { layerViews.add(hotseat); - layerViews.add(searchBar); layerViews.add(overviewPanel); } @@ -2385,11 +2426,21 @@ public class Workspace extends SmoothPagedView overviewPanelAlpha.setDuration(duration); pageIndicatorAlpha.setDuration(duration); hotseatAlpha.setDuration(duration); - searchBarAlpha.setDuration(duration); + + if (searchBar != null) { + Animator searchBarAlpha = new LauncherViewPropertyAnimator(searchBar) + .alpha(finalSearchBarAlpha).withLayer(); + searchBarAlpha.addListener(new AlphaUpdateListener(searchBar)); + searchBar.setLayerType(View.LAYER_TYPE_HARDWARE, null); + if (layerViews != null) { + layerViews.add(searchBar); + } + searchBarAlpha.setDuration(duration); + anim.play(searchBarAlpha); + } anim.play(overviewPanelAlpha); anim.play(hotseatAlpha); - anim.play(searchBarAlpha); anim.play(pageIndicatorAlpha); anim.setStartDelay(delay); } else { |