Implement swipe to delete on Recents Go
Introduce a ItemTouchHelper.Callback implementation that hooks up remove logic to swiping right on task items. Additionally, tighten the modification access to the task list in TaskListLoader so it is harder to mis-use. Bug: 114136250 Test: Removed app via swiping Change-Id: I9b6e2783d1f6d56e655e9b7ffa9af85328f98159
This commit is contained in:
parent
f820d5d817
commit
013af455b1
|
@ -25,7 +25,8 @@ import com.android.launcher3.R;
|
||||||
import com.android.quickstep.views.TaskItemView;
|
import com.android.quickstep.views.TaskItemView;
|
||||||
import com.android.systemui.shared.recents.model.Task;
|
import com.android.systemui.shared.recents.model.Task;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recycler view adapter that dynamically inflates and binds {@link TaskHolder} instances with the
|
* Recycler view adapter that dynamically inflates and binds {@link TaskHolder} instances with the
|
||||||
* appropriate {@link Task} from the recents task list.
|
* appropriate {@link Task} from the recents task list.
|
||||||
|
@ -56,7 +57,7 @@ public final class TaskAdapter extends Adapter<TaskHolder> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(TaskHolder holder, int position) {
|
public void onBindViewHolder(TaskHolder holder, int position) {
|
||||||
ArrayList<Task> tasks = mLoader.getCurrentTaskList();
|
List<Task> tasks = mLoader.getCurrentTaskList();
|
||||||
if (position >= tasks.size()) {
|
if (position >= tasks.size()) {
|
||||||
// Task list has updated.
|
// Task list has updated.
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package com.android.quickstep;
|
package com.android.quickstep;
|
||||||
|
|
||||||
|
import com.android.systemui.shared.recents.model.Task;
|
||||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,9 +23,11 @@ import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||||
*/
|
*/
|
||||||
public final class TaskInputController {
|
public final class TaskInputController {
|
||||||
|
|
||||||
TaskAdapter mAdapter;
|
private final TaskListLoader mLoader;
|
||||||
|
private final TaskAdapter mAdapter;
|
||||||
|
|
||||||
public TaskInputController(TaskAdapter adapter) {
|
public TaskInputController(TaskListLoader loader,TaskAdapter adapter) {
|
||||||
|
mLoader = loader;
|
||||||
mAdapter = adapter;
|
mAdapter = adapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +42,14 @@ public final class TaskInputController {
|
||||||
null /* options */, null /* resultCallback */, null /* resultCallbackHandler */);
|
null /* options */, null /* resultCallback */, null /* resultCallbackHandler */);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement swipe to delete and notify adapter that data has updated
|
public void onTaskSwiped(TaskHolder viewHolder) {
|
||||||
|
int position = viewHolder.getAdapterPosition();
|
||||||
|
Task task = viewHolder.getTask();
|
||||||
|
ActivityManagerWrapper.getInstance().removeTask(task.key.id);
|
||||||
|
mLoader.removeTask(task);
|
||||||
|
mAdapter.notifyItemRemoved(position);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Implement "Clear all" and notify adapter that data has updated
|
// TODO: Implement "Clear all" and notify adapter that data has updated
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import com.android.systemui.shared.recents.model.Task;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
@ -45,13 +46,13 @@ public final class TaskListLoader {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current task list as of the last completed load (see
|
* Returns the current task list as of the last completed load (see
|
||||||
* {@link #loadTaskList}). This list of tasks is guaranteed to always have all its task
|
* {@link #loadTaskList}) as a read-only list. This list of tasks is guaranteed to always have
|
||||||
* content loaded.
|
* all its task content loaded.
|
||||||
*
|
*
|
||||||
* @return the current list of tasks w/ all content loaded
|
* @return the current list of tasks w/ all content loaded
|
||||||
*/
|
*/
|
||||||
public ArrayList<Task> getCurrentTaskList() {
|
public List<Task> getCurrentTaskList() {
|
||||||
return mTaskList;
|
return Collections.unmodifiableList(mTaskList);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -84,6 +85,13 @@ public final class TaskListLoader {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the task from the current task list.
|
||||||
|
*/
|
||||||
|
void removeTask(Task task) {
|
||||||
|
mTaskList.remove(task);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads task content for a list of tasks, including the label, icon, and thumbnail. For content
|
* Loads task content for a list of tasks, including the label, icon, and thumbnail. For content
|
||||||
* that isn't cached, load the content asynchronously in the background.
|
* that isn't cached, load the content asynchronously in the background.
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2019 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;
|
||||||
|
|
||||||
|
import static androidx.recyclerview.widget.ItemTouchHelper.RIGHT;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for swipe input on {@link TaskHolder} views in the recents view.
|
||||||
|
*/
|
||||||
|
public final class TaskSwipeCallback extends ItemTouchHelper.SimpleCallback {
|
||||||
|
|
||||||
|
private final TaskInputController mTaskInputController;
|
||||||
|
|
||||||
|
public TaskSwipeCallback(TaskInputController inputController) {
|
||||||
|
super(0 /* dragDirs */, RIGHT);
|
||||||
|
mTaskInputController = inputController;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onMove(RecyclerView recyclerView, ViewHolder viewHolder,
|
||||||
|
ViewHolder target) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSwiped(ViewHolder viewHolder, int direction) {
|
||||||
|
if (direction == RIGHT) {
|
||||||
|
mTaskInputController.onTaskSwiped((TaskHolder) viewHolder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,6 +23,7 @@ import android.util.FloatProperty;
|
||||||
import android.view.ViewDebug;
|
import android.view.ViewDebug;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
@ -30,6 +31,7 @@ import com.android.launcher3.R;
|
||||||
import com.android.quickstep.TaskAdapter;
|
import com.android.quickstep.TaskAdapter;
|
||||||
import com.android.quickstep.TaskInputController;
|
import com.android.quickstep.TaskInputController;
|
||||||
import com.android.quickstep.TaskListLoader;
|
import com.android.quickstep.TaskListLoader;
|
||||||
|
import com.android.quickstep.TaskSwipeCallback;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Root view for the icon recents view. Acts as the main interface to the rest of the Launcher code
|
* Root view for the icon recents view. Acts as the main interface to the rest of the Launcher code
|
||||||
|
@ -76,29 +78,35 @@ public final class IconRecentsView extends FrameLayout {
|
||||||
@ViewDebug.ExportedProperty(category = "launcher")
|
@ViewDebug.ExportedProperty(category = "launcher")
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
private final TaskListLoader mTaskLoader;
|
||||||
|
private final TaskAdapter mTaskAdapter;
|
||||||
|
private final TaskInputController mTaskInputController;
|
||||||
|
|
||||||
private float mTranslationYFactor;
|
private float mTranslationYFactor;
|
||||||
private TaskAdapter mTaskAdapter;
|
|
||||||
private RecyclerView mTaskRecyclerView;
|
private RecyclerView mTaskRecyclerView;
|
||||||
private TaskInputController mTaskInputController;
|
|
||||||
private TaskListLoader mTaskLoader;
|
|
||||||
|
|
||||||
public IconRecentsView(Context context, AttributeSet attrs) {
|
public IconRecentsView(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
mContext = context;
|
mContext = context;
|
||||||
|
mTaskLoader = new TaskListLoader(mContext);
|
||||||
|
mTaskAdapter = new TaskAdapter(mTaskLoader);
|
||||||
|
mTaskInputController = new TaskInputController(mTaskLoader, mTaskAdapter);
|
||||||
|
mTaskAdapter.setInputController(mTaskInputController);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onFinishInflate() {
|
protected void onFinishInflate() {
|
||||||
super.onFinishInflate();
|
super.onFinishInflate();
|
||||||
mTaskLoader = new TaskListLoader(mContext);
|
if (mTaskRecyclerView == null) {
|
||||||
mTaskAdapter = new TaskAdapter(mTaskLoader);
|
|
||||||
mTaskInputController = new TaskInputController(mTaskAdapter);
|
|
||||||
mTaskAdapter.setInputController(mTaskInputController);
|
|
||||||
mTaskRecyclerView = findViewById(R.id.recent_task_recycler_view);
|
mTaskRecyclerView = findViewById(R.id.recent_task_recycler_view);
|
||||||
mTaskRecyclerView.setAdapter(mTaskAdapter);
|
mTaskRecyclerView.setAdapter(mTaskAdapter);
|
||||||
mTaskRecyclerView.setLayoutManager(
|
mTaskRecyclerView.setLayoutManager(
|
||||||
new LinearLayoutManager(mContext, VERTICAL, true /* reverseLayout */));
|
new LinearLayoutManager(mContext, VERTICAL, true /* reverseLayout */));
|
||||||
|
ItemTouchHelper helper = new ItemTouchHelper(
|
||||||
|
new TaskSwipeCallback(mTaskInputController));
|
||||||
|
helper.attachToRecyclerView(mTaskRecyclerView);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue