From d96fa1336921cc8c8bb4d773b2229b62df86e6ea Mon Sep 17 00:00:00 2001 From: Winson Date: Thu, 28 Jul 2016 12:24:55 -0700 Subject: Fixing RTL wallpaper scrolling. - Ensure that we map the scroll offsets to the full wallpaper offset range - Default to either edge of the wallpaper (depending on RTL) to match the default system wallpaper behavior (ag/1265418) Bug: 28795125 Bug: 29398681 Change-Id: I36c316095057912d2dda0beb43bd1e6aaeac3fdc --- .../util/WallpaperOffsetInterpolator.java | 87 +++++++++++----------- 1 file changed, 45 insertions(+), 42 deletions(-) diff --git a/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java b/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java index 1fbd0dc13..1568beb76 100644 --- a/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java +++ b/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java @@ -18,7 +18,7 @@ public class WallpaperOffsetInterpolator implements Choreographer.FrameCallback private static final int ANIMATION_DURATION = 250; // Don't use all the wallpaper for parallax until you have at least this many pages - private static final int MIN_PARALLAX_PAGE_SPAN = 3; + private static final int MIN_PARALLAX_PAGE_SPAN = 4; private final Choreographer mChoreographer; private final Interpolator mInterpolator; @@ -90,57 +90,60 @@ public class WallpaperOffsetInterpolator implements Choreographer.FrameCallback return false; } + /** + * TODO: do different behavior if it's a live wallpaper? + */ public float wallpaperOffsetForScroll(int scroll) { - // TODO: do different behavior if it's a live wallpaper? - // Don't use up all the wallpaper parallax until you have at least - // MIN_PARALLAX_PAGE_SPAN pages + // To match the default wallpaper behavior in the system, we default to either the left + // or right edge on initialization int numScrollingPages = getNumScreensExcludingEmptyAndCustom(); - int parallaxPageSpan; - if (mWallpaperIsLiveWallpaper) { - parallaxPageSpan = numScrollingPages - 1; - } else { - parallaxPageSpan = Math.max(MIN_PARALLAX_PAGE_SPAN, numScrollingPages - 1); + if (numScrollingPages <= 1) { + return mIsRtl ? 1f : 0f; } - mNumPagesForWallpaperParallax = parallaxPageSpan; - if (mWorkspace.getChildCount() <= 1) { - if (mIsRtl) { - return 1 - 1.0f/mNumPagesForWallpaperParallax; - } - return 0; + // Distribute the wallpaper parallax over a minimum of MIN_PARALLAX_PAGE_SPAN workspace + // screens, not including the custom screen, and empty screens (if > MIN_PARALLAX_PAGE_SPAN) + if (mWallpaperIsLiveWallpaper) { + mNumPagesForWallpaperParallax = numScrollingPages; + } else { + mNumPagesForWallpaperParallax = Math.max(MIN_PARALLAX_PAGE_SPAN, numScrollingPages); } - // Exclude the leftmost page - int emptyExtraPages = numEmptyScreensToIgnore(); - int firstIndex = mWorkspace.numCustomPages(); - // Exclude the last extra empty screen (if we have > MIN_PARALLAX_PAGE_SPAN pages) - int lastIndex = mWorkspace.getChildCount() - 1 - emptyExtraPages; + // Offset by the custom screen + int leftPageIndex; + int rightPageIndex; if (mIsRtl) { - int temp = firstIndex; - firstIndex = lastIndex; - lastIndex = temp; + rightPageIndex = mWorkspace.numCustomPages(); + leftPageIndex = rightPageIndex + numScrollingPages - 1; + } else { + leftPageIndex = mWorkspace.numCustomPages(); + rightPageIndex = leftPageIndex + numScrollingPages - 1; } - int firstPageScrollX = mWorkspace.getScrollForPage(firstIndex); - int scrollRange = mWorkspace.getScrollForPage(lastIndex) - firstPageScrollX; + // Calculate the scroll range + int leftPageScrollX = mWorkspace.getScrollForPage(leftPageIndex); + int rightPageScrollX = mWorkspace.getScrollForPage(rightPageIndex); + int scrollRange = rightPageScrollX - leftPageScrollX; if (scrollRange == 0) { - return 0; - } else { - // Sometimes the left parameter of the pages is animated during a layout transition; - // this parameter offsets it to keep the wallpaper from animating as well - int adjustedScroll = - scroll - firstPageScrollX - mWorkspace.getLayoutTransitionOffsetForPage(0); - float offset = Math.min(1, adjustedScroll / (float) scrollRange); - offset = Math.max(0, offset); - - // On RTL devices, push the wallpaper offset to the right if we don't have enough - // pages (ie if numScrollingPages < MIN_PARALLAX_PAGE_SPAN) - if (!mWallpaperIsLiveWallpaper && numScrollingPages < MIN_PARALLAX_PAGE_SPAN - && mIsRtl) { - return offset * (parallaxPageSpan - numScrollingPages + 1) / parallaxPageSpan; - } - return offset * (numScrollingPages - 1) / parallaxPageSpan; + return 0f; + } + + // Sometimes the left parameter of the pages is animated during a layout transition; + // this parameter offsets it to keep the wallpaper from animating as well + int adjustedScroll = scroll - leftPageScrollX - + mWorkspace.getLayoutTransitionOffsetForPage(0); + float offset = Utilities.boundToRange((float) adjustedScroll / scrollRange, 0f, 1f); + + // The offset is now distributed 0..1 between the left and right pages that we care about, + // so we just map that between the pages that we are using for parallax + float rtlOffset = 0; + if (mIsRtl) { + // In RTL, the pages are right aligned, so adjust the offset from the end + rtlOffset = (float) ((mNumPagesForWallpaperParallax - 1) - (numScrollingPages - 1)) / + (mNumPagesForWallpaperParallax - 1); } + return rtlOffset + offset * + ((float) (numScrollingPages - 1) / (mNumPagesForWallpaperParallax - 1)); } private float wallpaperOffsetForCurrentScroll() { @@ -182,7 +185,7 @@ public class WallpaperOffsetInterpolator implements Choreographer.FrameCallback private void setWallpaperOffsetSteps() { // Set wallpaper offset steps (1 / (number of screens - 1)) - float xOffset = 1.0f / mNumPagesForWallpaperParallax; + float xOffset = 1.0f / (mNumPagesForWallpaperParallax - 1); if (xOffset != mLastSetWallpaperOffsetSteps) { mWallpaperManager.setWallpaperOffsetSteps(xOffset, 1.0f); mLastSetWallpaperOffsetSteps = xOffset; -- cgit v1.2.3 From c7d2e83c15e85b2695e016213549d08e63c923b3 Mon Sep 17 00:00:00 2001 From: Winson Date: Thu, 28 Jul 2016 12:24:55 -0700 Subject: Working around incorrect wallpaper offsets being calculated in RTL. - When launcher starts up, onCreate() triggers the launcher model loader to start, which calls bindScreens() to add the workspace pages. However, layout does not happen until the device is unlocked, which means that even though the default screen index and children are there the page scrolls are calculated incorrectly, and even in RTL, the page scroll for the 0th screen is zero (it should be at the right most edge of the workspace). This CL works around this by deferring until the first layout after bindScreens() to unlock the wallpaper offset from its default bounds. The workaround is only applied when the launcher activity is first created. Bug: 28795125 Change-Id: I33da0d7f934f5337d26e69f068f579a32897a837 --- src/com/android/launcher3/Launcher.java | 8 ++++++++ src/com/android/launcher3/Workspace.java | 17 ++++++++++++++++- .../launcher3/util/WallpaperOffsetInterpolator.java | 16 ++++++++++++++-- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 3f12abfd4..aa6f62e94 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -1372,6 +1372,9 @@ public class Launcher extends Activity mWorkspace.setHapticFeedbackEnabled(false); mWorkspace.setOnLongClickListener(this); mWorkspace.setup(mDragController); + // Until the workspace is bound, ensure that we keep the wallpaper offset locked to the + // default state, otherwise we will update to the wrong offsets in RTL + mWorkspace.lockWallpaperToDefaultPage(); mWorkspace.bindAndInitFirstWorkspaceScreen(null /* recycled qsb */); mDragController.addDragListener(mWorkspace); @@ -3667,6 +3670,11 @@ public class Launcher extends Activity mWorkspace.createCustomContentContainer(); populateCustomContentContainer(); } + + // After we have added all the screens, if the wallpaper was locked to the default state, + // then notify to indicate that it can be released and a proper wallpaper offset can be + // computed before the next layout + mWorkspace.unlockWallpaperFromDefaultPageOnNextLayout(); } private void bindAddScreens(ArrayList orderedScreenIds) { diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 3c057e6fd..264da04d8 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -90,7 +90,6 @@ import com.android.launcher3.widget.PendingAddWidgetInfo; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; -import java.util.concurrent.atomic.AtomicInteger; /** * The workspace is a wide area with a wallpaper and a finite number of pages. @@ -253,6 +252,7 @@ public class Workspace extends PagedView private boolean mWorkspaceFadeInAdjacentScreens; final WallpaperOffsetInterpolator mWallpaperOffset; + private boolean mUnlockWallpaperFromDefaultPageOnLayout; @Thunk Runnable mDelayedResizeRunnable; private Runnable mDelayedSnapToPageRunnable; @@ -1616,6 +1616,17 @@ public class Workspace extends PagedView }); } + public void lockWallpaperToDefaultPage() { + mWallpaperOffset.setLockToDefaultPage(true); + } + + public void unlockWallpaperFromDefaultPageOnNextLayout() { + if (mWallpaperOffset.isLockedToDefaultPage()) { + mUnlockWallpaperFromDefaultPageOnLayout = true; + requestLayout(); + } + } + protected void snapToPage(int whichPage, Runnable r) { snapToPage(whichPage, SLOW_PAGE_SNAP_ANIMATION_DURATION, r); } @@ -1797,6 +1808,10 @@ public class Workspace extends PagedView @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + if (mUnlockWallpaperFromDefaultPageOnLayout) { + mWallpaperOffset.setLockToDefaultPage(false); + mUnlockWallpaperFromDefaultPageOnLayout = false; + } if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < getChildCount()) { mWallpaperOffset.syncWithScroll(); mWallpaperOffset.jumpToFinal(); diff --git a/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java b/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java index 1568beb76..d7b391427 100644 --- a/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java +++ b/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java @@ -33,6 +33,7 @@ public class WallpaperOffsetInterpolator implements Choreographer.FrameCallback private float mFinalOffset = 0.0f; private float mCurrentOffset = 0.5f; // to force an initial update private boolean mWaitingForUpdate; + private boolean mLockedToDefaultPage; private boolean mAnimating; private long mAnimationStartTime; @@ -68,6 +69,17 @@ public class WallpaperOffsetInterpolator implements Choreographer.FrameCallback } } + /** + * Locks the wallpaper offset to the offset in the default state of Launcher. + */ + public void setLockToDefaultPage(boolean lockToDefaultPage) { + mLockedToDefaultPage = lockToDefaultPage; + } + + public boolean isLockedToDefaultPage() { + return mLockedToDefaultPage; + } + public boolean computeScrollOffset() { final float oldOffset = mCurrentOffset; if (mAnimating) { @@ -97,7 +109,7 @@ public class WallpaperOffsetInterpolator implements Choreographer.FrameCallback // To match the default wallpaper behavior in the system, we default to either the left // or right edge on initialization int numScrollingPages = getNumScreensExcludingEmptyAndCustom(); - if (numScrollingPages <= 1) { + if (mLockedToDefaultPage || numScrollingPages <= 1) { return mIsRtl ? 1f : 0f; } @@ -194,7 +206,7 @@ public class WallpaperOffsetInterpolator implements Choreographer.FrameCallback public void setFinalX(float x) { scheduleUpdate(); - mFinalOffset = Math.max(0f, Math.min(x, 1.0f)); + mFinalOffset = Math.max(0f, Math.min(x, 1f)); if (getNumScreensExcludingEmptyAndCustom() != mNumScreens) { if (mNumScreens > 0) { // Don't animate if we're going from 0 screens -- cgit v1.2.3