From 3eb06355e212fc442fc58f096276cd8b9ef2caa3 Mon Sep 17 00:00:00 2001 From: Adam Cohen Date: Thu, 16 Oct 2014 09:49:24 -0700 Subject: First pass of the Launcher Overlay interface / impl -> Added simple reference launcher extension -> Make launcher able to handle a null qsb Change-Id: Ib1575243cac800a335e95bbf00cdc394bb4741c3 --- src/com/android/launcher3/DragLayer.java | 14 + src/com/android/launcher3/Launcher.java | 97 +++++- src/com/android/launcher3/LauncherCallbacks.java | 19 ++ src/com/android/launcher3/LauncherExtension.java | 354 +++++++++++++++++++++ src/com/android/launcher3/PagedView.java | 21 ++ src/com/android/launcher3/SearchDropTargetBar.java | 37 ++- src/com/android/launcher3/Workspace.java | 97 ++++-- 7 files changed, 597 insertions(+), 42 deletions(-) create mode 100644 src/com/android/launcher3/LauncherExtension.java (limited to 'src/com/android') diff --git a/src/com/android/launcher3/DragLayer.java b/src/com/android/launcher3/DragLayer.java index 328c31173..1ded03038 100644 --- a/src/com/android/launcher3/DragLayer.java +++ b/src/com/android/launcher3/DragLayer.java @@ -90,6 +90,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. * @@ -219,11 +221,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)) { @@ -366,6 +376,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 0d964e206..58a09a435 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -98,6 +98,7 @@ import android.view.View; 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; @@ -263,6 +264,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; @@ -582,6 +587,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); + } } IntentFilter protectedAppsFilter = new IntentFilter( "cyanogenmod.intent.action.PROTECTED_COMPONENT_UPDATE"); @@ -1323,6 +1335,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(); @@ -4743,11 +4833,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 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 c456f06d6..ec69b7f8f 100644 --- a/src/com/android/launcher3/PagedView.java +++ b/src/com/android/launcher3/PagedView.java @@ -207,6 +207,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; @@ -645,6 +647,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc mDelayedSnapToPageRunnable.run(); mDelayedSnapToPageRunnable = null; } + mWasInOverscroll = false; } /** @@ -683,6 +686,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 { @@ -692,6 +696,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 { @@ -699,6 +704,10 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc } } } else { + if (mWasInOverscroll) { + overScroll(0); + mWasInOverscroll = false; + } mOverScrollX = x; super.scrollTo(x, y); } @@ -1608,6 +1617,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc mLastMotionXRemainder = 0; mTouchX = getViewportOffsetX() + getScrollX(); mSmoothingTime = System.nanoTime() / NANOTIME_DIV; + onScrollInteractionBegin(); pageBeginMoving(); } } @@ -1847,6 +1857,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc mActivePointerId = ev.getPointerId(0); if (mTouchState == TOUCH_STATE_SCROLLING) { + onScrollInteractionBegin(); pageBeginMoving(); } break; @@ -2036,6 +2047,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 @@ -2121,6 +2133,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 611948d29..1d90a4178 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(); @@ -78,28 +79,38 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D public void setupQSB(Launcher launcher) { mLauncher = 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); + } } }); } @@ -153,9 +164,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); } } @@ -169,9 +180,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 60200177d..2cbbaa702 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -70,6 +70,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; @@ -295,6 +296,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() { @@ -1284,6 +1291,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 @@ -1769,18 +1828,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(); @@ -2493,12 +2540,6 @@ public class Workspace extends SmoothPagedView hotseatAlpha.addListener( new AlphaUpdateListener(hotseat, finalHotseatAndPageIndicatorAlpha)); - Animator searchBarAlpha = new LauncherViewPropertyAnimator(searchBar) - .alpha(finalSearchBarAlpha).withLayer(); - if (mShowSearchBar) { - searchBarAlpha.addListener(new AlphaUpdateListener(searchBar, finalSearchBarAlpha)); - } - Animator overviewPanelAlpha = new LauncherViewPropertyAnimator(overviewPanel) .alpha(finalOverviewPanelAlpha).withLayer(); overviewPanelAlpha.addListener( @@ -2507,11 +2548,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); } @@ -2528,7 +2567,20 @@ 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, finalSearchBarAlpha)); + searchBar.setLayerType(View.LAYER_TYPE_HARDWARE, null); + if (layerViews != null) { + layerViews.add(searchBar); + } + searchBarAlpha.setDuration(duration); + if (mShowSearchBar && !mLauncher.getDragController().isDragging()) { + anim.play(searchBarAlpha); + } + } float mOverviewPanelSlideScale = 1.0f; @@ -2576,9 +2628,6 @@ public class Workspace extends SmoothPagedView // Animation animation = AnimationUtils.loadAnimation(mLauncher, R.anim.drop_down); // overviewPanel.startAnimation(animation); anim.play(hotseatAlpha); - if (mShowSearchBar && !mLauncher.getDragController().isDragging()) { - anim.play(searchBarAlpha); - } anim.play(pageIndicatorAlpha); anim.setStartDelay(delay); } else { -- cgit v1.2.3