Show widget previews in their expected cell sizes

1. Show widget previews in their expected cell sizes.
2. Update the bottom picker to use a table layout rather than
a horizontal scrollbar.
3. Move the title and cell size description to the bottom of
the preview.

Test: Run AddConfigWidgetTest
      Manually open full and bottom widgets picker and observe
      widget previews.
      Video: https://drive.google.com/file/d/1K8A8hK5B4FgPTsX3cb-Yt4a_VjI0pk-w/view?usp=sharing
Bug: 179797520
Change-Id: I938612cb2e2477ce4a3a2d6c8891a0a36fc0978c
This commit is contained in:
Steven Ng
2021-02-25 22:54:37 +00:00
parent d6844dcb7f
commit 11773f47d2
10 changed files with 123 additions and 94 deletions

View File

@@ -15,14 +15,16 @@
-->
<com.android.launcher3.dragndrop.LivePreviewWidgetCell
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingHorizontal="@dimen/widget_cell_horizontal_padding"
android:paddingVertical="@dimen/widget_cell_vertical_padding"
android:layout_weight="1"
android:orientation="vertical"
android:focusable="true"
android:background="?android:attr/colorPrimaryDark"
android:gravity="center_horizontal">
<include layout="@layout/widget_cell_content" />
<include layout="@layout/widget_cell_content" />
</com.android.launcher3.dragndrop.LivePreviewWidgetCell>

View File

@@ -15,8 +15,10 @@
-->
<com.android.launcher3.widget.WidgetCell
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingHorizontal="@dimen/widget_cell_horizontal_padding"
android:paddingVertical="@dimen/widget_cell_vertical_padding"
android:layout_weight="1"
android:orientation="vertical"
android:focusable="true"

View File

