Moving clear all button inside the recents view
Bug: 72222505
Bug: 109828536
Change-Id: I843b79db3e47abc2c41ed78f186b9c941941ddef
diff --git a/quickstep/res/layout/fallback_recents_activity.xml b/quickstep/res/layout/fallback_recents_activity.xml
index 84e13ad..ef272ed 100644
--- a/quickstep/res/layout/fallback_recents_activity.xml
+++ b/quickstep/res/layout/fallback_recents_activity.xml
@@ -20,25 +20,12 @@
android:layout_height="match_parent"
android:fitsSystemWindows="true">
- <com.android.quickstep.views.RecentsViewContainer
- android:id="@+id/overview_panel_container"
+ <com.android.quickstep.fallback.FallbackRecentsView
+ android:id="@id/overview_panel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
- >
- <include layout="@layout/overview_clear_all_button"/>
-
- <com.android.quickstep.fallback.FallbackRecentsView
- android:id="@id/overview_panel"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:outlineProvider="none"
- android:focusableInTouchMode="true"
- android:theme="@style/HomeScreenElementTheme"
- >
-
- </com.android.quickstep.fallback.FallbackRecentsView>
- </com.android.quickstep.views.RecentsViewContainer>
+ android:clipToPadding="false"
+ android:outlineProvider="none"
+ android:theme="@style/HomeScreenElementTheme" />
</com.android.quickstep.fallback.RecentsRootView>
diff --git a/quickstep/res/layout/overview_clear_all_button.xml b/quickstep/res/layout/overview_clear_all_button.xml
index 25615e0..ea7a494 100644
--- a/quickstep/res/layout/overview_clear_all_button.xml
+++ b/quickstep/res/layout/overview_clear_all_button.xml
@@ -1,15 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
<com.android.quickstep.views.ClearAllButton
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/clear_all_button"
style="@android:style/Widget.DeviceDefault.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="start|top"
android:text="@string/recents_clear_all"
android:textColor="?attr/workspaceTextColor"
- android:visibility="invisible"
android:textSize="14sp"
- android:importantForAccessibility="no"
-/>
\ No newline at end of file
+ android:translationY="@dimen/task_thumbnail_half_top_margin"
+ />
\ No newline at end of file
diff --git a/quickstep/res/layout/overview_panel.xml b/quickstep/res/layout/overview_panel.xml
index 840b040..7f1425b 100644
--- a/quickstep/res/layout/overview_panel.xml
+++ b/quickstep/res/layout/overview_panel.xml
@@ -14,26 +14,12 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<com.android.quickstep.views.RecentsViewContainer
+<com.android.quickstep.views.LauncherRecentsView
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:theme="@style/HomeScreenElementTheme"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
- android:visibility="invisible"
->
- <include layout="@layout/overview_clear_all_button"/>
-
- <com.android.quickstep.views.LauncherRecentsView
- android:id="@id/overview_panel"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:outlineProvider="none"
- android:focusableInTouchMode="true"
- android:accessibilityPaneTitle="@string/accessibility_recent_apps"
- android:theme="@style/HomeScreenElementTheme"
- >
-
- </com.android.quickstep.views.LauncherRecentsView>
-</com.android.quickstep.views.RecentsViewContainer>
\ No newline at end of file
+ android:clipToPadding="false"
+ android:accessibilityPaneTitle="@string/accessibility_recent_apps"
+ android:visibility="invisible" />
\ No newline at end of file
diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml
index f163872..36d327d 100644
--- a/quickstep/res/layout/task.xml
+++ b/quickstep/res/layout/task.xml
@@ -17,8 +17,9 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:focusable="false"
- android:elevation="4dp">
+ android:defaultFocusHighlightEnabled="false"
+ android:elevation="4dp"
+ android:focusable="true">
<com.android.quickstep.views.TaskThumbnailView
android:id="@+id/snapshot"
@@ -30,7 +31,7 @@
android:id="@+id/icon"
android:layout_width="@dimen/task_thumbnail_icon_size"
android:layout_height="@dimen/task_thumbnail_icon_size"
- android:importantForAccessibility="no"
+ android:layout_gravity="top|center_horizontal"
android:focusable="false"
- android:layout_gravity="top|center_horizontal" />
+ android:importantForAccessibility="no" />
</com.android.quickstep.views.TaskView>
\ No newline at end of file
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index ea7d21b..afaad38 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -17,6 +17,7 @@
<resources>
<dimen name="task_thumbnail_top_margin">24dp</dimen>
+ <dimen name="task_thumbnail_half_top_margin">12dp</dimen>
<dimen name="task_thumbnail_icon_size">48dp</dimen>
<dimen name="task_corner_radius">2dp</dimen>
<dimen name="recents_page_spacing">10dp</dimen>
@@ -50,9 +51,6 @@
docked_stack_divider_thickness - 2 * docked_stack_divider_insets -->
<dimen name="multi_window_task_divider_size">10dp</dimen>
- <!-- Width of the space behind the last task in Overview. In the center of it, there is "Clear all" button. -->
- <dimen name="clear_all_container_width">168dp</dimen>
-
<dimen name="shelf_surface_radius">16dp</dimen>
<!-- same as vertical_drag_handle_size -->
<dimen name="shelf_surface_offset">24dp</dimen>
diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
index 72d6260..6ee4cdb 100644
--- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
@@ -369,8 +369,9 @@
launcherAnimator.play(ObjectAnimator.ofFloat(allAppsController, ALL_APPS_PROGRESS,
allAppsController.getProgress(), ALL_APPS_PROGRESS_OFF_SCREEN));
- View overview = mLauncher.getOverviewPanelContainer();
- ObjectAnimator alpha = ObjectAnimator.ofFloat(overview, View.ALPHA, alphas);
+ RecentsView overview = mLauncher.getOverviewPanel();
+ ObjectAnimator alpha = ObjectAnimator.ofFloat(overview,
+ RecentsView.CONTENT_ALPHA, alphas);
alpha.setDuration(217);
alpha.setInterpolator(LINEAR);
launcherAnimator.play(alpha);
@@ -380,14 +381,7 @@
transY.setDuration(350);
launcherAnimator.play(transY);
- overview.setLayerType(View.LAYER_TYPE_HARDWARE, null);
-
- endListener = () -> {
- overview.setLayerType(View.LAYER_TYPE_NONE, null);
- overview.setAlpha(1f);
- overview.setTranslationY(0f);
- mLauncher.getStateManager().reapplyState();
- };
+ endListener = mLauncher.getStateManager()::reapplyState;
} else {
mDragLayerAlpha.setValue(alphas[0]);
ObjectAnimator alpha =
diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
index 9169ffb..1e10319 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
@@ -25,6 +25,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
+import com.android.launcher3.R;
import com.android.launcher3.Workspace;
import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -118,6 +119,11 @@
/ launcher.getAllAppsController().getShiftRange());
}
+ @Override
+ public String getDescription(Launcher launcher) {
+ return launcher.getString(R.string.accessibility_desc_recent_apps);
+ }
+
public static float getDefaultSwipeHeight(Launcher launcher) {
DeviceProfile dp = launcher.getDeviceProfile();
return dp.allAppsCellHeightPx - dp.allAppsIconTextSizePx;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
index 717179d..512d19a 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
@@ -139,7 +139,7 @@
cancelPendingAnim();
RecentsView recentsView = mLauncher.getOverviewPanel();
- TaskView taskView = (TaskView) recentsView.getChildAt(recentsView.getNextPage());
+ TaskView taskView = recentsView.getTaskViewAt(recentsView.getNextPage());
if (recentsView.shouldSwipeDownLaunchApp() && mFromState == OVERVIEW && mToState == NORMAL
&& taskView != null) {
// Reset the state manager, when changing the interaction mode
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index ea27eb2..abd2846 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -25,7 +25,7 @@
import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_START_INTERPOLATOR;
import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_TRANSLATION_Y_FACTOR;
import static com.android.quickstep.views.LauncherRecentsView.TRANSLATION_Y_FACTOR;
-import static com.android.quickstep.views.RecentsViewContainer.CONTENT_ALPHA;
+import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
@@ -40,24 +40,21 @@
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PropertySetter;
import com.android.quickstep.views.LauncherRecentsView;
-import com.android.quickstep.views.RecentsViewContainer;
@TargetApi(Build.VERSION_CODES.O)
public class RecentsViewStateController implements StateHandler {
private final Launcher mLauncher;
private final LauncherRecentsView mRecentsView;
- private final RecentsViewContainer mRecentsViewContainer;
public RecentsViewStateController(Launcher launcher) {
mLauncher = launcher;
mRecentsView = launcher.getOverviewPanel();
- mRecentsViewContainer = launcher.getOverviewPanelContainer();
}
@Override
public void setState(LauncherState state) {
- mRecentsViewContainer.setContentAlpha(state.overviewUi ? 1 : 0);
+ mRecentsView.setContentAlpha(state.overviewUi ? 1 : 0);
float[] scaleTranslationYFactor = state.getOverviewScaleAndTranslationYFactor(mLauncher);
SCALE_PROPERTY.set(mRecentsView, scaleTranslationYFactor[0]);
mRecentsView.setTranslationYFactor(scaleTranslationYFactor[1]);
@@ -86,7 +83,7 @@
scaleAndTransYInterpolator);
setter.setFloat(mRecentsView, TRANSLATION_Y_FACTOR, scaleTranslationYFactor[1],
scaleAndTransYInterpolator);
- setter.setFloat(mRecentsViewContainer, CONTENT_ALPHA, toState.overviewUi ? 1 : 0,
+ setter.setFloat(mRecentsView, CONTENT_ALPHA, toState.overviewUi ? 1 : 0,
builder.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
if (!toState.overviewUi) {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
index a405735..ba15ebe 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
@@ -115,8 +115,8 @@
} else {
mTaskBeingDragged = null;
- for (int i = 0; i < mRecentsView.getChildCount(); i++) {
- TaskView view = mRecentsView.getPageAt(i);
+ for (int i = 0; i < mRecentsView.getTaskViewCount(); i++) {
+ TaskView view = mRecentsView.getTaskViewAt(i);
if (mRecentsView.isTaskViewVisible(view) && mActivity.getDragLayer()
.isEventOverView(view, ev)) {
mTaskBeingDragged = view;
diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
index 8e4270e..3197532 100644
--- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java
+++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
@@ -25,6 +25,7 @@
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.quickstep.TouchConsumer.INTERACTION_NORMAL;
import static com.android.quickstep.TouchConsumer.INTERACTION_QUICK_SCRUB;
+import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_BACK;
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_ROTATION;
@@ -67,7 +68,6 @@
import com.android.quickstep.util.TransformedRect;
import com.android.quickstep.views.LauncherLayoutListener;
import com.android.quickstep.views.RecentsView;
-import com.android.quickstep.views.RecentsViewContainer;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -293,7 +293,7 @@
*/
private void playScaleDownAnim(AnimatorSet anim, Launcher launcher) {
RecentsView recentsView = launcher.getOverviewPanel();
- TaskView v = recentsView.getPageAt(recentsView.getCurrentPage());
+ TaskView v = recentsView.getTaskViewAt(recentsView.getCurrentPage());
ClipAnimationHelper clipHelper = new ClipAnimationHelper();
clipHelper.fromTaskThumbnailView(v.getThumbnail(), (RecentsView) v.getParent(), null);
if (!clipHelper.getSourceRect().isEmpty() && !clipHelper.getTargetRect().isEmpty()) {
@@ -466,7 +466,7 @@
return (transitionLength, interactionType) -> { };
}
- RecentsViewContainer rv = activity.getOverviewPanelContainer();
+ RecentsView rv = activity.getOverviewPanel();
rv.setContentAlpha(0);
return new AnimationFactory() {
@@ -490,8 +490,7 @@
return;
}
- ObjectAnimator anim = ObjectAnimator
- .ofFloat(rv, RecentsViewContainer.CONTENT_ALPHA, 0, 1);
+ ObjectAnimator anim = ObjectAnimator.ofFloat(rv, CONTENT_ALPHA, 0, 1);
anim.setDuration(transitionLength).setInterpolator(LINEAR);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(anim);
diff --git a/quickstep/src/com/android/quickstep/QuickScrubController.java b/quickstep/src/com/android/quickstep/QuickScrubController.java
index e0089c6..cbc7a67 100644
--- a/quickstep/src/com/android/quickstep/QuickScrubController.java
+++ b/quickstep/src/com/android/quickstep/QuickScrubController.java
@@ -98,7 +98,7 @@
}
int page = mRecentsView.getNextPage();
Runnable launchTaskRunnable = () -> {
- TaskView taskView = mRecentsView.getPageAt(page);
+ TaskView taskView = mRecentsView.getTaskViewAt(page);
if (taskView != null) {
mWaitingForTaskLaunch = true;
taskView.launchTask(true, (result) -> {
@@ -222,7 +222,7 @@
private void goToPageWithHaptic(int pageToGoTo, int overrideDuration, boolean forceHaptic,
Interpolator interpolator) {
- pageToGoTo = Utilities.boundToRange(pageToGoTo, 0, mRecentsView.getPageCount() - 1);
+ pageToGoTo = Utilities.boundToRange(pageToGoTo, 0, mRecentsView.getTaskViewCount() - 1);
boolean snappingToPage = pageToGoTo != mRecentsView.getNextPage();
if (snappingToPage) {
int duration = overrideDuration > -1 ? overrideDuration
@@ -246,7 +246,7 @@
return;
}
if (mQuickScrubSection == QUICK_SCRUB_THRESHOLDS.length
- && currPage < mRecentsView.getPageCount() - 1) {
+ && currPage < mRecentsView.getTaskViewCount() - 1) {
goToPageWithHaptic(currPage + 1);
} else if (mQuickScrubSection == 0 && currPage > 0) {
goToPageWithHaptic(currPage - 1);
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index 3adb290..a5fbba7 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -52,7 +52,6 @@
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.fallback.RecentsRootView;
import com.android.quickstep.util.ClipAnimationHelper;
-import com.android.quickstep.views.RecentsViewContainer;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
@@ -70,7 +69,6 @@
private Handler mUiHandler = new Handler(Looper.getMainLooper());
private RecentsRootView mRecentsRootView;
private FallbackRecentsView mFallbackRecentsView;
- private RecentsViewContainer mOverviewPanelContainer;
private Configuration mOldConfig;
@@ -84,7 +82,6 @@
setContentView(R.layout.fallback_recents_activity);
mRecentsRootView = findViewById(R.id.drag_layer);
mFallbackRecentsView = findViewById(R.id.overview_panel);
- mOverviewPanelContainer = findViewById(R.id.overview_panel_container);
mRecentsRootView.setup();
@@ -166,10 +163,6 @@
return (T) mFallbackRecentsView;
}
- public RecentsViewContainer getOverviewPanelContainer() {
- return mOverviewPanelContainer;
- }
-
@Override
public BadgeInfo getBadgeInfoForItem(ItemInfo info) {
return null;
diff --git a/quickstep/src/com/android/quickstep/TaskUtils.java b/quickstep/src/com/android/quickstep/TaskUtils.java
index c9ba7dc..f9b5e30 100644
--- a/quickstep/src/com/android/quickstep/TaskUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskUtils.java
@@ -104,8 +104,8 @@
ComponentName componentName = itemInfo.getTargetComponent();
int userId = itemInfo.user.getIdentifier();
if (componentName != null) {
- for (int i = 0; i < recentsView.getChildCount(); i++) {
- TaskView taskView = recentsView.getPageAt(i);
+ for (int i = 0; i < recentsView.getTaskViewCount(); i++) {
+ TaskView taskView = recentsView.getTaskViewAt(i);
if (recentsView.isTaskViewVisible(taskView)) {
Task.TaskKey key = taskView.getTask().key;
if (componentName.equals(key.getComponent()) && userId == key.userId) {
diff --git a/quickstep/src/com/android/quickstep/views/ClearAllButton.java b/quickstep/src/com/android/quickstep/views/ClearAllButton.java
index 0025df1..3911931 100644
--- a/quickstep/src/com/android/quickstep/views/ClearAllButton.java
+++ b/quickstep/src/com/android/quickstep/views/ClearAllButton.java
@@ -17,34 +17,57 @@
package com.android.quickstep.views;
import android.content.Context;
-import android.graphics.Rect;
-import android.support.annotation.Nullable;
import android.util.AttributeSet;
-import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Button;
-public class ClearAllButton extends Button {
- RecentsView mRecentsView;
+import com.android.launcher3.Utilities;
+import com.android.quickstep.views.RecentsView.PageCallbacks;
+import com.android.quickstep.views.RecentsView.ScrollState;
- public ClearAllButton(Context context, @Nullable AttributeSet attrs) {
+public class ClearAllButton extends Button implements PageCallbacks {
+
+ private float mScrollAlpha = 1;
+ private float mContentAlpha = 1;
+
+ private final boolean mIsRtl;
+
+ private int mScrollOffset;
+
+ public ClearAllButton(Context context, AttributeSet attrs) {
super(context, attrs);
- }
-
- public void setRecentsView(RecentsView recentsView) {
- mRecentsView = recentsView;
+ mIsRtl = Utilities.isRtl(context.getResources());
}
@Override
- public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
- super.onInitializeAccessibilityNodeInfo(info);
- info.setParent(mRecentsView); // Pretend we are a part of the task carousel.
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+
+ RecentsView parent = (RecentsView) getParent();
+ mScrollOffset = mIsRtl ? parent.getPaddingRight() / 2 : - parent.getPaddingLeft() / 2;
}
@Override
- protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
- super.onFocusChanged(focused, direction, previouslyFocusedRect);
- if (focused) {
- mRecentsView.revealClearAllButton();
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
+
+ public void setContentAlpha(float alpha) {
+ if (mContentAlpha != alpha) {
+ mContentAlpha = alpha;
+ setAlpha(mScrollAlpha * mContentAlpha);
}
}
+
+ @Override
+ public void onPageScroll(ScrollState scrollState) {
+ float width = getWidth();
+ if (width == 0) {
+ return;
+ }
+
+ float shift = Math.min(scrollState.scrollFromEdge, width);
+ setTranslationX(mIsRtl ? (mScrollOffset - shift) : (mScrollOffset + shift));
+ mScrollAlpha = 1 - shift / width;
+ setAlpha(mScrollAlpha * mContentAlpha);
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 1e3db96..ee97c06 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -40,7 +40,6 @@
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
-import android.os.Bundle;
import android.os.Handler;
import android.os.UserHandle;
import android.support.annotation.Nullable;
@@ -49,6 +48,7 @@
import android.text.TextPaint;
import android.util.ArraySet;
import android.util.AttributeSet;
+import android.util.FloatProperty;
import android.util.SparseBooleanArray;
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
@@ -90,7 +90,6 @@
import com.android.systemui.shared.system.TaskStackChangeListener;
import java.util.ArrayList;
-import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
/**
@@ -101,6 +100,19 @@
private static final String TAG = RecentsView.class.getSimpleName();
+ public static final FloatProperty<RecentsView> CONTENT_ALPHA =
+ new FloatProperty<RecentsView>("contentAlpha") {
+ @Override
+ public void setValue(RecentsView view, float v) {
+ view.setContentAlpha(v);
+ }
+
+ @Override
+ public Float get(RecentsView view) {
+ return view.getContentAlpha();
+ }
+ };
+
private final Rect mTempRect = new Rect();
private static final int DISMISS_TASK_DURATION = 300;
@@ -114,13 +126,12 @@
private final float mFastFlingVelocity;
private final RecentsModel mModel;
private final int mTaskTopMargin;
+ private final ClearAllButton mClearAllButton;
private final ScrollState mScrollState = new ScrollState();
// Keeps track of the previously known visible tasks for purposes of loading/unloading task data
private final SparseBooleanArray mHasVisibleTaskData = new SparseBooleanArray();
- private boolean mIsClearAllButtonFullyRevealed;
-
/**
* TODO: Call reloadIdNeeded in onTaskStackChanged.
*/
@@ -228,8 +239,6 @@
// Keeps track of task views whose visual state should not be reset
private ArraySet<TaskView> mIgnoreResetTaskViews = new ArraySet<>();
- private View mClearAllButton;
-
// Variables for empty state
private final Drawable mEmptyIcon;
private final CharSequence mEmptyMessage;
@@ -259,6 +268,10 @@
mQuickScrubController = new QuickScrubController(mActivity, this);
mModel = RecentsModel.getInstance(context);
+ mClearAllButton = (ClearAllButton) LayoutInflater.from(context)
+ .inflate(R.layout.overview_clear_all_button, this, false);
+ mClearAllButton.setOnClickListener(this::dismissAllTasks);
+
mIsRtl = !Utilities.isRtl(getResources());
setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
mTaskTopMargin = getResources()
@@ -275,7 +288,6 @@
.getDimensionPixelSize(R.dimen.recents_empty_message_text_padding);
setWillNotDraw(false);
updateEmptyMessage();
- setFocusable(false);
}
public boolean isRtl() {
@@ -317,14 +329,15 @@
super.onViewRemoved(child);
// Clear the task data for the removed child if it was visible
- Task task = ((TaskView) child).getTask();
- if (mHasVisibleTaskData.get(task.key.id)) {
- mHasVisibleTaskData.delete(task.key.id);
- RecentsTaskLoader loader = mModel.getRecentsTaskLoader();
- loader.unloadTaskData(task);
- loader.getHighResThumbnailLoader().onTaskInvisible(task);
+ if (child != mClearAllButton) {
+ Task task = ((TaskView) child).getTask();
+ if (mHasVisibleTaskData.get(task.key.id)) {
+ mHasVisibleTaskData.delete(task.key.id);
+ RecentsTaskLoader loader = mModel.getRecentsTaskLoader();
+ loader.unloadTaskData(task);
+ loader.getHighResThumbnailLoader().onTaskInvisible(task);
+ }
}
- onChildViewsChanged();
}
public boolean isTaskViewVisible(TaskView tv) {
@@ -333,7 +346,7 @@
}
public TaskView getTaskView(int taskId) {
- for (int i = 0; i < getChildCount(); i++) {
+ for (int i = 0; i < getTaskViewCount(); i++) {
TaskView tv = (TaskView) getChildAt(i);
if (tv.getTask().key.id == taskId) {
return tv;
@@ -363,75 +376,14 @@
}
}
- private int getScrollEnd() {
- return mIsRtl ? 0 : mMaxScrollX;
- }
-
- private float calculateClearAllButtonAlpha() {
- final int childCount = getChildCount();
- if (mShowEmptyMessage || childCount == 0 || mPageScrolls == null
- || childCount != mPageScrolls.length) {
- return 0;
- }
-
- final int scrollEnd = getScrollEnd();
- final int oldestChildScroll = getScrollForPage(childCount - 1);
-
- final int clearAllButtonMotionRange = scrollEnd - oldestChildScroll;
- if (clearAllButtonMotionRange == 0) return 0;
-
- final float alphaUnbound = ((float) (getScrollX() - oldestChildScroll)) /
- clearAllButtonMotionRange;
- if (alphaUnbound > 1) return 0;
-
- return Math.max(alphaUnbound, 0);
- }
-
- private void updateClearAllButtonAlpha() {
- if (mClearAllButton != null) {
- final float alpha = calculateClearAllButtonAlpha();
- final boolean revealed = alpha == 1;
- if (mIsClearAllButtonFullyRevealed != revealed) {
- mIsClearAllButtonFullyRevealed = revealed;
- mClearAllButton.setImportantForAccessibility(revealed ?
- IMPORTANT_FOR_ACCESSIBILITY_YES :
- IMPORTANT_FOR_ACCESSIBILITY_NO);
- }
- mClearAllButton.setAlpha(alpha * mContentAlpha);
- }
- }
-
- @Override
- protected void onScrollChanged(int l, int t, int oldl, int oldt) {
- super.onScrollChanged(l, t, oldl, oldt);
- updateClearAllButtonAlpha();
- }
-
- @Override
- protected void restoreScrollOnLayout() {
- if (mIsClearAllButtonFullyRevealed) {
- scrollAndForceFinish(getScrollEnd());
- } else {
- super.restoreScrollOnLayout();
- }
- }
-
@Override
public boolean onTouchEvent(MotionEvent ev) {
- if (ev.getAction() == MotionEvent.ACTION_DOWN && mTouchState == TOUCH_STATE_REST
- && mScroller.isFinished() && mIsClearAllButtonFullyRevealed) {
- mClearAllButton.getHitRect(mTempRect);
- mTempRect.offset(-getLeft(), -getTop());
- if (mTempRect.contains((int) ev.getX(), (int) ev.getY())) {
- // If nothing is in motion, let the Clear All button process the event.
- return false;
- }
- }
-
+ super.onTouchEvent(ev);
if (ev.getAction() == MotionEvent.ACTION_UP && mShowEmptyMessage) {
onAllTasksRemoved();
}
- return super.onTouchEvent(ev);
+ // Do not let touch escape to siblings below this view.
+ return true;
}
private void applyLoadPlan(RecentsTaskLoadPlan loadPlan) {
@@ -453,22 +405,30 @@
final LayoutInflater inflater = LayoutInflater.from(getContext());
final ArrayList<Task> tasks = new ArrayList<>(stack.getTasks());
- final int requiredChildCount = tasks.size();
- for (int i = getChildCount(); i < requiredChildCount; i++) {
- final TaskView taskView = (TaskView) inflater.inflate(R.layout.task, this, false);
- addView(taskView);
- }
- while (getChildCount() > requiredChildCount) {
- final TaskView taskView = (TaskView) getChildAt(getChildCount() - 1);
- removeView(taskView);
+ final int requiredTaskCount = tasks.size();
+ if (getTaskViewCount() != requiredTaskCount) {
+ if (oldChildCount > 0) {
+ removeView(mClearAllButton);
+ }
+ for (int i = getChildCount(); i < requiredTaskCount; i++) {
+ final TaskView taskView = (TaskView) inflater.inflate(R.layout.task, this, false);
+ addView(taskView);
+ }
+ while (getChildCount() > requiredTaskCount) {
+ final TaskView taskView = (TaskView) getChildAt(getChildCount() - 1);
+ removeView(taskView);
+ }
+ if (requiredTaskCount > 0) {
+ addView(mClearAllButton);
+ }
}
// Unload existing visible task data
unloadVisibleTaskData();
// Rebind and reset all task views
- for (int i = requiredChildCount - 1; i >= 0; i--) {
- final int pageIndex = requiredChildCount - i - 1;
+ for (int i = requiredTaskCount - 1; i >= 0; i--) {
+ final int pageIndex = requiredTaskCount - i - 1;
final Task task = tasks.get(i);
final TaskView taskView = (TaskView) getChildAt(pageIndex);
taskView.bind(task);
@@ -481,10 +441,16 @@
onTaskStackUpdated();
}
+ public int getTaskViewCount() {
+ // Account for the clear all button.
+ int childCount = getChildCount();
+ return childCount == 0 ? 0 : childCount - 1;
+ }
+
protected void onTaskStackUpdated() { }
public void resetTaskVisuals() {
- for (int i = getChildCount() - 1; i >= 0; i--) {
+ for (int i = getTaskViewCount() - 1; i >= 0; i--) {
TaskView taskView = (TaskView) getChildAt(i);
if (!mIgnoreResetTaskViews.contains(taskView)) {
taskView.resetVisualProperties();
@@ -558,10 +524,12 @@
if (getPageCount() == 0 || getPageAt(0).getMeasuredWidth() == 0) {
return;
}
+ int scrollX = getScrollX();
final int halfPageWidth = getNormalChildWidth() / 2;
- final int screenCenter = mInsets.left + getPaddingLeft() + getScrollX() + halfPageWidth;
+ final int screenCenter = mInsets.left + getPaddingLeft() + scrollX + halfPageWidth;
final int halfScreenWidth = getMeasuredWidth() / 2;
final int pageSpacing = mPageSpacing;
+ mScrollState.scrollFromEdge = mIsRtl ? scrollX : (mMaxScrollX - scrollX);
final int pageCount = getPageCount();
for (int i = 0; i < pageCount; i++) {
@@ -587,9 +555,9 @@
RecentsTaskLoader loader = mModel.getRecentsTaskLoader();
int centerPageIndex = getPageNearestToCenterOfScreen();
+ int numChildren = getTaskViewCount();
int lower = Math.max(0, centerPageIndex - 2);
- int upper = Math.min(centerPageIndex + 2, getChildCount() - 1);
- int numChildren = getChildCount();
+ int upper = Math.min(centerPageIndex + 2, numChildren - 1);
// Update the task data for the in/visible children
for (int i = 0; i < numChildren; i++) {
@@ -667,6 +635,7 @@
final TaskView taskView = (TaskView) LayoutInflater.from(getContext())
.inflate(R.layout.task, this, false);
addView(taskView);
+ addView(mClearAllButton);
// The temporary running task is only used for the duration between the start of the
// gesture and the task list is loaded and applied
@@ -713,14 +682,14 @@
TaskView runningTaskView = getTaskView(mRunningTaskId);
if (runningTaskView == null) {
// Launch the first task
- if (getChildCount() > 0) {
+ if (getTaskViewCount() > 0) {
((TaskView) getChildAt(0)).launchTask(true /* animate */);
}
} else {
// Get the next launch task
int runningTaskIndex = indexOfChild(runningTaskView);
- int nextTaskIndex = Math.max(0, Math.min(getChildCount() - 1, runningTaskIndex + 1));
- if (nextTaskIndex < getChildCount()) {
+ int nextTaskIndex = Math.max(0, Math.min(getTaskViewCount() - 1, runningTaskIndex + 1));
+ if (nextTaskIndex < getTaskViewCount()) {
((TaskView) getChildAt(nextTaskIndex)).launchTask(true /* animate */);
}
}
@@ -763,7 +732,7 @@
/**
* Updates the page UI based on scroll params.
*/
- default void onPageScroll(ScrollState scrollState) {};
+ default void onPageScroll(ScrollState scrollState) {}
}
public static class ScrollState {
@@ -773,6 +742,11 @@
* of the screen and 1 is the edge of the screen.
*/
public float linearInterpolation;
+
+ /**
+ * The amount by which all the content is scrolled relative to the end of the list.
+ */
+ public float scrollFromEdge;
}
public void addIgnoreResetTask(TaskView taskView) {
@@ -809,7 +783,7 @@
AnimatorSet anim = new AnimatorSet();
PendingAnimation pendingAnimation = new PendingAnimation(anim);
- int count = getChildCount();
+ int count = getPageCount();
if (count == 0) {
return pendingAnimation;
}
@@ -820,12 +794,10 @@
int[] newScroll = new int[count];
getPageScrolls(newScroll, false, (v) -> v.getVisibility() != GONE && v != taskView);
+ int taskCount = getTaskViewCount();
int scrollDiffPerPage = 0;
- int leftmostPage = mIsRtl ? count -1 : 0;
- int rightmostPage = mIsRtl ? 0 : count - 1;
if (count > 1) {
- int secondRightmostPage = mIsRtl ? 1 : count - 2;
- scrollDiffPerPage = oldScroll[rightmostPage] - oldScroll[secondRightmostPage];
+ scrollDiffPerPage = Math.abs(oldScroll[1] - oldScroll[0]);
}
int draggedIndex = indexOfChild(taskView);
@@ -845,7 +817,7 @@
// - Dragging an adjacent page on the left side (right side for RTL)
int offset = mIsRtl ? scrollDiffPerPage : 0;
if (mCurrentPage == draggedIndex) {
- int lastPage = mIsRtl ? leftmostPage : rightmostPage;
+ int lastPage = taskCount - 1;
if (mCurrentPage == lastPage) {
offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage;
}
@@ -883,13 +855,15 @@
removeTask(taskView.getTask(), draggedIndex, onEndListener, true);
}
int pageToSnapTo = mCurrentPage;
- if (draggedIndex < pageToSnapTo) {
+ if (draggedIndex < pageToSnapTo || pageToSnapTo == (getTaskViewCount() - 1)) {
pageToSnapTo -= 1;
}
removeView(taskView);
- if (getChildCount() == 0) {
+
+ if (getTaskViewCount() == 0) {
+ removeView(mClearAllButton);
onAllTasksRemoved();
- } else if (!mIsClearAllButtonFullyRevealed) {
+ } else {
snapToPageImmediately(pageToSnapTo);
}
}
@@ -906,7 +880,7 @@
AnimatorSet anim = new AnimatorSet();
PendingAnimation pendingAnimation = new PendingAnimation(anim);
- int count = getChildCount();
+ int count = getTaskViewCount();
for (int i = 0; i < count; i++) {
addDismissedTaskAnimations(getChildAt(i), anim, duration);
}
@@ -914,11 +888,11 @@
mPendingAnimation = pendingAnimation;
mPendingAnimation.addEndListener((onEndListener) -> {
if (onEndListener.isSuccess) {
- while (getChildCount() != 0) {
- TaskView taskView = getPageAt(getChildCount() - 1);
- removeTask(taskView.getTask(), -1, onEndListener, false);
- removeView(taskView);
+ int taskViewCount = getTaskViewCount();
+ for (int i = 0; i < taskViewCount; i++) {
+ removeTask(getTaskViewAt(i).getTask(), -1, onEndListener, false);
}
+ removeAllViews();
onAllTasksRemoved();
}
mPendingAnimation = null;
@@ -932,15 +906,16 @@
set.play(anim);
}
- private boolean snapToPageRelative(int delta, boolean cycle) {
- if (getPageCount() == 0) {
+ private boolean snapToPageRelative(int pageCount, int delta, boolean cycle) {
+ if (pageCount == 0) {
return false;
}
final int newPageUnbound = getNextPage() + delta;
- if (!cycle && (newPageUnbound < 0 || newPageUnbound >= getChildCount())) {
+ if (!cycle && (newPageUnbound < 0 || newPageUnbound >= pageCount)) {
return false;
}
- snapToPage((newPageUnbound + getPageCount()) % getPageCount());
+ snapToPage((newPageUnbound + pageCount) % pageCount);
+ getChildAt(getNextPage()).requestFocus();
return true;
}
@@ -958,31 +933,37 @@
DISMISS_TASK_DURATION));
}
- public void dismissAllTasks() {
+ @SuppressWarnings("unused")
+ private void dismissAllTasks(View view) {
runDismissAnimation(createAllTasksDismissAnimation(DISMISS_TASK_DURATION));
}
+ private void dismissCurrentTask() {
+ TaskView taskView = getTaskView(getNextPage());
+ if (taskView != null) {
+ dismissTask(taskView, true /*animateTaskView*/, true /*removeTask*/);
+ }
+ }
+
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_TAB:
- return snapToPageRelative(event.isShiftPressed() ? -1 : 1,
+ return snapToPageRelative(getTaskViewCount(), event.isShiftPressed() ? -1 : 1,
event.isAltPressed() /* cycle */);
case KeyEvent.KEYCODE_DPAD_RIGHT:
- return snapToPageRelative(mIsRtl ? -1 : 1, false /* cycle */);
+ return snapToPageRelative(getPageCount(), mIsRtl ? -1 : 1, false /* cycle */);
case KeyEvent.KEYCODE_DPAD_LEFT:
- return snapToPageRelative(mIsRtl ? 1 : -1, false /* cycle */);
+ return snapToPageRelative(getPageCount(), mIsRtl ? 1 : -1, false /* cycle */);
case KeyEvent.KEYCODE_DEL:
case KeyEvent.KEYCODE_FORWARD_DEL:
- dismissTask((TaskView) getChildAt(getNextPage()), true /*animateTaskView*/,
- true /*removeTask*/);
+ dismissCurrentTask();
return true;
case KeyEvent.KEYCODE_NUMPAD_DOT:
if (event.isAltPressed()) {
// Numpad DEL pressed while holding Alt.
- dismissTask((TaskView) getChildAt(getNextPage()), true /*animateTaskView*/,
- true /*removeTask*/);
+ dismissCurrentTask();
return true;
}
}
@@ -1013,19 +994,24 @@
}
public void setContentAlpha(float alpha) {
+ if (alpha == mContentAlpha) {
+ return;
+ }
alpha = Utilities.boundToRange(alpha, 0, 1);
mContentAlpha = alpha;
- for (int i = getChildCount() - 1; i >= 0; i--) {
- TaskView child = getPageAt(i);
+ for (int i = getTaskViewCount() - 1; i >= 0; i--) {
+ TaskView child = getTaskViewAt(i);
if (!mRunningTaskTileHidden || child.getTask().key.id != mRunningTaskId) {
getChildAt(i).setAlpha(alpha);
}
}
+ mClearAllButton.setContentAlpha(mContentAlpha);
int alphaInt = Math.round(alpha * 255);
mEmptyMessagePaint.setAlpha(alphaInt);
mEmptyIcon.setAlpha(alphaInt);
- updateClearAllButtonAlpha();
+
+ setVisibility(alpha > 0 ? VISIBLE : GONE);
}
private float[] getAdjacentScaleAndTranslation(TaskView currTask,
@@ -1041,12 +1027,11 @@
public void onViewAdded(View child) {
super.onViewAdded(child);
child.setAlpha(mContentAlpha);
- onChildViewsChanged();
}
- @Override
- public TaskView getPageAt(int index) {
- return (TaskView) getChildAt(index);
+ public TaskView getTaskViewAt(int index) {
+ View child = getChildAt(index);
+ return child == mClearAllButton ? null : (TaskView) child;
}
public void updateEmptyMessage() {
@@ -1080,7 +1065,6 @@
mEmptyTextLayout = null;
mLastMeasureSize.set(getWidth(), getHeight());
}
- updateClearAllButtonAlpha();
if (mShowEmptyMessage && hasValidSize && mEmptyTextLayout == null) {
int availableWidth = mLastMeasureSize.x - mEmptyMessagePadding - mEmptyMessagePadding;
@@ -1138,16 +1122,16 @@
float toTranslationY = clipAnimationHelper.getSourceRect().centerY()
- clipAnimationHelper.getTargetRect().centerY();
if (launchingCenterTask) {
- TaskView centerTask = getPageAt(centerTaskIndex);
+ TaskView centerTask = getTaskViewAt(centerTaskIndex);
if (taskIndex - 1 >= 0) {
- TaskView adjacentTask = getPageAt(taskIndex - 1);
+ TaskView adjacentTask = getTaskViewAt(taskIndex - 1);
float[] scaleAndTranslation = getAdjacentScaleAndTranslation(centerTask,
toScale, toTranslationY);
scaleAndTranslation[1] = -scaleAndTranslation[1];
anim.play(createAnimForChild(adjacentTask, scaleAndTranslation));
}
- if (taskIndex + 1 < getPageCount()) {
- TaskView adjacentTask = getPageAt(taskIndex + 1);
+ if (taskIndex + 1 < getTaskViewCount()) {
+ TaskView adjacentTask = getTaskViewAt(taskIndex + 1);
float[] scaleAndTranslation = getAdjacentScaleAndTranslation(centerTask,
toScale, toTranslationY);
anim.play(createAnimForChild(adjacentTask, scaleAndTranslation));
@@ -1269,67 +1253,9 @@
return "";
}
- private int additionalScrollForClearAllButton() {
- return (int) getResources().getDimension(
- R.dimen.clear_all_container_width) - getPaddingEnd();
- }
-
- @Override
- protected int computeMaxScrollX() {
- if (getChildCount() == 0) {
- return super.computeMaxScrollX();
- }
-
- // Allow a clear_all_container_width-sized gap after the last task.
- return super.computeMaxScrollX() + (mIsRtl ? 0 : additionalScrollForClearAllButton());
- }
-
- @Override
- protected int offsetForPageScrolls() {
- return mIsRtl ? additionalScrollForClearAllButton() : 0;
- }
-
- public void setClearAllButton(View clearAllButton) {
- mClearAllButton = clearAllButton;
- updateClearAllButtonAlpha();
- }
-
- private void onChildViewsChanged() {
- final int childCount = getChildCount();
- mClearAllButton.setVisibility(childCount == 0 ? INVISIBLE : VISIBLE);
- setFocusable(childCount != 0);
- }
-
- public void revealClearAllButton() {
- setCurrentPage(getChildCount() - 1); // Loads tasks info if needed.
- scrollTo(mIsRtl ? 0 : computeMaxScrollX(), 0);
- }
-
- @Override
- public boolean performAccessibilityAction(int action, Bundle arguments) {
- if (getChildCount() > 0) {
- switch (action) {
- case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
- if (!mIsClearAllButtonFullyRevealed && getCurrentPage() == getPageCount() - 1) {
- revealClearAllButton();
- return true;
- }
- }
- case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
- if (mIsClearAllButtonFullyRevealed) {
- setCurrentPage(getChildCount() - 1);
- return true;
- }
- }
- break;
- }
- }
- return super.performAccessibilityAction(action, arguments);
- }
-
@Override
public void addChildrenForAccessibility(ArrayList<View> outChildren) {
- outChildren.add(mClearAllButton);
+ // Add children in reverse order
for (int i = getChildCount() - 1; i >= 0; --i) {
outChildren.add(getChildAt(i));
}
@@ -1338,17 +1264,9 @@
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
-
- if (getChildCount() > 0) {
- info.addAction(mIsClearAllButtonFullyRevealed ?
- AccessibilityNodeInfo.ACTION_SCROLL_FORWARD :
- AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
- info.setScrollable(true);
- }
-
final AccessibilityNodeInfo.CollectionInfo
collectionInfo = AccessibilityNodeInfo.CollectionInfo.obtain(
- 1, getChildCount(), false,
+ 1, getTaskViewCount(), false,
AccessibilityNodeInfo.CollectionInfo.SELECTION_MODE_NONE);
info.setCollectionInfo(collectionInfo);
}
@@ -1357,15 +1275,14 @@
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
- event.setScrollable(getPageCount() > 0);
+ final int taskViewCount = getTaskViewCount();
+ event.setScrollable(taskViewCount > 0);
- if (!mIsClearAllButtonFullyRevealed
- && event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
- final int childCount = getChildCount();
+ if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
final int[] visibleTasks = getVisibleChildrenRange();
- event.setFromIndex(childCount - visibleTasks[1] - 1);
- event.setToIndex(childCount - visibleTasks[0] - 1);
- event.setItemCount(childCount);
+ event.setFromIndex(taskViewCount - visibleTasks[1] - 1);
+ event.setToIndex(taskViewCount - visibleTasks[0] - 1);
+ event.setItemCount(taskViewCount);
}
}
@@ -1379,8 +1296,4 @@
protected boolean isPageOrderFlipped() {
return true;
}
-
- public boolean performTaskAccessibilityActionExtra(int action) {
- return false;
- }
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java b/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java
deleted file mode 100644
index c6cd527..0000000
--- a/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * 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.quickstep.views;
-
-import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
-import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.CLEAR_ALL_BUTTON;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.util.FloatProperty;
-import android.view.MotionEvent;
-import android.view.View;
-
-import com.android.launcher3.InsettableFrameLayout;
-import com.android.launcher3.R;
-
-import java.util.ArrayList;
-
-public class RecentsViewContainer extends InsettableFrameLayout {
- public static final FloatProperty<RecentsViewContainer> CONTENT_ALPHA =
- new FloatProperty<RecentsViewContainer>("contentAlpha") {
- @Override
- public void setValue(RecentsViewContainer view, float v) {
- view.setContentAlpha(v);
- }
-
- @Override
- public Float get(RecentsViewContainer view) {
- return view.mRecentsView.getContentAlpha();
- }
- };
-
- private final Rect mTempRect = new Rect();
-
- private RecentsView mRecentsView;
- private ClearAllButton mClearAllButton;
-
- public RecentsViewContainer(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- mClearAllButton = findViewById(R.id.clear_all_button);
- mClearAllButton.setOnClickListener((v) -> {
- mRecentsView.mActivity.getUserEventDispatcher()
- .logActionOnControl(TAP, CLEAR_ALL_BUTTON);
- mRecentsView.dismissAllTasks();
- });
-
- mRecentsView = findViewById(R.id.overview_panel);
- mClearAllButton.forceHasOverlappingRendering(false);
-
- mRecentsView.setClearAllButton(mClearAllButton);
- mClearAllButton.setRecentsView(mRecentsView);
-
- if (mRecentsView.isRtl()) {
- mClearAllButton.setNextFocusRightId(mRecentsView.getId());
- mRecentsView.setNextFocusLeftId(mClearAllButton.getId());
- } else {
- mClearAllButton.setNextFocusLeftId(mRecentsView.getId());
- mRecentsView.setNextFocusRightId(mClearAllButton.getId());
- }
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
-
- mRecentsView.getTaskSize(mTempRect);
-
- mClearAllButton.setTranslationX(
- (mRecentsView.isRtl() ? 1 : -1) *
- (getResources().getDimension(R.dimen.clear_all_container_width)
- - mClearAllButton.getMeasuredWidth()) / 2);
- mClearAllButton.setTranslationY(
- mTempRect.top + (mTempRect.height() - mClearAllButton.getMeasuredHeight()) / 2
- - mClearAllButton.getTop());
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- super.onTouchEvent(ev);
- // Do not let touch escape to siblings below this view. This prevents scrolling of the
- // workspace while in Recents.
- return true;
- }
-
- public void setContentAlpha(float alpha) {
- if (alpha == mRecentsView.getContentAlpha()) {
- return;
- }
- mRecentsView.setContentAlpha(alpha);
- setVisibility(alpha > 0 ? VISIBLE : GONE);
- }
-
- @Override
- public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
- if (mRecentsView.getChildCount() > 0) {
- // Carousel is first in tab order.
- views.add(mRecentsView);
- views.add(mClearAllButton);
- }
- }
-
- public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
- return mRecentsView.requestFocus(direction, previouslyFocusedRect) ||
- super.requestFocus(direction, previouslyFocusedRect);
- }
-
- @Override
- public void addChildrenForAccessibility(ArrayList<View> outChildren) {
- outChildren.add(mRecentsView);
- }
-}
\ No newline at end of file
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 468efd8..c4ccd96 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -121,6 +121,7 @@
TaskUtils.getLaunchComponentKeyForTask(getTask().key));
});
setOutlineProvider(new TaskOutlineProvider(getResources()));
+ setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS);
}
@Override
@@ -347,8 +348,6 @@
}
}
- if (getRecentsView().performTaskAccessibilityActionExtra(action)) return true;
-
return super.performAccessibilityAction(action, arguments);
}
diff --git a/res/layout/launcher.xml b/res/layout/launcher.xml
index da17b2b..17361ac 100644
--- a/res/layout/launcher.xml
+++ b/res/layout/launcher.xml
@@ -39,7 +39,7 @@
launcher:pageIndicator="@+id/page_indicator" />
<include
- android:id="@+id/overview_panel_container"
+ android:id="@+id/overview_panel"
layout="@layout/overview_panel"
android:visibility="gone" />
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 0645f41..07bd800 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -122,6 +122,7 @@
<item name="android:saveEnabled">false</item>
<item name="android:textColor">@android:color/white</item>
<item name="android:includeFontPadding">false</item>
+ <item name="android:importantForAccessibility">no</item>
</style>
<!-- Base theme for BubbleTextView and sub classes -->
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 3eaead1..aaeeb63 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -214,8 +214,6 @@
// UI and state for the overview panel
private View mOverviewPanel;
- private View mOverviewPanelContainer;
-
@Thunk boolean mWorkspaceLoading = true;
private OnResumeCallback mOnResumeCallback;
@@ -913,7 +911,6 @@
mWorkspace = mDragLayer.findViewById(R.id.workspace);
mWorkspace.initParentViews(mDragLayer);
mOverviewPanel = findViewById(R.id.overview_panel);
- mOverviewPanelContainer = findViewById(R.id.overview_panel_container);
mHotseat = findViewById(R.id.hotseat);
mHotseatSearchBox = findViewById(R.id.search_container_hotseat);
@@ -1174,10 +1171,6 @@
return (T) mOverviewPanel;
}
- public <T extends View> T getOverviewPanelContainer() {
- return (T) mOverviewPanelContainer;
- }
-
public DropTargetBar getDropTargetBar() {
return mDropTargetBar;
}
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index de9cd98..db5dc66 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -24,7 +24,6 @@
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
-import android.graphics.Matrix;
import android.graphics.Rect;
import android.os.Bundle;
import android.provider.Settings;
@@ -142,8 +141,6 @@
protected T mPageIndicator;
// Convenience/caching
- private static final Matrix sTmpInvMatrix = new Matrix();
- private static final float[] sTmpPoint = new float[2];
private static final Rect sTmpRect = new Rect();
protected final Rect mInsets = new Rect();
@@ -242,12 +239,6 @@
return index;
}
- protected void scrollAndForceFinish(int scrollX) {
- scrollTo(scrollX, 0);
- mScroller.setFinalX(scrollX);
- forceFinishScroller(true);
- }
-
/**
* Updates the scroll of the current page immediately to its final scroll position. We use this
* in CustomizePagedView to allow tabs to share the same PagedView while resetting the scroll of
@@ -259,7 +250,9 @@
if (0 <= mCurrentPage && mCurrentPage < getPageCount()) {
newX = getScrollForPage(mCurrentPage);
}
- scrollAndForceFinish(newX);
+ scrollTo(newX, 0);
+ mScroller.setFinalX(newX);
+ forceFinishScroller(true);
}
private void abortScrollerAnimation(boolean resetNextPage) {
@@ -544,10 +537,6 @@
setMeasuredDimension(widthSize, heightSize);
}
- protected void restoreScrollOnLayout() {
- setCurrentPage(getNextPage());
- }
-
@SuppressLint("DrawAllocation")
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
@@ -599,7 +588,7 @@
}
if (mScroller.isFinished() && pageScrollChanged) {
- restoreScrollOnLayout();
+ setCurrentPage(getNextPage());
}
}
@@ -620,23 +609,26 @@
- mInsets.bottom - getPaddingBottom()) / 2;
final int scrollOffsetLeft = mInsets.left + getPaddingLeft();
+ final int scrollOffsetRight = getWidth() - getPaddingRight() - mInsets.right;
boolean pageScrollChanged = false;
- for (int i = startIndex, childLeft = scrollOffsetLeft + offsetForPageScrolls();
- i != endIndex;
- i += delta) {
+ for (int i = startIndex, childLeft = scrollOffsetLeft; i != endIndex; i += delta) {
final View child = getPageAt(i);
if (scrollLogic.shouldIncludeView(child)) {
- final int childTop = verticalCenter - child.getMeasuredHeight() / 2;
final int childWidth = child.getMeasuredWidth();
+ final int childRight = childLeft + childWidth;
if (layoutChildren) {
final int childHeight = child.getMeasuredHeight();
- child.layout(childLeft, childTop,
- childLeft + child.getMeasuredWidth(), childTop + childHeight);
+ final int childTop = verticalCenter - childHeight / 2;
+ child.layout(childLeft, childTop, childRight, childTop + childHeight);
}
- final int pageScroll = childLeft - scrollOffsetLeft;
+ // In case the pages are of different width, align the page to left or right edge
+ // based on the orientation.
+ final int pageScroll = mIsRtl
+ ? (childLeft - scrollOffsetLeft)
+ : Math.max(0, childRight - scrollOffsetRight);
if (outPageScrolls[i] != pageScroll) {
pageScrollChanged = true;
outPageScrolls[i] = pageScroll;
@@ -666,10 +658,6 @@
}
}
- protected int offsetForPageScrolls() {
- return 0;
- }
-
public void setPageSpacing(int pageSpacing) {
mPageSpacing = pageSpacing;
requestLayout();
@@ -747,11 +735,13 @@
if (direction == View.FOCUS_LEFT) {
if (getCurrentPage() > 0) {
snapToPage(getCurrentPage() - 1);
+ getChildAt(getCurrentPage() - 1).requestFocus(direction);
return true;
}
} else if (direction == View.FOCUS_RIGHT) {
if (getCurrentPage() < getPageCount() - 1) {
snapToPage(getCurrentPage() + 1);
+ getChildAt(getCurrentPage() + 1).requestFocus(direction);
return true;
}
}
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 72ba418..8993978 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -490,6 +490,12 @@
});
}
+ @Override
+ public void getDrawingRect(Rect outRect) {
+ super.getDrawingRect(outRect);
+ outRect.offset(0, (int) getTranslationY());
+ }
+
public class AdapterHolder {
public static final int MAIN = 0;
public static final int WORK = 1;