Introducing Clear-all button on Overview
It’s an initial implementation, i.e. no fancy effects. It shares a parent (LauncherRecentsViewContainer) with RecentsView. The button is centered in clear_all_button_container, which gets positioned programmatically to the right of the last task. (RTL polish will be a separate CL as well). Bug: 72222505 Change-Id: Ia912908a93a30c2f51450ccf0f97c7495e7916d5 Test: Manual
This commit is contained in:
parent
de967a2355
commit
6d2321cb7d
|
@ -20,13 +20,23 @@
|
|||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<com.android.quickstep.fallback.FallbackRecentsView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/overview_panel"
|
||||
<com.android.quickstep.views.RecentsViewContainer
|
||||
android:id="@+id/overview_panel_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:theme="@style/HomeScreenElementTheme" />
|
||||
>
|
||||
<include layout="@layout/overview_clear_all_button"/>
|
||||
|
||||
</com.android.quickstep.fallback.RecentsRootView>
|
||||
<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:focusableInTouchMode="true"
|
||||
android:theme="@style/HomeScreenElementTheme"
|
||||
>
|
||||
|
||||
</com.android.quickstep.fallback.FallbackRecentsView>
|
||||
</com.android.quickstep.views.RecentsViewContainer>
|
||||
</com.android.quickstep.fallback.RecentsRootView>
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<TextView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/clear_all_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|top"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:text="@string/recents_clear_all"
|
||||
android:textColor="?attr/workspaceTextColor"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:textSize="14sp"
|
||||
/>
|
|
@ -14,14 +14,23 @@
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<com.android.quickstep.views.LauncherRecentsView
|
||||
<com.android.quickstep.views.RecentsViewContainer
|
||||
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:clipToPadding="false"
|
||||
android:visibility="invisible"
|
||||
android:focusableInTouchMode="true" >
|
||||
>
|
||||
<include layout="@layout/overview_clear_all_button"/>
|
||||
|
||||
</com.android.quickstep.views.LauncherRecentsView>
|
||||
<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:focusableInTouchMode="true"
|
||||
android:theme="@style/HomeScreenElementTheme"
|
||||
>
|
||||
|
||||
</com.android.quickstep.views.LauncherRecentsView>
|
||||
</com.android.quickstep.views.RecentsViewContainer>
|
|
@ -45,4 +45,7 @@
|
|||
<!-- Copied from framework resource:
|
||||
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>
|
||||
</resources>
|
||||
|
|
|
@ -35,4 +35,7 @@
|
|||
|
||||
<!-- Content description for the recent apps's accessibility option that closes it. [CHAR LIMIT=NONE] -->
|
||||
<string name="accessibility_close_task">Close</string>
|
||||
|
||||
<!-- Recents: Title of a button that clears the task list, i.e. closes all tasks. [CHAR LIMIT=30] -->
|
||||
<string name="recents_clear_all">Clear all</string>
|
||||
</resources>
|
|
@ -20,7 +20,7 @@ import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT;
|
|||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.quickstep.views.LauncherRecentsView.TRANSLATION_Y_FACTOR;
|
||||
import static com.android.quickstep.views.RecentsView.ADJACENT_SCALE;
|
||||
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
|
||||
import static com.android.quickstep.views.RecentsViewContainer.CONTENT_ALPHA;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.TargetApi;
|
||||
|
@ -33,21 +33,24 @@ import com.android.launcher3.LauncherStateManager.StateHandler;
|
|||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
||||
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) {
|
||||
mRecentsView.setContentAlpha(state.overviewUi ? 1 : 0);
|
||||
mRecentsViewContainer.setContentAlpha(state.overviewUi ? 1 : 0);
|
||||
float[] scaleTranslationYFactor = state.getOverviewScaleAndTranslationYFactor(mLauncher);
|
||||
mRecentsView.setAdjacentScale(scaleTranslationYFactor[0]);
|
||||
mRecentsView.setTranslationYFactor(scaleTranslationYFactor[1]);
|
||||
|
@ -66,7 +69,7 @@ public class RecentsViewStateController implements StateHandler {
|
|||
builder.getInterpolator(ANIM_OVERVIEW_TRANSLATION, LINEAR));
|
||||
setter.setFloat(mRecentsView, TRANSLATION_Y_FACTOR, scaleTranslationYFactor[1],
|
||||
builder.getInterpolator(ANIM_OVERVIEW_TRANSLATION, LINEAR));
|
||||
setter.setFloat(mRecentsView, CONTENT_ALPHA, toState.overviewUi ? 1 : 0,
|
||||
setter.setFloat(mRecentsViewContainer, CONTENT_ALPHA, toState.overviewUi ? 1 : 0,
|
||||
AGGRESSIVE_EASE_IN_OUT);
|
||||
|
||||
if (!toState.overviewUi) {
|
||||
|
|
|
@ -87,21 +87,10 @@ import java.util.ArrayList;
|
|||
public abstract class RecentsView<T extends BaseActivity>
|
||||
extends PagedView implements OnSharedPreferenceChangeListener, Insettable {
|
||||
|
||||
public static final boolean DEBUG_SHOW_CLEAR_ALL_BUTTON = false;
|
||||
|
||||
private final Rect mTempRect = new Rect();
|
||||
|
||||
public static final FloatProperty<RecentsView> CONTENT_ALPHA =
|
||||
new FloatProperty<RecentsView>("contentAlpha") {
|
||||
@Override
|
||||
public void setValue(RecentsView recentsView, float v) {
|
||||
recentsView.setContentAlpha(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float get(RecentsView recentsView) {
|
||||
return recentsView.mContentAlpha;
|
||||
}
|
||||
};
|
||||
|
||||
public static final FloatProperty<RecentsView> ADJACENT_SCALE =
|
||||
new FloatProperty<RecentsView>("adjacentScale") {
|
||||
@Override
|
||||
|
@ -180,6 +169,8 @@ public abstract class RecentsView<T extends BaseActivity>
|
|||
// Keeps track of task views whose visual state should not be reset
|
||||
private ArraySet<TaskView> mIgnoreResetTaskViews = new ArraySet<>();
|
||||
|
||||
private RecentsViewContainer mContainerView;
|
||||
|
||||
// Variables for empty state
|
||||
private final Drawable mEmptyIcon;
|
||||
private final CharSequence mEmptyMessage;
|
||||
|
@ -320,12 +311,18 @@ public abstract class RecentsView<T extends BaseActivity>
|
|||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
super.onTouchEvent(ev);
|
||||
if (DEBUG_SHOW_CLEAR_ALL_BUTTON && mTouchState == TOUCH_STATE_REST && mScroller.isFinished()
|
||||
&& getChildCount() != 0
|
||||
&& ev.getX() > getChildAt(getChildCount() - 1).getRight() - getScrollX()) {
|
||||
// If nothing is in motion, allow events to the right of the last task to go to the
|
||||
// Clear All button.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ev.getAction() == MotionEvent.ACTION_UP && mShowEmptyMessage) {
|
||||
onAllTasksRemoved();
|
||||
}
|
||||
// Do not let touch escape to siblings below this view.
|
||||
return true;
|
||||
return super.onTouchEvent(ev);
|
||||
}
|
||||
|
||||
private void applyLoadPlan(RecentsTaskLoadPlan loadPlan) {
|
||||
|
@ -424,6 +421,10 @@ public abstract class RecentsView<T extends BaseActivity>
|
|||
|
||||
protected abstract void getTaskSize(DeviceProfile dp, Rect outRect);
|
||||
|
||||
public void getTaskSize(Rect outRect) {
|
||||
getTaskSize(mActivity.getDeviceProfile(), outRect);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean computeScrollHelper() {
|
||||
boolean scrolling = super.computeScrollHelper();
|
||||
|
@ -530,6 +531,7 @@ public abstract class RecentsView<T extends BaseActivity>
|
|||
|
||||
unloadVisibleTaskData();
|
||||
setCurrentPage(0);
|
||||
scrollTo(0, 0);
|
||||
|
||||
OverviewCallbacks.get(getContext()).onResetOverview();
|
||||
}
|
||||
|
@ -844,11 +846,11 @@ public abstract class RecentsView<T extends BaseActivity>
|
|||
snapToPageRelative(1);
|
||||
}
|
||||
|
||||
public void setContentAlpha(float alpha) {
|
||||
if (mContentAlpha == alpha) {
|
||||
return;
|
||||
}
|
||||
public float getContentAlpha() {
|
||||
return mContentAlpha;
|
||||
}
|
||||
|
||||
public void setContentAlpha(float alpha) {
|
||||
mContentAlpha = alpha;
|
||||
for (int i = getChildCount() - 1; i >= 0; i--) {
|
||||
TaskView child = getPageAt(i);
|
||||
|
@ -860,8 +862,6 @@ public abstract class RecentsView<T extends BaseActivity>
|
|||
int alphaInt = Math.round(alpha * 255);
|
||||
mEmptyMessagePaint.setAlpha(alphaInt);
|
||||
mEmptyIcon.setAlpha(alphaInt);
|
||||
|
||||
setVisibility(alpha > 0 ? VISIBLE : GONE);
|
||||
}
|
||||
|
||||
public void setAdjacentScale(float adjacentScale) {
|
||||
|
@ -929,6 +929,9 @@ public abstract class RecentsView<T extends BaseActivity>
|
|||
mShowEmptyMessage = isEmpty;
|
||||
updateEmptyStateUi(hasSizeChanged);
|
||||
invalidate();
|
||||
if (mContainerView != null) {
|
||||
mContainerView.onEmptyStateChanged(!DEBUG_SHOW_CLEAR_ALL_BUTTON || mShowEmptyMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1095,4 +1098,30 @@ public abstract class RecentsView<T extends BaseActivity>
|
|||
protected String getCurrentPageDescription() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public void dismissAllTasks() {
|
||||
for (int i = 0; i < getChildCount(); ++i) {
|
||||
Task task = getPageAt(i).getTask();
|
||||
if (task != null) {
|
||||
ActivityManagerWrapper.getInstance().removeTask(task.key.id);
|
||||
}
|
||||
}
|
||||
onAllTasksRemoved();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int computeMaxScrollX() {
|
||||
if (!DEBUG_SHOW_CLEAR_ALL_BUTTON || getChildCount() == 0) {
|
||||
return super.computeMaxScrollX();
|
||||
}
|
||||
|
||||
// Allow a clear_all_container_width-sized gap after the last task.
|
||||
return super.computeMaxScrollX() + (int) getResources().getDimension(
|
||||
R.dimen.clear_all_container_width) - getPaddingEnd();
|
||||
}
|
||||
|
||||
public void setContainerView(RecentsViewContainer containerView) {
|
||||
mContainerView = containerView;
|
||||
mContainerView.onEmptyStateChanged(!DEBUG_SHOW_CLEAR_ALL_BUTTON || mShowEmptyMessage);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
package com.android.quickstep.views;
|
||||
|
||||
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;
|
||||
|
||||
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 View 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.dismissAllTasks();
|
||||
});
|
||||
|
||||
mRecentsView = (RecentsView) findViewById(R.id.overview_panel);
|
||||
mRecentsView.setContainerView(this);
|
||||
}
|
||||
|
||||
@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(
|
||||
(mClearAllButton.getMeasuredWidth() - getResources().getDimension(
|
||||
R.dimen.clear_all_container_width)) / 2);
|
||||
mClearAllButton.setTranslationY(
|
||||
mTempRect.top + (mTempRect.height() - mClearAllButton.getMeasuredHeight()) / 2
|
||||
- mClearAllButton.getY());
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
public void onEmptyStateChanged(boolean isEmpty) {
|
||||
mClearAllButton.setVisibility(isEmpty ? GONE : VISIBLE);
|
||||
}
|
||||
}
|
|
@ -40,7 +40,7 @@
|
|||
launcher:pageIndicator="@+id/page_indicator" />
|
||||
|
||||
<include
|
||||
android:id="@+id/overview_panel"
|
||||
android:id="@+id/overview_panel_container"
|
||||
layout="@layout/overview_panel"
|
||||
android:visibility="gone" />
|
||||
|
||||
|
|
|
@ -147,6 +147,7 @@
|
|||
<item type="id" name="search_container_all_apps" />
|
||||
|
||||
<!-- Recents -->
|
||||
<item type="id" name="overview_panel"/>
|
||||
<integer name="config_recentsMaxThumbnailCacheSize">6</integer>
|
||||
<integer name="config_recentsMaxIconCacheSize">12</integer>
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ package com.android.launcher3;
|
|||
|
||||
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
|
||||
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
|
||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
|
@ -205,6 +206,8 @@ public class Launcher extends BaseDraggingActivity
|
|||
// UI and state for the overview panel
|
||||
private View mOverviewPanel;
|
||||
|
||||
private View mOverviewPanelContainer;
|
||||
|
||||
@Thunk boolean mWorkspaceLoading = true;
|
||||
|
||||
private OnResumeCallback mOnResumeCallback;
|
||||
|
@ -912,6 +915,7 @@ public class Launcher extends BaseDraggingActivity
|
|||
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);
|
||||
mDragHandleIndicator = findViewById(R.id.drag_indicator);
|
||||
mHotseatSearchBox = findViewById(R.id.search_container_hotseat);
|
||||
|
@ -1192,6 +1196,10 @@ public class Launcher extends BaseDraggingActivity
|
|||
return (T) mOverviewPanel;
|
||||
}
|
||||
|
||||
public <T extends View> T getOverviewPanelContainer() {
|
||||
return (T) mOverviewPanelContainer;
|
||||
}
|
||||
|
||||
public DropTargetBar getDropTargetBar() {
|
||||
return mDropTargetBar;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue