summaryrefslogtreecommitdiffstats
path: root/go
diff options
context:
space:
mode:
authorKevin <kevhan@google.com>2019-04-16 11:46:35 -0700
committerKevin Han <kevhan@google.com>2019-04-23 19:24:13 +0000
commit3f343b7b5394595640d3467f4049a0fe92f21520 (patch)
tree03911c89c760956e7a0e958e39589b33ee6431e1 /go
parentf17917fab3ce44e89a5ba3aafda8987a80b86f62 (diff)
downloadandroid_packages_apps_Trebuchet-3f343b7b5394595640d3467f4049a0fe92f21520.tar.gz
android_packages_apps_Trebuchet-3f343b7b5394595640d3467f4049a0fe92f21520.tar.bz2
android_packages_apps_Trebuchet-3f343b7b5394595640d3467f4049a0fe92f21520.zip
Smarter task laying out based off onMeasure
Previously laid out via calls to layoutParams. This isn't as optimized as being baked into the measure + layout system and has the issue of being less flexible. For example, if the device profile changes (e.g. orientation change), we'd have to apply new layout params for all the views. With this CL, we would only need to do this for top-level views and the children will resolve themselves. Bug: 114136250 Test: Check layout on marlin + walleye Change-Id: Iddd503a8844bdde7724d3f804660da61719d5c90 (cherry picked from commit c98f116b7757e48d09f29325e0c32d20fedc18d6)
Diffstat (limited to 'go')
-rw-r--r--go/quickstep/res/layout/icon_recents_root_view.xml1
-rw-r--r--go/quickstep/res/layout/task_item_view.xml20
-rw-r--r--go/quickstep/src/com/android/quickstep/TaskAdapter.java14
-rw-r--r--go/quickstep/src/com/android/quickstep/TaskLayoutManager.java42
-rw-r--r--go/quickstep/src/com/android/quickstep/views/IconRecentsView.java8
-rw-r--r--go/quickstep/src/com/android/quickstep/views/TaskItemView.java32
-rw-r--r--go/quickstep/src/com/android/quickstep/views/TaskLayoutUtils.java14
-rw-r--r--go/quickstep/src/com/android/quickstep/views/TaskThumbnailIconView.java100
8 files changed, 157 insertions, 74 deletions
diff --git a/go/quickstep/res/layout/icon_recents_root_view.xml b/go/quickstep/res/layout/icon_recents_root_view.xml
index 630088236..6dc293f74 100644
--- a/go/quickstep/res/layout/icon_recents_root_view.xml
+++ b/go/quickstep/res/layout/icon_recents_root_view.xml
@@ -29,7 +29,6 @@
android:id="@+id/recent_task_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_weight="1"
android:scrollbars="none"/>
<Button
android:id="@+id/clear_all_button"
diff --git a/go/quickstep/res/layout/task_item_view.xml b/go/quickstep/res/layout/task_item_view.xml
index 219823734..1483d4cf5 100644
--- a/go/quickstep/res/layout/task_item_view.xml
+++ b/go/quickstep/res/layout/task_item_view.xml
@@ -17,25 +17,23 @@
<com.android.quickstep.views.TaskItemView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="match_parent"
android:orientation="horizontal">
- <FrameLayout
+ <com.android.quickstep.views.TaskThumbnailIconView
android:id="@+id/task_icon_and_thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_gravity="center_vertical"
- android:layout_marginHorizontal="8dp">
+ android:layout_marginHorizontal="8dp"
+ android:layout_marginTop="16dp">
<ImageView
android:id="@+id/task_thumbnail"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_gravity="top|start"/>
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
<ImageView
android:id="@+id/task_icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom|end"/>
- </FrameLayout>
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+ </com.android.quickstep.views.TaskThumbnailIconView>
<TextView
android:id="@+id/task_label"
android:layout_width="wrap_content"
diff --git a/go/quickstep/src/com/android/quickstep/TaskAdapter.java b/go/quickstep/src/com/android/quickstep/TaskAdapter.java
index f1fc9deee..7e7f27829 100644
--- a/go/quickstep/src/com/android/quickstep/TaskAdapter.java
+++ b/go/quickstep/src/com/android/quickstep/TaskAdapter.java
@@ -15,11 +15,6 @@
*/
package com.android.quickstep;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-
-import static com.android.quickstep.views.TaskLayoutUtils.getTaskHeight;
-import static com.android.quickstep.views.TaskLayoutUtils.getTaskTopMargin;
-
import android.view.LayoutInflater;
import android.view.ViewGroup;
@@ -45,13 +40,11 @@ public final class TaskAdapter extends Adapter<TaskHolder> {
private static final String TAG = "TaskAdapter";
private final TaskListLoader mLoader;
- private final DeviceProfile mDeviceProfile;
private TaskActionController mTaskActionController;
private boolean mIsShowingLoadingUi;
- public TaskAdapter(@NonNull TaskListLoader loader, DeviceProfile dp) {
+ public TaskAdapter(@NonNull TaskListLoader loader) {
mLoader = loader;
- mDeviceProfile = dp;
}
public void setActionController(TaskActionController taskActionController) {
@@ -74,11 +67,6 @@ public final class TaskAdapter extends Adapter<TaskHolder> {
public TaskHolder onCreateViewHolder(ViewGroup parent, int viewType) {
TaskItemView itemView = (TaskItemView) LayoutInflater.from(parent.getContext())
.inflate(R.layout.task_item_view, parent, false);
- ViewGroup.MarginLayoutParams itemViewParams =
- (ViewGroup.MarginLayoutParams) itemView.getLayoutParams();
- itemViewParams.width = MATCH_PARENT;
- itemViewParams.height = getTaskHeight(mDeviceProfile);
- itemViewParams.topMargin = getTaskTopMargin(mDeviceProfile);
TaskHolder holder = new TaskHolder(itemView);
itemView.setOnClickListener(view -> mTaskActionController.launchTask(holder));
return holder;
diff --git a/go/quickstep/src/com/android/quickstep/TaskLayoutManager.java b/go/quickstep/src/com/android/quickstep/TaskLayoutManager.java
new file mode 100644
index 000000000..ecb249926
--- /dev/null
+++ b/go/quickstep/src/com/android/quickstep/TaskLayoutManager.java
@@ -0,0 +1,42 @@
+/*
+ * 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.content.Context;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.LinearLayoutManager;
+
+/**
+ * Layout manager for task list that restricts child height based off the max number of tasks the
+ * recycler view should hold and the height of the recycler view.
+ */
+public final class TaskLayoutManager extends LinearLayoutManager {
+
+ public TaskLayoutManager(Context context, int vertical, boolean b) {
+ super(context, vertical, b);
+ }
+
+ @Override
+ public void measureChildWithMargins(@NonNull View child, int widthUsed, int heightUsed) {
+ // Request child view takes up 1 / MAX_TASKS of the total view height.
+ int heightUsedByView = (int) (getHeight() *
+ (TaskAdapter.MAX_TASKS_TO_DISPLAY - 1.0f) / TaskAdapter.MAX_TASKS_TO_DISPLAY);
+ super.measureChildWithMargins(child, widthUsed, heightUsedByView);
+ }
+}
diff --git a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
index 2c4abc5c3..712b9dc11 100644
--- a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
+++ b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java
@@ -43,7 +43,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.ItemTouchHelper;
-import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver;
import androidx.recyclerview.widget.RecyclerView.OnChildAttachStateChangeListener;
@@ -56,6 +55,7 @@ import com.android.quickstep.RecentsToActivityHelper;
import com.android.quickstep.TaskActionController;
import com.android.quickstep.TaskAdapter;
import com.android.quickstep.TaskHolder;
+import com.android.quickstep.TaskLayoutManager;
import com.android.quickstep.TaskListLoader;
import com.android.quickstep.TaskSwipeCallback;
@@ -121,7 +121,7 @@ public final class IconRecentsView extends FrameLayout {
mContext = context;
mDeviceProfile = activity.getDeviceProfile();
mTaskLoader = new TaskListLoader(mContext);
- mTaskAdapter = new TaskAdapter(mTaskLoader, mDeviceProfile);
+ mTaskAdapter = new TaskAdapter(mTaskLoader);
mTaskActionController = new TaskActionController(mTaskLoader, mTaskAdapter);
mTaskAdapter.setActionController(mTaskActionController);
}
@@ -135,7 +135,7 @@ public final class IconRecentsView extends FrameLayout {
recyclerViewParams.height = getTaskListHeight(mDeviceProfile);
mTaskRecyclerView.setAdapter(mTaskAdapter);
mTaskRecyclerView.setLayoutManager(
- new LinearLayoutManager(mContext, VERTICAL, true /* reverseLayout */));
+ new TaskLayoutManager(mContext, VERTICAL, true /* reverseLayout */));
ItemTouchHelper helper = new ItemTouchHelper(
new TaskSwipeCallback(mTaskActionController));
helper.attachToRecyclerView(mTaskRecyclerView);
@@ -170,6 +170,8 @@ 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();
diff --git a/go/quickstep/src/com/android/quickstep/views/TaskItemView.java b/go/quickstep/src/com/android/quickstep/views/TaskItemView.java
index 4392c68a0..572747bfd 100644
--- a/go/quickstep/src/com/android/quickstep/views/TaskItemView.java
+++ b/go/quickstep/src/com/android/quickstep/views/TaskItemView.java
@@ -15,8 +15,6 @@
*/
package com.android.quickstep.views;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -25,8 +23,6 @@ import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.FloatProperty;
import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -43,7 +39,6 @@ public final class TaskItemView extends LinearLayout {
private static final String EMPTY_LABEL = "";
private static final String DEFAULT_LABEL = "...";
- private static final float SUBITEM_FRAME_RATIO = .6f;
private final Drawable mDefaultIcon;
private final Drawable mDefaultThumbnail;
private final TaskLayerDrawable mIconDrawable;
@@ -51,7 +46,6 @@ public final class TaskItemView extends LinearLayout {
private TextView mLabelView;
private ImageView mIconView;
private ImageView mThumbnailView;
- private FrameLayout mThumbnailIconFrame;
private float mContentTransitionProgress;
/**
@@ -86,7 +80,6 @@ public final class TaskItemView extends LinearLayout {
mLabelView = findViewById(R.id.task_label);
mThumbnailView = findViewById(R.id.task_thumbnail);
mIconView = findViewById(R.id.task_icon);
- mThumbnailIconFrame = findViewById(R.id.task_icon_and_thumbnail);
mThumbnailView.setImageDrawable(mThumbnailDrawable);
mIconView.setImageDrawable(mIconDrawable);
@@ -95,31 +88,6 @@ public final class TaskItemView extends LinearLayout {
CONTENT_TRANSITION_PROGRESS.setValue(this, 1.0f);
}
- @Override
- public void setLayoutParams(ViewGroup.LayoutParams params) {
- super.setLayoutParams(params);
-
- // TODO: Rather than setting child layout params, make custom views and override onMeasure.
- if (mThumbnailIconFrame == null
- || mIconView == null
- || mThumbnailView == null) {
- // Views not initialized yet.
- return;
- }
-
- int frameSize = params.height;
- ViewGroup.LayoutParams frameParams = mThumbnailIconFrame.getLayoutParams();
- frameParams.width = frameSize;
-
- int frameSubItemWidth = (int) (SUBITEM_FRAME_RATIO * frameSize);
- ViewGroup.LayoutParams thumbnailParams = mThumbnailView.getLayoutParams();
- thumbnailParams.width = frameSubItemWidth;
-
- ViewGroup.LayoutParams iconParams = mIconView.getLayoutParams();
- iconParams.width = frameSubItemWidth;
- iconParams.height = frameSubItemWidth;
- }
-
/**
* Resets task item view to empty, loading UI.
*/
diff --git a/go/quickstep/src/com/android/quickstep/views/TaskLayoutUtils.java b/go/quickstep/src/com/android/quickstep/views/TaskLayoutUtils.java
index 1b507071f..5bb30ad9c 100644
--- a/go/quickstep/src/com/android/quickstep/views/TaskLayoutUtils.java
+++ b/go/quickstep/src/com/android/quickstep/views/TaskLayoutUtils.java
@@ -26,23 +26,9 @@ public final class TaskLayoutUtils {
private static final float BUTTON_TO_DEVICE_HEIGHT_RATIO = 36.0f/569;
private static final float BUTTON_WIDTH_TO_HEIGHT_RATIO = 53.0f/18;
private static final float BUTTON_MARGIN_TO_BUTTON_HEIGHT_RATIO = 5.0f/9;
- private static final float TASK_TO_DEVICE_HEIGHT_RATIO = 15.0f/19;
- private static final float TASK_MARGIN_TO_TASK_HEIGHT_RATIO = 4.0f/15;
private TaskLayoutUtils() {}
- public static int getTaskHeight(DeviceProfile dp) {
- return (int) (TASK_TO_DEVICE_HEIGHT_RATIO * getTaskItemSpace(dp));
- }
-
- public static int getTaskTopMargin(DeviceProfile dp) {
- return (int) (TASK_MARGIN_TO_TASK_HEIGHT_RATIO * getTaskHeight(dp));
- }
-
- private static int getTaskItemSpace(DeviceProfile dp) {
- return getTaskListHeight(dp) / TaskAdapter.MAX_TASKS_TO_DISPLAY;
- }
-
public static int getTaskListHeight(DeviceProfile dp) {
int clearAllSpace = getClearAllButtonHeight(dp) + 2 * getClearAllButtonTopBottomMargin(dp);
return getDeviceLongWidth(dp) - clearAllSpace;
diff --git a/go/quickstep/src/com/android/quickstep/views/TaskThumbnailIconView.java b/go/quickstep/src/com/android/quickstep/views/TaskThumbnailIconView.java
new file mode 100644
index 000000000..b1c60dd97
--- /dev/null
+++ b/go/quickstep/src/com/android/quickstep/views/TaskThumbnailIconView.java
@@ -0,0 +1,100 @@
+/*
+ * 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.views;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.launcher3.R;
+
+/**
+ * Square view that holds thumbnail and icon and shrinks them appropriately so that both fit nicely
+ * within the view. Side length is determined by height.
+ */
+final class TaskThumbnailIconView extends ViewGroup {
+ private final Rect mTmpFrameRect = new Rect();
+ private final Rect mTmpChildRect = new Rect();
+ private View mThumbnailView;
+ private View mIconView;
+ private static final float SUBITEM_FRAME_RATIO = .6f;
+
+ public TaskThumbnailIconView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mThumbnailView = findViewById(R.id.task_thumbnail);
+ mIconView = findViewById(R.id.task_icon);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
+ int width = height;
+ setMeasuredDimension(width, height);
+
+ int subItemSize = (int) (SUBITEM_FRAME_RATIO * height);
+ if (mThumbnailView.getVisibility() != GONE) {
+ int thumbnailHeightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
+ int thumbnailWidthSpec = MeasureSpec.makeMeasureSpec(subItemSize, MeasureSpec.EXACTLY);
+ measureChild(mThumbnailView, thumbnailWidthSpec, thumbnailHeightSpec);
+ }
+ if (mIconView.getVisibility() != GONE) {
+ int iconHeightSpec = MeasureSpec.makeMeasureSpec(subItemSize, MeasureSpec.EXACTLY);
+ int iconWidthSpec = MeasureSpec.makeMeasureSpec(subItemSize, MeasureSpec.EXACTLY);
+ measureChild(mIconView, iconWidthSpec, iconHeightSpec);
+ }
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ mTmpFrameRect.left = getPaddingLeft();
+ mTmpFrameRect.right = right - left - getPaddingRight();
+ mTmpFrameRect.top = getPaddingTop();
+ mTmpFrameRect.bottom = bottom - top - getPaddingBottom();
+
+ // Layout the thumbnail to the top-start corner of the view
+ if (mThumbnailView.getVisibility() != GONE) {
+ final int width = mThumbnailView.getMeasuredWidth();
+ final int height = mThumbnailView.getMeasuredHeight();
+
+ final int thumbnailGravity = Gravity.TOP | Gravity.START;
+ Gravity.apply(thumbnailGravity, width, height, mTmpFrameRect, mTmpChildRect);
+
+ mThumbnailView.layout(mTmpChildRect.left, mTmpChildRect.top,
+ mTmpChildRect.right, mTmpChildRect.bottom);
+ }
+
+ // Layout the icon to the bottom-end corner of the view
+ if (mIconView.getVisibility() != GONE) {
+ final int width = mIconView.getMeasuredWidth();
+ final int height = mIconView.getMeasuredHeight();
+
+ int thumbnailGravity = Gravity.BOTTOM | Gravity.END;
+ Gravity.apply(thumbnailGravity, width, height, mTmpFrameRect, mTmpChildRect);
+
+ mIconView.layout(mTmpChildRect.left, mTmpChildRect.top,
+ mTmpChildRect.right, mTmpChildRect.bottom);
+ }
+ }
+}