diff options
Diffstat (limited to 'go')
5 files changed, 140 insertions, 71 deletions
diff --git a/go/quickstep/res/layout/clear_all_button.xml b/go/quickstep/res/layout/clear_all_button.xml new file mode 100644 index 000000000..eceffec42 --- /dev/null +++ b/go/quickstep/res/layout/clear_all_button.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. +--> +<Button 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="center_horizontal" + android:background="@drawable/clear_all_button" + android:gravity="center" + android:text="@string/recents_clear_all" + android:textAllCaps="false" + android:textColor="@color/clear_all_button_text" + android:textSize="14sp"> +</Button> diff --git a/go/quickstep/res/layout/icon_recents_root_view.xml b/go/quickstep/res/layout/icon_recents_root_view.xml index 6dc293f74..6fb7e19d1 100644 --- a/go/quickstep/res/layout/icon_recents_root_view.xml +++ b/go/quickstep/res/layout/icon_recents_root_view.xml @@ -19,29 +19,11 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> - <LinearLayout - android:id="@+id/recent_task_content_view" + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/recent_task_recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" - android:orientation="vertical" - android:visibility="gone"> - <androidx.recyclerview.widget.RecyclerView - android:id="@+id/recent_task_recycler_view" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:scrollbars="none"/> - <Button - android:id="@+id/clear_all_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal" - android:background="@drawable/clear_all_button" - android:gravity="center" - android:text="@string/recents_clear_all" - android:textAllCaps="false" - android:textColor="@color/clear_all_button_text" - android:textSize="14sp"/> - </LinearLayout> + android:scrollbars="none"/> <TextView android:id="@+id/recent_task_empty_view" android:layout_width="match_parent" diff --git a/go/quickstep/src/com/android/quickstep/ClearAllHolder.java b/go/quickstep/src/com/android/quickstep/ClearAllHolder.java new file mode 100644 index 000000000..ce87171f4 --- /dev/null +++ b/go/quickstep/src/com/android/quickstep/ClearAllHolder.java @@ -0,0 +1,30 @@ +/* + * 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 android.view.View; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView.ViewHolder; + +/** + * Holder for clear all button view in task recycler view. + */ +final class ClearAllHolder extends ViewHolder { + public ClearAllHolder(@NonNull View itemView) { + super(itemView); + } +} diff --git a/go/quickstep/src/com/android/quickstep/TaskAdapter.java b/go/quickstep/src/com/android/quickstep/TaskAdapter.java index 18d5877aa..4eec78be2 100644 --- a/go/quickstep/src/com/android/quickstep/TaskAdapter.java +++ b/go/quickstep/src/com/android/quickstep/TaskAdapter.java @@ -16,12 +16,14 @@ package com.android.quickstep; import android.view.LayoutInflater; +import android.view.View.OnClickListener; import android.view.ViewGroup; +import android.widget.Button; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView.Adapter; +import androidx.recyclerview.widget.RecyclerView.ViewHolder; -import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; import com.android.quickstep.views.TaskItemView; import com.android.systemui.shared.recents.model.Task; @@ -34,14 +36,17 @@ import java.util.Optional; * Recycler view adapter that dynamically inflates and binds {@link TaskHolder} instances with the * appropriate {@link Task} from the recents task list. */ -public final class TaskAdapter extends Adapter<TaskHolder> { +public final class TaskAdapter extends Adapter<ViewHolder> { public static final int CHANGE_EVENT_TYPE_EMPTY_TO_CONTENT = 0; public static final int MAX_TASKS_TO_DISPLAY = 6; private static final String TAG = "TaskAdapter"; + private static final int ITEM_TYPE_TASK = 0; + private static final int ITEM_TYPE_CLEAR_ALL = 1; private final TaskListLoader mLoader; private TaskActionController mTaskActionController; + private OnClickListener mClearAllListener; private boolean mIsShowingLoadingUi; public TaskAdapter(@NonNull TaskListLoader loader) { @@ -52,6 +57,10 @@ public final class TaskAdapter extends Adapter<TaskHolder> { mTaskActionController = taskActionController; } + public void setOnClearAllClickListener(OnClickListener listener) { + mClearAllListener = listener; + } + /** * Sets all positions in the task adapter to loading views, binding new views if necessary. * This changes the task adapter's view of the data, so the appropriate notify events should be @@ -65,21 +74,32 @@ public final class TaskAdapter extends Adapter<TaskHolder> { } @Override - public TaskHolder onCreateViewHolder(ViewGroup parent, int viewType) { - TaskItemView itemView = (TaskItemView) LayoutInflater.from(parent.getContext()) - .inflate(R.layout.task_item_view, parent, false); - TaskHolder holder = new TaskHolder(itemView); - itemView.setOnClickListener(view -> mTaskActionController.launchTask(holder)); - return holder; + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + switch (viewType) { + case ITEM_TYPE_TASK: + TaskItemView itemView = (TaskItemView) LayoutInflater.from(parent.getContext()) + .inflate(R.layout.task_item_view, parent, false); + TaskHolder taskHolder = new TaskHolder(itemView); + itemView.setOnClickListener(view -> mTaskActionController.launchTask(taskHolder)); + return taskHolder; + case ITEM_TYPE_CLEAR_ALL: + Button clearView = (Button) LayoutInflater.from(parent.getContext()) + .inflate(R.layout.clear_all_button, parent, false); + ClearAllHolder clearAllHolder = new ClearAllHolder(clearView); + clearView.setOnClickListener(mClearAllListener); + return clearAllHolder; + default: + throw new IllegalArgumentException("No known holder for item type: " + viewType); + } } @Override - public void onBindViewHolder(TaskHolder holder, int position) { + public void onBindViewHolder(ViewHolder holder, int position) { onBindViewHolderInternal(holder, position, false /* willAnimate */); } @Override - public void onBindViewHolder(@NonNull TaskHolder holder, int position, + public void onBindViewHolder(@NonNull ViewHolder holder, int position, @NonNull List<Object> payloads) { if (payloads.isEmpty()) { super.onBindViewHolder(holder, position, payloads); @@ -95,40 +115,60 @@ public final class TaskAdapter extends Adapter<TaskHolder> { } } - private void onBindViewHolderInternal(@NonNull TaskHolder holder, int position, + private void onBindViewHolderInternal(@NonNull ViewHolder holder, int position, boolean willAnimate) { - if (mIsShowingLoadingUi) { - holder.bindEmptyUi(); - return; + int itemType = getItemViewType(position); + switch (itemType) { + case ITEM_TYPE_TASK: + TaskHolder taskHolder = (TaskHolder) holder; + if (mIsShowingLoadingUi) { + taskHolder.bindEmptyUi(); + return; + } + List<Task> tasks = mLoader.getCurrentTaskList(); + if (position >= tasks.size()) { + // Task list has updated. + return; + } + Task task = tasks.get(position); + taskHolder.bindTask(task, willAnimate /* willAnimate */); + mLoader.loadTaskIconAndLabel(task, () -> { + // Ensure holder still has the same task. + if (Objects.equals(Optional.of(task), taskHolder.getTask())) { + taskHolder.getTaskItemView().setIcon(task.icon); + taskHolder.getTaskItemView().setLabel(task.titleDescription); + } + }); + mLoader.loadTaskThumbnail(task, () -> { + if (Objects.equals(Optional.of(task), taskHolder.getTask())) { + taskHolder.getTaskItemView().setThumbnail(task.thumbnail.thumbnail); + } + }); + break; + case ITEM_TYPE_CLEAR_ALL: + // Nothing to bind. + break; + default: + throw new IllegalArgumentException("No known holder for item type: " + itemType); } - List<Task> tasks = mLoader.getCurrentTaskList(); - if (position >= tasks.size()) { - // Task list has updated. - return; - } - Task task = tasks.get(position); - holder.bindTask(task, willAnimate /* willAnimate */); - mLoader.loadTaskIconAndLabel(task, () -> { - // Ensure holder still has the same task. - if (Objects.equals(Optional.of(task), holder.getTask())) { - holder.getTaskItemView().setIcon(task.icon); - holder.getTaskItemView().setLabel(task.titleDescription); - } - }); - mLoader.loadTaskThumbnail(task, () -> { - if (Objects.equals(Optional.of(task), holder.getTask())) { - holder.getTaskItemView().setThumbnail(task.thumbnail.thumbnail); - } - }); + } + + @Override + public int getItemViewType(int position) { + // Bottom is always clear all button. + return (position == 0) ? ITEM_TYPE_CLEAR_ALL : ITEM_TYPE_TASK; } @Override public int getItemCount() { + // Always at least one for clear all button. + int itemCount = 1; if (mIsShowingLoadingUi) { // Show loading version of all items. - return MAX_TASKS_TO_DISPLAY; + itemCount += MAX_TASKS_TO_DISPLAY; } else { - return Math.min(mLoader.getCurrentTaskList().size(), MAX_TASKS_TO_DISPLAY); + itemCount += Math.min(mLoader.getCurrentTaskList().size(), MAX_TASKS_TO_DISPLAY); } + return itemCount; } } diff --git a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java index 3c08b7ec7..e2dad58b9 100644 --- a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java +++ b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java @@ -18,9 +18,6 @@ package com.android.quickstep.views; import static androidx.recyclerview.widget.LinearLayoutManager.VERTICAL; import static com.android.quickstep.TaskAdapter.CHANGE_EVENT_TYPE_EMPTY_TO_CONTENT; -import static com.android.quickstep.views.TaskLayoutUtils.getClearAllButtonHeight; -import static com.android.quickstep.views.TaskLayoutUtils.getClearAllButtonTopBottomMargin; -import static com.android.quickstep.views.TaskLayoutUtils.getClearAllButtonWidth; import static com.android.quickstep.views.TaskLayoutUtils.getTaskListHeight; import android.animation.Animator; @@ -114,7 +111,6 @@ public final class IconRecentsView extends FrameLayout { private View mShowingContentView; private View mEmptyView; private View mContentView; - private View mClearAllView; private boolean mTransitionedFromApp; private AnimatorSet mLayoutAnimation; private final ArraySet<View> mLayingOutViews = new ArraySet<>(); @@ -141,6 +137,7 @@ public final class IconRecentsView extends FrameLayout { mDeviceProfile = activity.getDeviceProfile(); mTaskLoader = new TaskListLoader(mContext); mTaskAdapter = new TaskAdapter(mTaskLoader); + mTaskAdapter.setOnClearAllClickListener(view -> animateClearAllTasks()); mTaskActionController = new TaskActionController(mTaskLoader, mTaskAdapter); mTaskAdapter.setActionController(mTaskActionController); RecentsModel.INSTANCE.get(context).addThumbnailChangeListener(listener); @@ -178,7 +175,7 @@ public final class IconRecentsView extends FrameLayout { () -> mTaskRecyclerView.setItemAnimator(new DefaultItemAnimator())); mEmptyView = findViewById(R.id.recent_task_empty_view); - mContentView = findViewById(R.id.recent_task_content_view); + mContentView = mTaskRecyclerView; mTaskAdapter.registerAdapterDataObserver(new AdapterDataObserver() { @Override public void onChanged() { @@ -190,16 +187,7 @@ public final class IconRecentsView extends FrameLayout { updateContentViewVisibility(); } }); - // TODO: Move clear all button to recycler view so that it can scroll off screen. // TODO: Move layout param logic into onMeasure - mClearAllView = findViewById(R.id.clear_all_button); - MarginLayoutParams clearAllParams = - (MarginLayoutParams) mClearAllView.getLayoutParams(); - clearAllParams.height = getClearAllButtonHeight(mDeviceProfile); - clearAllParams.width = getClearAllButtonWidth(mDeviceProfile); - clearAllParams.topMargin = getClearAllButtonTopBottomMargin(mDeviceProfile); - clearAllParams.bottomMargin = getClearAllButtonTopBottomMargin(mDeviceProfile); - mClearAllView.setOnClickListener(v -> animateClearAllTasks()); } } @@ -210,7 +198,7 @@ public final class IconRecentsView extends FrameLayout { for (TaskItemView itemView : itemViews) { itemView.setEnabled(enabled); } - mClearAllView.setEnabled(enabled); + // TODO: Disable clear all button. } /** @@ -365,6 +353,7 @@ public final class IconRecentsView extends FrameLayout { * @return array of attached task item views */ private TaskItemView[] getTaskViews() { + // TODO: Check that clear all button isn't here.. int taskCount = mTaskRecyclerView.getChildCount(); TaskItemView[] itemViews = new TaskItemView[taskCount]; for (int i = 0; i < taskCount; i ++) { |