Add tap-to-add button to widget picker

This change introduces an "Add" button that appears when a widget
preview is clicked in the widget picker. This button disappears when the
preview is clicked again, or another preview is clicked. When the button
is pressed, it adds that widget to the picker. The add button is
available in the app-specific widget sheet as well.

Bug: 323886237
Test: Manual
Flag: ACONFIG com.android.launcher3.enable_widget_tap_to_add DEVELOPMENT

Change-Id: I86a8a4c22119960c54a885fd2efeb91916b4f9a0
This commit is contained in:
Willie Koomson
2024-02-08 19:16:07 +00:00
parent a51a749bc9
commit cdc26951ff
16 changed files with 303 additions and 43 deletions
@@ -18,6 +18,7 @@ package com.android.launcher3.widget;
import static android.appwidget.AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN;
import static com.android.launcher3.Flags.enableWidgetTapToAdd;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_TRAY;
import static com.android.launcher3.widget.LauncherAppWidgetProviderInfo.fromProviderInfo;
import static com.android.launcher3.widget.util.WidgetSizes.getWidgetItemSizePx;
@@ -36,6 +37,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -77,6 +79,7 @@ public class WidgetCell extends LinearLayout {
private static final boolean DEBUG = false;
private static final int FADE_IN_DURATION_MS = 90;
private static final int ADD_BUTTON_FADE_DURATION_MS = 300;
/**
* The requested scale of the preview container. It can be lower than this as well.
@@ -89,6 +92,8 @@ public class WidgetCell extends LinearLayout {
private TextView mWidgetName;
private TextView mWidgetDims;
private TextView mWidgetDescription;
private Button mWidgetAddButton;
private LinearLayout mWidgetTextContainer;
private WidgetItem mItem;
private Size mWidgetSize;
@@ -141,6 +146,11 @@ public class WidgetCell extends LinearLayout {
mWidgetName = findViewById(R.id.widget_name);
mWidgetDims = findViewById(R.id.widget_dims);
mWidgetDescription = findViewById(R.id.widget_description);
mWidgetTextContainer = findViewById(R.id.widget_text_container);
mWidgetAddButton = findViewById(R.id.widget_add_button);
if (enableWidgetTapToAdd()) {
mWidgetAddButton.setVisibility(INVISIBLE);
}
}
public void setRemoteViewsPreview(RemoteViews view) {
@@ -181,6 +191,10 @@ public class WidgetCell extends LinearLayout {
showDescription(true);
showDimensions(true);
if (enableWidgetTapToAdd()) {
hideAddButton(/* animate= */ false);
}
if (mActiveRequest != null) {
mActiveRequest.cancel();
mActiveRequest = null;
@@ -223,12 +237,8 @@ public class WidgetCell extends LinearLayout {
initPreviewContainerSizeAndScale();
mWidgetName.setText(mItem.label);
mWidgetName.setContentDescription(
context.getString(R.string.widget_preview_context_description, mItem.label));
mWidgetDims.setText(context.getString(R.string.widget_dims_format,
mItem.spanX, mItem.spanY));
mWidgetDims.setContentDescription(context.getString(
R.string.widget_accessible_dims_format, mItem.spanX, mItem.spanY));
if (!TextUtils.isEmpty(mItem.description)) {
mWidgetDescription.setText(mItem.description);
mWidgetDescription.setVisibility(VISIBLE);
@@ -236,6 +246,14 @@ public class WidgetCell extends LinearLayout {
mWidgetDescription.setVisibility(GONE);
}
// Setting the content description on the WidgetCell itself ensures that it remains
// screen reader focusable when the add button is showing and the text is hidden.
setContentDescription(createContentDescription(context));
if (mWidgetAddButton != null) {
mWidgetAddButton.setContentDescription(context.getString(
R.string.widget_add_button_content_description, mItem.label));
}
if (item.activityInfo != null) {
setTag(new PendingAddShortcutInfo(item.activityInfo));
} else {
@@ -285,6 +303,16 @@ public class WidgetCell extends LinearLayout {
mPreviewContainerScale = Math.min(scaleX, scaleY);
}
private String createContentDescription(Context context) {
String contentDescription =
context.getString(R.string.widget_preview_name_and_dims_content_description,
mItem.label, mItem.spanX, mItem.spanY);
if (!TextUtils.isEmpty(mItem.description)) {
contentDescription += " " + mItem.description;
}
return contentDescription;
}
private void setAppWidgetHostViewPreview(
NavigableAppWidgetHostView appWidgetHostViewPreview,
LauncherAppWidgetProviderInfo providerInfo,
@@ -517,4 +545,55 @@ public class WidgetCell extends LinearLayout {
mIconLoadRequest = null;
}
}
/**
* Show tap to add button.
* @param callback Callback to be set on the button.
*/
public void showAddButton(View.OnClickListener callback) {
mWidgetAddButton.setAlpha(0F);
mWidgetAddButton.setVisibility(VISIBLE);
mWidgetAddButton.setOnClickListener(callback);
mWidgetAddButton.animate().cancel();
mWidgetAddButton.animate()
.alpha(1F)
.setDuration(ADD_BUTTON_FADE_DURATION_MS);
mWidgetTextContainer.animate().cancel();
mWidgetTextContainer.animate()
.alpha(0F)
.setDuration(ADD_BUTTON_FADE_DURATION_MS)
.withEndAction(() -> {
mWidgetTextContainer.setVisibility(INVISIBLE);
});
}
/**
* Hide tap to add button.
*/
public void hideAddButton(boolean animate) {
mWidgetAddButton.setOnClickListener(null);
mWidgetAddButton.animate().cancel();
mWidgetTextContainer.animate().cancel();
if (!animate) {
mWidgetAddButton.setVisibility(INVISIBLE);
mWidgetTextContainer.setVisibility(VISIBLE);
mWidgetTextContainer.setAlpha(1F);
return;
}
mWidgetAddButton.animate()
.alpha(0F)
.setDuration(ADD_BUTTON_FADE_DURATION_MS)
.withEndAction(() -> {
mWidgetAddButton.setVisibility(INVISIBLE);
});
mWidgetTextContainer.setAlpha(0F);
mWidgetTextContainer.setVisibility(VISIBLE);
mWidgetTextContainer.animate()
.alpha(1F)
.setDuration(ADD_BUTTON_FADE_DURATION_MS);
}
}