Merge "Defer starting the recents animation when swiping over back button" into ub-launcher3-master
diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
index 2f0cd78..59b637e 100644
--- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
@@ -20,6 +20,7 @@
import static com.android.systemui.shared.recents.utilities.Utilities.getNextFrameNumber;
import static com.android.systemui.shared.recents.utilities.Utilities.getSurface;
import static com.android.systemui.shared.recents.utilities.Utilities.postAtFrontOfQueueAsynchronously;
+import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -530,7 +531,7 @@
TransactionCompat t = new TransactionCompat();
for (RemoteAnimationTargetCompat target : targets) {
- if (target.mode == RemoteAnimationTargetCompat.MODE_OPENING) {
+ if (target.mode == MODE_OPENING) {
t.setAlpha(target.leash, alpha);
// TODO: This isn't correct at the beginning of the animation, but better
@@ -573,6 +574,16 @@
}
}
+ private boolean isLauncherInSetOfOpeningTargets(RemoteAnimationTargetCompat[] targets) {
+ int launcherTaskId = mLauncher.getTaskId();
+ for (RemoteAnimationTargetCompat target : targets) {
+ if (target.mode == MODE_OPENING && target.taskId == launcherTaskId) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* @return Runner that plays when user goes to Launcher
* ie. pressing home, swiping up from nav bar.
@@ -584,9 +595,12 @@
Runnable finishedCallback) {
Handler handler = mLauncher.getWindow().getDecorView().getHandler();
postAtFrontOfQueueAsynchronously(handler, () -> {
- if (Utilities.getPrefs(mLauncher).getBoolean("pref_use_screenshot_animation",
- true) && mLauncher.isInState(LauncherState.OVERVIEW)) {
- // We use a separate transition for Overview mode.
+ if ((Utilities.getPrefs(mLauncher).getBoolean("pref_use_screenshot_animation",
+ true) && mLauncher.isInState(LauncherState.OVERVIEW))
+ || !isLauncherInSetOfOpeningTargets(targets)) {
+ // We use a separate transition for Overview mode. And we can skip the
+ // animation in cases where Launcher is not in the set of opening targets.
+ // This can happen when Launcher is already visible. ie. Closing a dialog.
setCurrentAnimator(null);
finishedCallback.run();
return;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 9a5640b..57e588b 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -139,7 +139,9 @@
applyProgress();
if (mIsRecentsScrollingToFirstTask) {
int scrollForFirstTask = mRecentsView.getScrollForPage(mRecentsView.getFirstTaskIndex());
- mRecentsView.setScrollX((int) (mTransitionProgress.value * scrollForFirstTask));
+ int scrollForPage0 = mRecentsView.getScrollForPage(0);
+ mRecentsView.setScrollX((int) (mTransitionProgress.value * scrollForFirstTask
+ + (1 - mTransitionProgress.value) * scrollForPage0));
}
}
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 1576c4e..35c982c 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -21,7 +21,6 @@
import static android.view.MotionEvent.ACTION_POINTER_DOWN;
import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;
-
import static com.android.quickstep.TouchConsumer.INTERACTION_QUICK_SCRUB;
import static com.android.quickstep.TouchConsumer.INTERACTION_QUICK_SWITCH;
@@ -42,13 +41,15 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
+import android.view.ViewTreeObserver;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherState;
import com.android.launcher3.MainThreadExecutor;
-import com.android.launcher3.model.ModelPreload;
import com.android.launcher3.R;
+import com.android.launcher3.Workspace;
+import com.android.launcher3.model.ModelPreload;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -225,9 +226,6 @@
}
View target = launcher.getDragLayer();
- if (!target.getWindowId().isFocused()) {
- return mNoOpTouchConsumer;
- }
return new LauncherTouchConsumer(launcher, target);
}
@@ -253,6 +251,9 @@
@Override
public void accept(MotionEvent ev) {
+ if (!mTarget.getWindowId().isFocused()) {
+ return;
+ }
int action = ev.getActionMasked();
if (action == ACTION_DOWN) {
mTrackingStarted = false;
@@ -303,6 +304,12 @@
public void updateTouchTracking(int interactionType) {
mMainThreadExecutor.execute(() -> {
if (TouchConsumer.isInteractionQuick(interactionType)) {
+ if (mLauncher.getWorkspace().runOnOverlayHidden(
+ () -> updateTouchTracking(interactionType))) {
+ // Hide the minus one overlay so launcher can get window focus.
+ mLauncher.onQuickstepGestureStarted(true);
+ return;
+ }
Runnable onComplete = null;
if (interactionType == INTERACTION_QUICK_SCRUB) {
mQuickScrubController.onQuickScrubStart(true);
diff --git a/res/layout/all_apps_tabs.xml b/res/layout/all_apps_tabs.xml
index 54a9b88..2accd2d 100644
--- a/res/layout/all_apps_tabs.xml
+++ b/res/layout/all_apps_tabs.xml
@@ -14,21 +14,23 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<com.android.launcher3.allapps.InterceptingViewPager
+<com.android.launcher3.allapps.AllAppsPagedView
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto"
android:id="@+id/all_apps_tabs_view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/search_container_all_apps"
android:layout_gravity="center_horizontal|top"
android:layout_marginTop="@dimen/all_apps_header_tab_height"
- android:clipChildren="false"
+ android:clipChildren="true"
android:clipToPadding="false"
android:descendantFocusability="afterDescendants"
- android:paddingTop="@dimen/all_apps_header_top_padding">
+ android:paddingTop="@dimen/all_apps_header_top_padding"
+ launcher:pageIndicator="@+id/tabs" >
<include layout="@layout/all_apps_rv_layout" />
<include layout="@layout/all_apps_rv_layout" />
-</com.android.launcher3.allapps.InterceptingViewPager>
\ No newline at end of file
+</com.android.launcher3.allapps.AllAppsPagedView>
\ No newline at end of file
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 4d820bc..3fde58b 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1975,18 +1975,12 @@
return mAppLaunchSuccess;
}
- boolean isShortcut = Utilities.ATLEAST_MARSHMALLOW
- && (item instanceof ShortcutInfo)
- && (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
- || item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
- && !((ShortcutInfo) item).isPromise();
-
// Only launch using the new animation if the shortcut has not opted out (this is a
// private contract between launcher and may be ignored in the future).
boolean useLaunchAnimation = (v != null) &&
!intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
Bundle optsBundle = useLaunchAnimation
- ? getActivityLaunchOptions(v, isShortcut || isInMultiWindowModeCompat())
+ ? getActivityLaunchOptions(v, isInMultiWindowModeCompat())
: null;
UserHandle user = item == null ? null : item.user;
@@ -1997,6 +1991,11 @@
intent.setSourceBounds(getViewBounds(v));
}
try {
+ boolean isShortcut = Utilities.ATLEAST_MARSHMALLOW
+ && (item instanceof ShortcutInfo)
+ && (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
+ || item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
+ && !((ShortcutInfo) item).isPromise();
if (isShortcut) {
// Shortcuts need some special checks due to legacy reasons.
startShortcutIntentSafely(intent, optsBundle, item);
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index bb137b0..ccb0a95 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -59,7 +59,7 @@
* An abstraction of the original Workspace which supports browsing through a
* sequential list of "pages"
*/
-public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarchyChangeListener {
+public abstract class PagedView<T extends View & PageIndicator> extends ViewGroup {
private static final String TAG = "PagedView";
private static final boolean DEBUG = false;
protected static final int INVALID_PAGE = -1;
@@ -154,7 +154,7 @@
// Page Indicator
@Thunk int mPageIndicatorViewId;
- protected PageIndicator mPageIndicator;
+ protected T mPageIndicator;
// Reordering
// We use the min scale to determine how much to expand the actually PagedView measured
@@ -224,7 +224,6 @@
mFlingThresholdVelocity = (int) (FLING_THRESHOLD_VELOCITY * density);
mMinFlingVelocity = (int) (MIN_FLING_VELOCITY * density);
mMinSnapVelocity = (int) (MIN_SNAP_VELOCITY * density);
- setOnHierarchyChangeListener(this);
setWillNotDraw(false);
}
@@ -235,9 +234,9 @@
public void initParentViews(View parent) {
if (mPageIndicatorViewId > -1) {
- mPageIndicator = (PageIndicator) parent.findViewById(mPageIndicatorViewId);
+ mPageIndicator = parent.findViewById(mPageIndicatorViewId);
mPageIndicator.setMarkersCount(getChildCount());
- mPageIndicator.setContentDescription(getPageIndicatorDescription());
+ mPageIndicator.setPageDescription(getPageIndicatorDescription());
}
}
@@ -282,7 +281,7 @@
}
}
- public PageIndicator getPageIndicator() {
+ public T getPageIndicator() {
return mPageIndicator;
}
@@ -384,7 +383,7 @@
private void updatePageIndicator() {
// Update the page indicator (when we aren't reordering)
if (mPageIndicator != null) {
- mPageIndicator.setContentDescription(getPageIndicatorDescription());
+ mPageIndicator.setPageDescription(getPageIndicatorDescription());
if (!isReordering(false)) {
mPageIndicator.setActiveMarker(getNextPage());
}
@@ -748,63 +747,24 @@
requestLayout();
}
- @Override
- public void onChildViewAdded(View parent, View child) {
- // Update the page indicator, we don't update the page indicator as we
- // add/remove pages
- if (mPageIndicator != null && !isReordering(false)) {
- mPageIndicator.addMarker();
+ private void dispatchPageCountChanged() {
+ if (mPageIndicator != null) {
+ mPageIndicator.setMarkersCount(getChildCount());
}
-
// This ensures that when children are added, they get the correct transforms / alphas
// in accordance with any scroll effects.
invalidate();
}
@Override
- public void onChildViewRemoved(View parent, View child) {
+ public void onViewAdded(View child) {
+ dispatchPageCountChanged();
+ }
+
+ @Override
+ public void onViewRemoved(View child) {
mCurrentPage = validateNewPage(mCurrentPage);
- invalidate();
- }
-
- private void removeMarkerForView() {
- // Update the page indicator, we don't update the page indicator as we
- // add/remove pages
- if (mPageIndicator != null && !isReordering(false)) {
- mPageIndicator.removeMarker();
- }
- }
-
- @Override
- public void removeView(View v) {
- // XXX: We should find a better way to hook into this before the view
- // gets removed form its parent...
- removeMarkerForView();
- super.removeView(v);
- }
- @Override
- public void removeViewInLayout(View v) {
- // XXX: We should find a better way to hook into this before the view
- // gets removed form its parent...
- removeMarkerForView();
- super.removeViewInLayout(v);
- }
- @Override
- public void removeViewAt(int index) {
- // XXX: We should find a better way to hook into this before the view
- // gets removed form its parent...
- removeMarkerForView();
- super.removeViewAt(index);
- }
- @Override
- public void removeAllViewsInLayout() {
- // Update the page indicator, we don't update the page indicator as we
- // add/remove pages
- if (mPageIndicator != null) {
- mPageIndicator.setMarkersCount(0);
- }
-
- super.removeAllViewsInLayout();
+ dispatchPageCountChanged();
}
protected int getChildOffset(int index) {
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 2d24028..a4ca68a 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -52,6 +52,7 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
import android.widget.Toast;
import com.android.launcher3.Launcher.LauncherOverlay;
@@ -75,6 +76,7 @@
import com.android.launcher3.folder.PreviewBackground;
import com.android.launcher3.graphics.DragPreviewProvider;
import com.android.launcher3.graphics.PreloadIconDrawable;
+import com.android.launcher3.pageindicators.WorkspacePageIndicator;
import com.android.launcher3.popup.PopupContainerWithArrow;
import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
import com.android.launcher3.uioverrides.UiFactory;
@@ -100,10 +102,9 @@
* Each page contains a number of icons, folders or widgets the user can
* interact with. A workspace is meant to be used with a fixed width only.
*/
-public class Workspace extends PagedView
+public class Workspace extends PagedView<WorkspacePageIndicator>
implements DropTarget, DragSource, View.OnTouchListener,
- DragController.DragListener, ViewGroup.OnHierarchyChangeListener,
- Insettable, LauncherStateManager.StateHandler {
+ DragController.DragListener, Insettable, LauncherStateManager.StateHandler {
private static final String TAG = "Launcher.Workspace";
/** The value that {@link #mTransitionProgress} must be greater than for
@@ -235,6 +236,7 @@
boolean mStartedSendingScrollEvents;
float mLastOverlayScroll = 0;
boolean mOverlayShown = false;
+ private Runnable mOnOverlayHiddenCallback;
private boolean mForceDrawAdjacentPages = false;
private boolean mPageRearrangeEnabled = false;
@@ -273,9 +275,7 @@
mWallpaperOffset = new WallpaperOffsetInterpolator(this);
- setOnHierarchyChangeListener(this);
setHapticFeedbackEnabled(false);
-
initWorkspace();
// Disable multitouch across the workspace/all apps/customize tray
@@ -463,7 +463,7 @@
}
@Override
- public void onChildViewAdded(View parent, View child) {
+ public void onViewAdded(View child) {
if (!(child instanceof CellLayout)) {
throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
}
@@ -471,7 +471,7 @@
cl.setOnInterceptTouchListener(this);
cl.setClickable(true);
cl.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
- super.onChildViewAdded(parent, child);
+ super.onViewAdded(child);
}
boolean isTouchActive() {
@@ -1163,6 +1163,10 @@
if (mOverlayShown) {
mLauncher.getUserEventDispatcher().logActionOnContainer(Action.Touch.SWIPE,
Action.Direction.RIGHT, ContainerType.WORKSPACE, -1);
+ if (mOnOverlayHiddenCallback != null) {
+ mOnOverlayHiddenCallback.run();
+ mOnOverlayHiddenCallback = null;
+ }
}
mOverlayShown = false;
}
@@ -1188,6 +1192,59 @@
mLauncher.getDragLayer().setAlpha(alpha);
}
+ /**
+ * Runs the given callback when the minus one overlay is hidden. Specifically, it is run
+ * when launcher's window has focus and the overlay is no longer being shown. If a callback
+ * is already present, the new callback will chain off it so both are run.
+ *
+ * @return Whether the callback was deferred.
+ */
+ public boolean runOnOverlayHidden(Runnable callback) {
+ View rootView = getRootView();
+ if (rootView.hasWindowFocus()) {
+ if (mOverlayShown) {
+ chainOverlayHiddenCallback(callback);
+ return true;
+ } else {
+ callback.run();
+ return false;
+ }
+ }
+ ViewTreeObserver observer = rootView.getViewTreeObserver();
+ if (observer != null && observer.isAlive()) {
+ observer.addOnWindowFocusChangeListener(
+ new ViewTreeObserver.OnWindowFocusChangeListener() {
+ @Override
+ public void onWindowFocusChanged(boolean hasFocus) {
+ if (hasFocus) {
+ // Defer further if the minus one overlay is still showing.
+ if (mOverlayShown) {
+ chainOverlayHiddenCallback(callback);
+ } else {
+ callback.run();
+ }
+ observer.removeOnWindowFocusChangeListener(this);
+ }
+ }
+ });
+ return true;
+ }
+ return false;
+ }
+
+ private void chainOverlayHiddenCallback(Runnable callback) {
+ if (mOnOverlayHiddenCallback == null) {
+ mOnOverlayHiddenCallback = callback;
+ } else {
+ // Chain the new callback onto the previous callback(s).
+ Runnable oldCallback = mOnOverlayHiddenCallback;
+ mOnOverlayHiddenCallback = () -> {
+ oldCallback.run();
+ callback.run();
+ };
+ }
+ }
+
@Override
protected void notifyPageSwitchListener(int prevPage) {
super.notifyPageSwitchListener(prevPage);
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index d4277db..a7eae39 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -21,8 +21,6 @@
import android.os.Process;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
-import android.support.v4.view.PagerAdapter;
-import android.support.v4.view.ViewPager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.Selection;
@@ -50,7 +48,6 @@
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.PromiseAppInfo;
import com.android.launcher3.R;
import com.android.launcher3.anim.SpringAnimationHandler;
import com.android.launcher3.config.FeatureFlags;
@@ -59,12 +56,8 @@
import com.android.launcher3.keyboard.FocusedItemDecorator;
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
import com.android.launcher3.util.ItemInfoMatcher;
-import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.views.BottomUserEducationView;
-import java.util.List;
-import java.util.Set;
-
/**
* The all apps view container.
*/
@@ -80,9 +73,8 @@
private SearchUiManager mSearchUiManager;
private View mSearchContainer;
- private InterceptingViewPager mViewPager;
+ private AllAppsPagedView mViewPager;
private FloatingHeaderView mHeader;
- private TabsPagerAdapter mTabsPagerAdapter;
private SpannableStringBuilder mSearchQueryBuilder = null;
@@ -184,7 +176,7 @@
}
public AllAppsRecyclerView getActiveRecyclerView() {
- if (!mUsingTabs || mViewPager.getCurrentItem() == 0) {
+ if (!mUsingTabs || mViewPager.getNextPage() == 0) {
return mAH[AdapterHolder.MAIN].recyclerView;
} else {
return mAH[AdapterHolder.WORK].recyclerView;
@@ -329,9 +321,8 @@
if (mUsingTabs) {
mAH[AdapterHolder.MAIN].setup(mViewPager.getChildAt(0), mPersonalMatcher);
mAH[AdapterHolder.WORK].setup(mViewPager.getChildAt(1), mWorkMatcher);
- setupWorkProfileTabs();
+ onTabChanged(mViewPager.getNextPage());
} else {
- mTabsPagerAdapter = null;
mAH[AdapterHolder.MAIN].setup(findViewById(R.id.apps_list_view), null);
mAH[AdapterHolder.WORK].recyclerView = null;
}
@@ -355,50 +346,35 @@
int layout = showTabs ? R.layout.all_apps_tabs : R.layout.all_apps_rv_layout;
View newView = LayoutInflater.from(getContext()).inflate(layout, this, false);
addView(newView, index);
- mViewPager = showTabs ? (InterceptingViewPager) newView : null;
+ if (showTabs) {
+ mViewPager = (AllAppsPagedView) newView;
+ mViewPager.initParentViews(this);
+ mViewPager.getPageIndicator().setContainerView(this);
+ } else {
+ mViewPager = null;
+ }
}
public View getRecyclerViewContainer() {
return mViewPager != null ? mViewPager : findViewById(R.id.apps_list_view);
}
- private void setupWorkProfileTabs() {
- if (mTabsPagerAdapter != null) {
- return;
+ public void onTabChanged(int pos) {
+ mHeader.setMainActive(pos == 0);
+ reset();
+ applyTouchDelegate();
+ if (mAH[pos].recyclerView != null) {
+ mAH[pos].recyclerView.bindFastScrollbar();
+
+ findViewById(R.id.tab_personal)
+ .setOnClickListener((View view) -> mViewPager.snapToPage(AdapterHolder.MAIN));
+ findViewById(R.id.tab_work)
+ .setOnClickListener((View view) -> mViewPager.snapToPage(AdapterHolder.WORK));
+
}
- final PersonalWorkSlidingTabStrip tabs = findViewById(R.id.tabs);
- mViewPager.setAdapter(mTabsPagerAdapter = new TabsPagerAdapter());
- mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
-
- @Override
- public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
- tabs.updateIndicatorPosition(position, positionOffset);
- }
-
- @Override
- public void onPageSelected(int pos) {
- tabs.updateTabTextColor(pos);
- mHeader.setMainActive(pos == 0);
- reset();
- applyTouchDelegate();
- if (mAH[pos].recyclerView != null) {
- mAH[pos].recyclerView.bindFastScrollbar();
- }
- if (pos == AdapterHolder.WORK) {
- BottomUserEducationView.showIfNeeded(mLauncher);
- }
- }
-
- @Override
- public void onPageScrollStateChanged(int state) {
- }
- });
- mAH[AdapterHolder.MAIN].recyclerView.bindFastScrollbar();
-
- findViewById(R.id.tab_personal)
- .setOnClickListener((View view) -> mViewPager.setCurrentItem(0));
- findViewById(R.id.tab_work)
- .setOnClickListener((View view) -> mViewPager.setCurrentItem(1));
+ if (pos == AdapterHolder.WORK) {
+ BottomUserEducationView.showIfNeeded(mLauncher);
+ }
}
public AlphabeticalAppsList getApps() {
@@ -519,37 +495,4 @@
&& verticalFadingEdge);
}
}
-
- private class TabsPagerAdapter extends PagerAdapter {
- @Override
- public int getCount() {
- return 2;
- }
-
- @Override
- public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
- return view == object;
- }
-
- @NonNull
- @Override
- public Object instantiateItem(@NonNull ViewGroup container, int position) {
- if (position == 0) {
- return mAH[AdapterHolder.MAIN].recyclerView;
- } else {
- return mAH[AdapterHolder.WORK].recyclerView;
- }
- }
-
- @Nullable
- @Override
- public CharSequence getPageTitle(int position) {
- if (position == 0) {
- return getResources().getString(R.string.all_apps_personal_tab);
- } else {
- return getResources().getString(R.string.all_apps_work_tab);
- }
- }
- }
-
}
diff --git a/src/com/android/launcher3/allapps/AllAppsPagedView.java b/src/com/android/launcher3/allapps/AllAppsPagedView.java
new file mode 100644
index 0000000..86186fd
--- /dev/null
+++ b/src/com/android/launcher3/allapps/AllAppsPagedView.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.allapps;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+import com.android.launcher3.PagedView;
+import com.android.launcher3.R;
+
+public class AllAppsPagedView extends PagedView<PersonalWorkSlidingTabStrip> {
+
+ public AllAppsPagedView(Context context) {
+ this(context, null);
+ }
+
+ public AllAppsPagedView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public AllAppsPagedView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ protected String getCurrentPageDescription() {
+ return getResources().getString(
+ getNextPage() == 0 ? R.string.all_apps_personal_tab : R.string.all_apps_work_tab);
+ }
+
+ @Override
+ protected void onScrollChanged(int l, int t, int oldl, int oldt) {
+ super.onScrollChanged(l, t, oldl, oldt);
+ mPageIndicator.setScroll(l, mMaxScrollX);
+ }
+}
diff --git a/src/com/android/launcher3/allapps/InterceptingViewPager.java b/src/com/android/launcher3/allapps/InterceptingViewPager.java
deleted file mode 100644
index 3524ca9..0000000
--- a/src/com/android/launcher3/allapps/InterceptingViewPager.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.allapps;
-
-import android.content.Context;
-import android.graphics.PointF;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.view.ViewPager;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.ViewConfiguration;
-
-import com.android.launcher3.touch.SwipeDetector;
-
-import static android.view.MotionEvent.INVALID_POINTER_ID;
-
-
-public class InterceptingViewPager extends ViewPager {
-
-
- private final PointF mDownPos = new PointF();
- private final PointF mLastPos = new PointF();
- private final int mSlop;
- private int mActivePointerId = INVALID_POINTER_ID;
-
- public InterceptingViewPager(@NonNull Context context) {
- super(context);
- mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
- }
-
- public InterceptingViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
- super(context, attrs);
- mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- boolean result = super.onInterceptTouchEvent(ev);
- if (!result) {
- switch (ev.getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
- mActivePointerId = ev.getPointerId(0);
- mDownPos.set(ev.getX(), ev.getY());
- mLastPos.set(mDownPos);
- break;
- case MotionEvent.ACTION_POINTER_UP:
- int ptrIdx = ev.getActionIndex();
- int ptrId = ev.getPointerId(ptrIdx);
- if (ptrId == mActivePointerId) {
- final int newPointerIdx = ptrIdx == 0 ? 1 : 0;
- mDownPos.set(
- ev.getX(newPointerIdx) - (mLastPos.x - mDownPos.x),
- ev.getY(newPointerIdx) - (mLastPos.y - mDownPos.y));
- mLastPos.set(ev.getX(newPointerIdx), ev.getY(newPointerIdx));
- mActivePointerId = ev.getPointerId(newPointerIdx);
- }
- break;
- case MotionEvent.ACTION_MOVE:
- int pointerIndex = ev.findPointerIndex(mActivePointerId);
- if (pointerIndex == INVALID_POINTER_ID) {
- break;
- }
- float deltaX = ev.getX() - mDownPos.x;
- float deltaY = ev.getY() - mDownPos.y;
- if (Math.abs(deltaX) > mSlop && Math.abs(deltaX) > Math.abs(deltaY)) {
- return true;
- }
- mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
- break;
- default:
- break;
- }
- }
- return result;
- }
-
-}
\ No newline at end of file
diff --git a/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java b/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java
index 05cd655..b42d4cd 100644
--- a/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java
+++ b/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java
@@ -28,13 +28,13 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
+import com.android.launcher3.pageindicators.PageIndicator;
import com.android.launcher3.util.Themes;
/**
* Supports two indicator colors, dedicated for personal and work tabs.
*/
-public class PersonalWorkSlidingTabStrip extends LinearLayout {
+public class PersonalWorkSlidingTabStrip extends LinearLayout implements PageIndicator {
private static final int POSITION_PERSONAL = 0;
private static final int POSITION_WORK = 1;
@@ -51,6 +51,9 @@
private float mIndicatorOffset;
private int mSelectedPosition = 0;
+ private AllAppsContainerView mContainerView;
+ private int mLastActivePage = 0;
+
public PersonalWorkSlidingTabStrip(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
setOrientation(HORIZONTAL);
@@ -71,13 +74,13 @@
mSharedPreferences = Launcher.getLauncher(getContext()).getSharedPrefs();
}
- public void updateIndicatorPosition(int position, float positionOffset) {
+ private void updateIndicatorPosition(int position, float positionOffset) {
mIndicatorPosition = position;
mIndicatorOffset = positionOffset;
updateIndicatorPosition();
}
- public void updateTabTextColor(int pos) {
+ private void updateTabTextColor(int pos) {
mSelectedPosition = pos;
for (int i = 0; i < getChildCount(); i++) {
Button tab = (Button) getChildAt(i);
@@ -129,8 +132,6 @@
float y = getHeight() - mDividerPaint.getStrokeWidth();
canvas.drawLine(getPaddingLeft(), y, getWidth() - getPaddingRight(), y, mDividerPaint);
-
- final float middleX = getWidth() / 2.0f;
canvas.drawRect(mIndicatorLeft, getHeight() - mSelectedIndicatorHeight,
mIndicatorRight, getHeight(), mSelectedIndicatorPaint);
}
@@ -153,4 +154,35 @@
v.setPressed(false);
});
}
+
+ @Override
+ public void setScroll(int currentScroll, int totalScroll) {
+ if (currentScroll == totalScroll) {
+ updateIndicatorPosition(1, 0);
+ } else if (totalScroll > 0) {
+ updateIndicatorPosition(0, ((float) currentScroll) / totalScroll);
+ }
+ }
+
+ @Override
+ public void setActiveMarker(int activePage) {
+ updateTabTextColor(activePage);
+ if (mContainerView != null && mLastActivePage != activePage) {
+ mContainerView.onTabChanged(activePage);
+ }
+ mLastActivePage = activePage;
+ }
+
+ public void setContainerView(AllAppsContainerView containerView) {
+ mContainerView = containerView;
+ }
+
+ @Override
+ public void setMarkersCount(int numMarkers) { }
+
+ @Override
+ public void setPageDescription(CharSequence description) {
+ // We don't want custom page description as the tab-bar already has two tabs with their
+ // own descriptions.
+ }
}
diff --git a/src/com/android/launcher3/folder/FolderPagedView.java b/src/com/android/launcher3/folder/FolderPagedView.java
index f4462aa..a468cb5 100644
--- a/src/com/android/launcher3/folder/FolderPagedView.java
+++ b/src/com/android/launcher3/folder/FolderPagedView.java
@@ -44,14 +44,14 @@
import com.android.launcher3.Workspace.ItemOperator;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
-import com.android.launcher3.pageindicators.PageIndicator;
+import com.android.launcher3.pageindicators.PageIndicatorDots;
import com.android.launcher3.util.Thunk;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
-public class FolderPagedView extends PagedView {
+public class FolderPagedView extends PagedView<PageIndicatorDots> {
private static final String TAG = "FolderPagedView";
@@ -89,8 +89,6 @@
private Folder mFolder;
private PagedFolderKeyEventListener mKeyListener;
- private PageIndicator mPageIndicator;
-
public FolderPagedView(Context context, AttributeSet attrs) {
super(context, attrs);
InvariantDeviceProfile profile = LauncherAppState.getIDP(context);
diff --git a/src/com/android/launcher3/pageindicators/PageIndicator.java b/src/com/android/launcher3/pageindicators/PageIndicator.java
index 5e3d216..3ce7291 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicator.java
@@ -15,41 +15,16 @@
*/
package com.android.launcher3.pageindicators;
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-
/**
* Base class for a page indicator.
*/
-public abstract class PageIndicator extends View {
+public interface PageIndicator {
- protected int mNumPages = 1;
+ void setScroll(int currentScroll, int totalScroll);
- public PageIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
+ void setActiveMarker(int activePage);
- public void setScroll(int currentScroll, int totalScroll) {}
+ void setMarkersCount(int numMarkers);
- public void setActiveMarker(int activePage) {}
-
- public void addMarker() {
- mNumPages++;
- onPageCountChanged();
- }
-
- public void removeMarker() {
- mNumPages--;
- onPageCountChanged();
- }
-
- public void setMarkersCount(int numMarkers) {
- mNumPages = numMarkers;
- onPageCountChanged();
- }
-
- protected void onPageCountChanged() {}
-
- public void setShouldAutoHide(boolean shouldAutoHide) {}
+ void setPageDescription(CharSequence description);
}
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
index 6276c80..524ec3c 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
@@ -43,7 +43,7 @@
* {@link PageIndicator} which shows dots per page. The active page is shown with the current
* accent color.
*/
-public class PageIndicatorDots extends PageIndicator {
+public class PageIndicatorDots extends View implements PageIndicator {
private static final float SHIFT_PER_ANIMATION = 0.5f;
private static final float SHIFT_THRESHOLD = 0.1f;
@@ -79,6 +79,7 @@
private final int mInActiveColor;
private final boolean mIsRtl;
+ private int mNumPages;
private int mActivePage;
/**
@@ -221,11 +222,17 @@
}
@Override
- protected void onPageCountChanged() {
+ public void setMarkersCount(int numMarkers) {
+ mNumPages = numMarkers;
requestLayout();
}
@Override
+ public void setPageDescription(CharSequence description) {
+ setContentDescription(description);
+ }
+
+ @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Add extra spacing of mDotRadius on all sides so than entry animation could be run.
int width = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY ?
diff --git a/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java b/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
index ee4e4ee..4fc7d8a 100644
--- a/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
@@ -41,7 +41,8 @@
*
* The fraction is 1 / number of pages and the position is based on the progress of the page scroll.
*/
-public class WorkspacePageIndicator extends PageIndicator implements Insettable, OnClickListener {
+public class WorkspacePageIndicator extends View
+ implements Insettable, OnClickListener, PageIndicator {
private static final int LINE_ANIMATE_DURATION = ViewConfiguration.getScrollBarFadeDuration();
private static final int LINE_FADE_DELAY = ViewConfiguration.getScrollDefaultDelay();
@@ -185,14 +186,18 @@
}
@Override
- public void setActiveMarker(int activePage) {
+ public void setActiveMarker(int activePage) { }
+
+ @Override
+ public void setMarkersCount(int numMarkers) {
+ if (Float.compare(numMarkers, mNumPagesFloat) != 0) {
+ animateToNumPages(numMarkers);
+ }
}
@Override
- protected void onPageCountChanged() {
- if (Float.compare(mNumPages, mNumPagesFloat) != 0) {
- animateToNumPages(mNumPages);
- }
+ public void setPageDescription(CharSequence description) {
+ setContentDescription(description);
}
public void setShouldAutoHide(boolean shouldAutoHide) {