@@ -17,47 +17,37 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/widget_preview_label_vertical_padding"
android:paddingBottom="@dimen/widget_preview_label_vertical_padding"
android:paddingLeft="@dimen/widget_preview_label_horizontal_padding"
android:paddingRight="@dimen/widget_preview_label_horizontal_padding"
android:orientation="horizontal">
<!-- The name of the widget. -->
<TextView
android:id="@+id/widget_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:fadingEdge="horizontal"
android:gravity="start"
android:singleLine="true"
android:maxLines="1"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
<!-- The original dimensions of the widget (can't be the same text as above due to different
style. -->
<TextView
android:id="@+id/widget_dims"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp"
android:alpha="0.8" />
</LinearLayout>
<!-- The image of the widget. This view does not support padding. Any placement adjustment
should be done using margins. -->
<com.android.launcher3.widget.WidgetImageView
android:id="@+id/widget_preview"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1" />
android:layout_weight="1"
android:layout_marginVertical="8dp" />
<!-- The name of the widget. -->
<TextView
android:id="@+id/widget_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:fadingEdge="horizontal"
android:gravity="center_horizontal"
android:singleLine="true"
android:maxLines="1"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
<!-- The original dimensions of the widget (can't be the same text as above due to different
style. -->
<TextView
android:id="@+id/widget_dims"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp"
android:alpha="0.8" />
</merge>

View File

@@ -44,11 +44,16 @@
android:textSize="14sp"
android:text="@string/long_press_widget_to_add"/>
<include layout="@layout/widgets_scroll_container"
android:id="@+id/widgets"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="45dp"
android:layout_marginBottom="40dp"/>
<ScrollView
android:id="@+id/widgets_table_scroll_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="45dp"
android:layout_marginBottom="40dp">
<include layout="@layout/widgets_table_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
</ScrollView>
</com.android.launcher3.widget.WidgetsBottomSheet>

View File

@@ -18,4 +18,5 @@
android:id="@+id/widgets_table"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="8dp"
android:background="?android:attr/colorPrimaryDark" />

View File

@@ -102,8 +102,8 @@
<dimen name="work_profile_footer_text_size">16sp</dimen>
<!-- Widget tray -->
<dimen name="widget_preview_label_vertical_padding">8dp</dimen>
<dimen name="widget_preview_label_horizontal_padding">16dp</dimen>
<dimen name="widget_cell_vertical_padding">8dp</dimen>
<dimen name="widget_cell_horizontal_padding">16dp</dimen>
<dimen name="widget_preview_shadow_blur">0.5dp</dimen>
<dimen name="widget_preview_key_shadow_distance">1dp</dimen>

View File

@@ -24,7 +24,6 @@ import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnLayoutChangeListener;
import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.LinearLayout;
@@ -60,6 +59,8 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
/** Widget preview width is calculated by multiplying this factor to the widget cell width. */
private static final float PREVIEW_SCALE = 0.8f;
private int mPreviewWidth;
private int mPreviewHeight;
protected int mPresetPreviewSize;
private int mCellSize;
@@ -106,6 +107,7 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
private void setContainerWidth() {
mCellSize = (int) (mDeviceProfile.allAppsIconSizePx * WIDTH_SCALE);
mPresetPreviewSize = (int) (mCellSize * PREVIEW_SCALE);
mPreviewWidth = mPreviewHeight = mPresetPreviewSize;
}
@Override
@@ -128,6 +130,7 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
mWidgetImage.setBitmap(null, null);
mWidgetName.setText(null);
mWidgetDims.setText(null);
mPreviewWidth = mPreviewHeight = mPresetPreviewSize;
if (mActiveRequest != null) {
mActiveRequest.cancel();
@@ -181,6 +184,11 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
return;
}
if (bitmap != null) {
LayoutParams layoutParams = (LayoutParams) mWidgetImage.getLayoutParams();
layoutParams.width = bitmap.getWidth();
layoutParams.height = bitmap.getHeight();
mWidgetImage.setLayoutParams(layoutParams);
mWidgetImage.setBitmap(bitmap, mWidgetPreviewLoader.getBadgeForUser(mItem.user,
BaseIconFactory.getBadgeSizeForIconSize(mDeviceProfile.allAppsIconSizePx)));
if (mAnimatePreview) {
@@ -197,8 +205,16 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
if (mActiveRequest != null) {
return;
}
mActiveRequest = mWidgetPreviewLoader.getPreview(
mItem, mPresetPreviewSize, mPresetPreviewSize, this);
mActiveRequest = mWidgetPreviewLoader.getPreview(mItem, mPreviewWidth, mPreviewHeight,
this);
}
/** Sets the widget preview image size in number of cells. */
public void setPreviewSize(int spanX, int spanY) {
int padding = 2 * getResources()
.getDimensionPixelSize(R.dimen.widget_preview_shortcut_padding);
mPreviewWidth = mDeviceProfile.cellWidthPx * spanX + padding;
mPreviewHeight = mDeviceProfile.cellHeightPx * spanY + padding;
}
@Override
@@ -232,12 +248,6 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
return "";
}
@Override
public void setLayoutParams(ViewGroup.LayoutParams params) {
params.width = params.height = mCellSize;
super.setLayoutParams(params);
}
@Override
public CharSequence getAccessibilityClassName() {
return WidgetCell.class.getName();

View File

@@ -24,22 +24,25 @@ import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.IntProperty;
import android.util.Pair;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.widget.ScrollView;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
import com.android.launcher3.ResourceUtils;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.dragndrop.LivePreviewWidgetCell;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.widget.util.WidgetsTableUtils;
import java.util.List;
@@ -65,6 +68,8 @@ public class WidgetsBottomSheet extends BaseWidgetSheet implements Insettable {
private static final int DEFAULT_CLOSE_DURATION = 200;
private ItemInfo mOriginalItemInfo;
private Rect mInsets;
private final int mMaxTableHeight;
private int mMaxHorizontalSpan = 4;
public WidgetsBottomSheet(Context context, AttributeSet attrs) {
this(context, attrs, 0);
@@ -75,12 +80,41 @@ public class WidgetsBottomSheet extends BaseWidgetSheet implements Insettable {
setWillNotDraw(false);
mInsets = new Rect();
mContent = this;
DeviceProfile deviceProfile = mLauncher.getDeviceProfile();
// Set the max table height to 2 / 3 of the grid height so that the bottom picker won't
// take over the entire view vertically.
mMaxTableHeight = deviceProfile.inv.numRows * 2 / 3 * deviceProfile.cellHeightPx;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int paddingPx = 2 * getResources().getDimensionPixelOffset(
R.dimen.widget_cell_horizontal_padding);
int maxHorizontalSpan = findViewById(R.id.widgets_table).getMeasuredWidth()
/ (mLauncher.getDeviceProfile().cellWidthPx + paddingPx);
if (mMaxHorizontalSpan != maxHorizontalSpan) {
// Ensure the table layout is showing widgets in the right column after measure.
mMaxHorizontalSpan = maxHorizontalSpan;
onWidgetsBound();
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
setTranslationShift(mTranslationShift);
// Ensure the scroll view height is not larger than mMaxTableHeight, which is a value
// smaller than the entire screen height.
ScrollView widgetsTableScrollView = findViewById(R.id.widgets_table_scroll_view);
if (widgetsTableScrollView.getMeasuredHeight() > mMaxTableHeight) {
ViewGroup.LayoutParams layoutParams = widgetsTableScrollView.getLayoutParams();
layoutParams.height = mMaxTableHeight;
widgetsTableScrollView.setLayoutParams(layoutParams);
}
}
public void populateAndShow(ItemInfo itemInfo) {
@@ -101,39 +135,21 @@ public class WidgetsBottomSheet extends BaseWidgetSheet implements Insettable {
mOriginalItemInfo.getTargetComponent().getPackageName(),
mOriginalItemInfo.user));
ViewGroup widgetRow = findViewById(R.id.widgets);
ViewGroup widgetCells = widgetRow.findViewById(R.id.widgets_cell_list);
TableLayout widgetsTable = findViewById(R.id.widgets_table);
widgetsTable.removeAllViews();
widgetCells.removeAllViews();
for (int i = 0; i < widgets.size(); i++) {
WidgetCell widget = addItemCell(widgetCells);
widget.applyFromCellItem(widgets.get(i), LauncherAppState.getInstance(mLauncher)
.getWidgetCache());
widget.ensurePreview();
widget.setVisibility(View.VISIBLE);
if (i < widgets.size() - 1) {
addDivider(widgetCells);
}
}
if (widgets.size() == 1) {
// If there is only one widget, we want to center it instead of left-align.
WidgetsBottomSheet.LayoutParams params = (WidgetsBottomSheet.LayoutParams)
widgetRow.getLayoutParams();
params.gravity = Gravity.CENTER_HORIZONTAL;
} else {
// Otherwise, add an empty view to the start as padding (but still scroll edge to edge).
View leftPaddingView = LayoutInflater.from(getContext()).inflate(
R.layout.widget_list_divider, widgetRow, false);
leftPaddingView.getLayoutParams().width = ResourceUtils.pxFromDp(
16, getResources().getDisplayMetrics());
widgetCells.addView(leftPaddingView, 0);
}
}
private void addDivider(ViewGroup parent) {
LayoutInflater.from(getContext()).inflate(R.layout.widget_list_divider, parent, true);
WidgetsTableUtils.groupWidgetItemsIntoTable(widgets, mMaxHorizontalSpan).forEach(row -> {
TableRow tableRow = new TableRow(getContext());
row.forEach(widgetItem -> {
WidgetCell widget = addItemCell(tableRow);
widget.setPreviewSize(widgetItem.spanX, widgetItem.spanY);
widget.applyFromCellItem(widgetItem, LauncherAppState.getInstance(mLauncher)
.getWidgetCache());
widget.ensurePreview();
widget.setVisibility(View.VISIBLE);
});
widgetsTable.addView(tableRow);
});
}
protected WidgetCell addItemCell(ViewGroup parent) {

View File

@@ -198,8 +198,9 @@ public class WidgetsFullSheet extends BaseWidgetSheet
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
MeasureSpec.getSize(heightMeasureSpec));
int maxSpansPerRow = getMeasuredWidth() / (deviceProfile.cellWidthPx
+ deviceProfile.workspaceCellPaddingXPx);
int paddingPx = 2 * getResources().getDimensionPixelOffset(
R.dimen.widget_cell_horizontal_padding);
int maxSpansPerRow = getMeasuredWidth() / (deviceProfile.cellWidthPx + paddingPx);
mAdapters.get(AdapterHolder.PRIMARY).mWidgetsListAdapter.setMaxHorizontalSpansPerRow(
maxSpansPerRow);
if (mHasWorkProfile) {

View File

@@ -112,7 +112,9 @@ public final class WidgetsListTableViewHolderBinder
TableRow row = (TableRow) table.getChildAt(i);
row.setVisibility(View.VISIBLE);
WidgetCell widget = (WidgetCell) row.getChildAt(j);
widget.clear();
WidgetItem widgetItem = widgetItemsPerRow.get(j);
widget.setPreviewSize(widgetItem.spanX, widgetItem.spanY);
widget.applyFromCellItem(widgetItem, mWidgetPreviewLoader);
widget.setApplyBitmapDeferred(mApplyBitmapDeferred);
widget.ensurePreview();