summaryrefslogtreecommitdiff
path: root/java/src
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2022-12-16 22:19:31 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-12-16 22:19:31 +0000
commit2ce213c2243c1240cd64b7c44fed750695b4a17d (patch)
tree2ffddc2c7dec95286cfa34882c79815f5f4340fd /java/src
parent4ebf21f578b78ed83de87f829c4a126c9bb40759 (diff)
parent1d4f1782d24d8d881713de4e3ad9ca9156913455 (diff)
Merge "Create an action row view" into tm-qpr-dev
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/intentresolver/ChooserActivity.java95
-rw-r--r--java/src/com/android/intentresolver/ChooserContentPreviewUi.java123
-rw-r--r--java/src/com/android/intentresolver/widget/ActionRow.kt93
3 files changed, 200 insertions, 111 deletions
diff --git a/java/src/com/android/intentresolver/ChooserActivity.java b/java/src/com/android/intentresolver/ChooserActivity.java
index 6d5304d9..6cf1aef4 100644
--- a/java/src/com/android/intentresolver/ChooserActivity.java
+++ b/java/src/com/android/intentresolver/ChooserActivity.java
@@ -77,7 +77,6 @@ import android.util.Log;
import android.util.Size;
import android.util.Slog;
import android.util.SparseArray;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
@@ -86,7 +85,6 @@ import android.view.WindowInsets;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
-import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.MainThread;
@@ -97,7 +95,6 @@ import androidx.viewpager.widget.ViewPager;
import com.android.intentresolver.AbstractMultiProfilePagerAdapter.EmptyState;
import com.android.intentresolver.AbstractMultiProfilePagerAdapter.EmptyStateProvider;
import com.android.intentresolver.NoCrossProfileEmptyStateProvider.DevicePolicyBlockerEmptyState;
-import com.android.intentresolver.ResolverListAdapter.ViewHolder;
import com.android.intentresolver.chooser.DisplayResolveInfo;
import com.android.intentresolver.chooser.MultiDisplayResolveInfo;
import com.android.intentresolver.chooser.TargetInfo;
@@ -108,6 +105,7 @@ import com.android.intentresolver.model.AppPredictionServiceResolverComparator;
import com.android.intentresolver.model.ResolverRankerServiceResolverComparator;
import com.android.intentresolver.shortcuts.AppPredictorFactory;
import com.android.intentresolver.shortcuts.ShortcutLoader;
+import com.android.intentresolver.widget.ActionRow;
import com.android.intentresolver.widget.ResolverDrawerLayout;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
@@ -629,7 +627,7 @@ public class ChooserActivity extends ResolverActivity implements
updateProfileViewButton();
}
- private void onCopyButtonClicked(View v) {
+ private void onCopyButtonClicked() {
Intent targetIntent = getTargetIntent();
if (targetIntent == null) {
finish();
@@ -752,21 +750,23 @@ public class ChooserActivity extends ResolverActivity implements
int previewType = ChooserContentPreviewUi.findPreferredContentPreview(
targetIntent, getContentResolver(), this::isImageType);
- ChooserContentPreviewUi.ActionButtonFactory buttonFactory =
- new ChooserContentPreviewUi.ActionButtonFactory() {
+ ChooserContentPreviewUi.ActionFactory actionFactory =
+ new ChooserContentPreviewUi.ActionFactory() {
@Override
- public Button createCopyButton() {
- return ChooserActivity.this.createCopyButton();
+ public ActionRow.Action createCopyButton() {
+ return ChooserActivity.this.createCopyAction();
}
+ @Nullable
@Override
- public Button createEditButton() {
- return ChooserActivity.this.createEditButton(targetIntent);
+ public ActionRow.Action createEditButton() {
+ return ChooserActivity.this.createEditAction(targetIntent);
}
+ @Nullable
@Override
- public Button createNearbyButton() {
- return ChooserActivity.this.createNearbyButton(targetIntent);
+ public ActionRow.Action createNearbyButton() {
+ return ChooserActivity.this.createNearbyAction(targetIntent);
}
};
@@ -775,7 +775,7 @@ public class ChooserActivity extends ResolverActivity implements
targetIntent,
getResources(),
getLayoutInflater(),
- buttonFactory,
+ actionFactory,
parent,
previewCoordinator,
getContentResolver(),
@@ -902,54 +902,46 @@ public class ChooserActivity extends ResolverActivity implements
return dri;
}
- private Button createActionButton(Drawable icon, CharSequence title, View.OnClickListener r) {
- Button b = (Button) LayoutInflater.from(this).inflate(R.layout.chooser_action_button, null);
- if (icon != null) {
- final int size = getResources()
- .getDimensionPixelSize(R.dimen.chooser_action_button_icon_size);
- icon.setBounds(0, 0, size, size);
- b.setCompoundDrawablesRelative(icon, null, null, null);
- }
- b.setText(title);
- b.setOnClickListener(r);
- return b;
- }
-
- private Button createCopyButton() {
- final Button b = createActionButton(
+ private ActionRow.Action createCopyAction() {
+ return new ActionRow.Action(
+ com.android.internal.R.id.chooser_copy_button,
+ getString(com.android.internal.R.string.copy),
getDrawable(com.android.internal.R.drawable.ic_menu_copy_material),
- getString(com.android.internal.R.string.copy), this::onCopyButtonClicked);
- b.setId(com.android.internal.R.id.chooser_copy_button);
- return b;
+ this::onCopyButtonClicked);
}
- private @Nullable Button createNearbyButton(Intent originalIntent) {
+ @Nullable
+ private ActionRow.Action createNearbyAction(Intent originalIntent) {
final TargetInfo ti = getNearbySharingTarget(originalIntent);
- if (ti == null) return null;
+ if (ti == null) {
+ return null;
+ }
- final Button b = createActionButton(
- ti.getDisplayIconHolder().getDisplayIcon(),
+ return new ActionRow.Action(
+ com.android.internal.R.id.chooser_nearby_button,
ti.getDisplayLabel(),
- (View unused) -> {
+ ti.getDisplayIconHolder().getDisplayIcon(),
+ () -> {
getChooserActivityLogger().logActionSelected(
ChooserActivityLogger.SELECTION_TYPE_NEARBY);
// Action bar is user-independent, always start as primary
safelyStartActivityAsUser(ti, getPersonalProfileUserHandle());
finish();
- }
- );
- b.setId(com.android.internal.R.id.chooser_nearby_button);
- return b;
+ });
}
- private @Nullable Button createEditButton(Intent originalIntent) {
+ @Nullable
+ private ActionRow.Action createEditAction(Intent originalIntent) {
final TargetInfo ti = getEditSharingTarget(originalIntent);
- if (ti == null) return null;
+ if (ti == null) {
+ return null;
+ }
- final Button b = createActionButton(
- ti.getDisplayIconHolder().getDisplayIcon(),
+ return new ActionRow.Action(
+ com.android.internal.R.id.chooser_edit_button,
ti.getDisplayLabel(),
- (View unused) -> {
+ ti.getDisplayIconHolder().getDisplayIcon(),
+ () -> {
// Log share completion via edit
getChooserActivityLogger().logActionSelected(
ChooserActivityLogger.SELECTION_TYPE_EDIT);
@@ -967,8 +959,6 @@ public class ChooserActivity extends ResolverActivity implements
}
}
);
- b.setId(com.android.internal.R.id.chooser_edit_button);
- return b;
}
@Nullable
@@ -977,17 +967,6 @@ public class ChooserActivity extends ResolverActivity implements
return firstImage != null && firstImage.isVisibleToUser() ? firstImage : null;
}
- private void addActionButton(ViewGroup parent, Button b) {
- if (b == null) return;
- final ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams(
- LayoutParams.WRAP_CONTENT,
- LayoutParams.WRAP_CONTENT
- );
- final int gap = getResources().getDimensionPixelSize(R.dimen.resolver_icon_margin) / 2;
- lp.setMarginsRelative(gap, 0, gap, 0);
- parent.addView(b, lp);
- }
-
/**
* Wrapping the ContentResolver call to expose for easier mocking,
* and to avoid mocking Android core classes.
diff --git a/java/src/com/android/intentresolver/ChooserContentPreviewUi.java b/java/src/com/android/intentresolver/ChooserContentPreviewUi.java
index 22ff55db..f9f4ee98 100644
--- a/java/src/com/android/intentresolver/ChooserContentPreviewUi.java
+++ b/java/src/com/android/intentresolver/ChooserContentPreviewUi.java
@@ -34,11 +34,12 @@ import android.util.PluralsMessageFormatter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
+import androidx.annotation.Nullable;
+
+import com.android.intentresolver.widget.ActionRow;
import com.android.intentresolver.widget.RoundedRectImageView;
import com.android.internal.annotations.VisibleForTesting;
@@ -88,15 +89,17 @@ public final class ChooserContentPreviewUi {
* they're determined to be appropriate for the particular preview we display.
* TODO: clarify why action buttons are part of preview logic.
*/
- public interface ActionButtonFactory {
- /** Create a button that copies the share content to the clipboard. */
- Button createCopyButton();
+ public interface ActionFactory {
+ /** Create an action that copies the share content to the clipboard. */
+ ActionRow.Action createCopyButton();
- /** Create a button that opens the share content in a system-default editor. */
- Button createEditButton();
+ /** Create an action that opens the share content in a system-default editor. */
+ @Nullable
+ ActionRow.Action createEditButton();
- /** Create a "Share to Nearby" button. */
- Button createNearbyButton();
+ /** Create an "Share to Nearby" action. */
+ @Nullable
+ ActionRow.Action createNearbyButton();
}
/**
@@ -173,7 +176,7 @@ public final class ChooserContentPreviewUi {
Intent targetIntent,
Resources resources,
LayoutInflater layoutInflater,
- ActionButtonFactory buttonFactory,
+ ActionFactory actionFactory,
ViewGroup parent,
ContentPreviewCoordinator previewCoord,
ContentResolver contentResolver,
@@ -184,18 +187,16 @@ public final class ChooserContentPreviewUi {
case CONTENT_PREVIEW_TEXT:
layout = displayTextContentPreview(
targetIntent,
- resources,
layoutInflater,
- buttonFactory,
+ createTextPreviewActions(actionFactory),
parent,
previewCoord);
break;
case CONTENT_PREVIEW_IMAGE:
layout = displayImageContentPreview(
targetIntent,
- resources,
layoutInflater,
- buttonFactory,
+ createImagePreviewActions(actionFactory),
parent,
previewCoord,
contentResolver,
@@ -206,7 +207,7 @@ public final class ChooserContentPreviewUi {
targetIntent,
resources,
layoutInflater,
- buttonFactory,
+ createFilePreviewActions(actionFactory),
parent,
previewCoord,
contentResolver);
@@ -235,20 +236,18 @@ public final class ChooserContentPreviewUi {
private static ViewGroup displayTextContentPreview(
Intent targetIntent,
- Resources resources,
LayoutInflater layoutInflater,
- ActionButtonFactory buttonFactory,
+ List<ActionRow.Action> actions,
ViewGroup parent,
ContentPreviewCoordinator previewCoord) {
ViewGroup contentPreviewLayout = (ViewGroup) layoutInflater.inflate(
R.layout.chooser_grid_preview_text, parent, false);
- final ViewGroup actionRow =
- (ViewGroup) contentPreviewLayout.findViewById(
- com.android.internal.R.id.chooser_action_row);
- final int iconMargin = resources.getDimensionPixelSize(R.dimen.resolver_icon_margin);
- addActionButton(actionRow, buttonFactory.createCopyButton(), iconMargin);
- addActionButton(actionRow, buttonFactory.createNearbyButton(), iconMargin);
+ final ActionRow actionRow =
+ contentPreviewLayout.findViewById(com.android.internal.R.id.chooser_action_row);
+ if (actionRow != null) {
+ actionRow.setActions(actions);
+ }
CharSequence sharingText = targetIntent.getCharSequenceExtra(Intent.EXTRA_TEXT);
if (sharingText == null) {
@@ -296,11 +295,20 @@ public final class ChooserContentPreviewUi {
return contentPreviewLayout;
}
+ private static List<ActionRow.Action> createTextPreviewActions(ActionFactory actionFactory) {
+ ArrayList<ActionRow.Action> actions = new ArrayList<>(2);
+ actions.add(actionFactory.createCopyButton());
+ ActionRow.Action nearbyAction = actionFactory.createNearbyButton();
+ if (nearbyAction != null) {
+ actions.add(nearbyAction);
+ }
+ return actions;
+ }
+
private static ViewGroup displayImageContentPreview(
Intent targetIntent,
- Resources resources,
LayoutInflater layoutInflater,
- ActionButtonFactory buttonFactory,
+ List<ActionRow.Action> actions,
ViewGroup parent,
ContentPreviewCoordinator previewCoord,
ContentResolver contentResolver,
@@ -310,13 +318,11 @@ public final class ChooserContentPreviewUi {
ViewGroup imagePreview = contentPreviewLayout.findViewById(
com.android.internal.R.id.content_preview_image_area);
- final ViewGroup actionRow =
- (ViewGroup) contentPreviewLayout.findViewById(
- com.android.internal.R.id.chooser_action_row);
- final int iconMargin = resources.getDimensionPixelSize(R.dimen.resolver_icon_margin);
- //TODO: addActionButton(actionRow, buttonFactory.createCopyButton(), iconMargin);
- addActionButton(actionRow, buttonFactory.createNearbyButton(), iconMargin);
- addActionButton(actionRow, buttonFactory.createEditButton(), iconMargin);
+ final ActionRow actionRow =
+ contentPreviewLayout.findViewById(com.android.internal.R.id.chooser_action_row);
+ if (actionRow != null) {
+ actionRow.setActions(actions);
+ }
String action = targetIntent.getAction();
if (Intent.ACTION_SEND.equals(action)) {
@@ -375,24 +381,37 @@ public final class ChooserContentPreviewUi {
return contentPreviewLayout;
}
+ private static List<ActionRow.Action> createImagePreviewActions(
+ ActionFactory buttonFactory) {
+ ArrayList<ActionRow.Action> actions = new ArrayList<>(2);
+ //TODO: add copy action;
+ ActionRow.Action action = buttonFactory.createNearbyButton();
+ if (action != null) {
+ actions.add(action);
+ }
+ action = buttonFactory.createEditButton();
+ if (action != null) {
+ actions.add(action);
+ }
+ return actions;
+ }
+
private static ViewGroup displayFileContentPreview(
Intent targetIntent,
Resources resources,
LayoutInflater layoutInflater,
- ActionButtonFactory buttonFactory,
+ List<ActionRow.Action> actions,
ViewGroup parent,
ContentPreviewCoordinator previewCoord,
ContentResolver contentResolver) {
ViewGroup contentPreviewLayout = (ViewGroup) layoutInflater.inflate(
R.layout.chooser_grid_preview_file, parent, false);
- final ViewGroup actionRow =
- (ViewGroup) contentPreviewLayout.findViewById(
- com.android.internal.R.id.chooser_action_row);
- final int iconMargin = resources.getDimensionPixelSize(R.dimen.resolver_icon_margin);
- //TODO(b/120417119):
- // addActionButton(actionRow, buttonFactory.createCopyButton(), iconMargin);
- addActionButton(actionRow, buttonFactory.createNearbyButton(), iconMargin);
+ final ActionRow actionRow =
+ contentPreviewLayout.findViewById(com.android.internal.R.id.chooser_action_row);
+ if (actionRow != null) {
+ actionRow.setActions(actions);
+ }
String action = targetIntent.getAction();
if (Intent.ACTION_SEND.equals(action)) {
@@ -438,6 +457,17 @@ public final class ChooserContentPreviewUi {
return contentPreviewLayout;
}
+ private static List<ActionRow.Action> createFilePreviewActions(ActionFactory actionFactory) {
+ List<ActionRow.Action> actions = new ArrayList<>(1);
+ //TODO(b/120417119):
+ // add action buttonFactory.createCopyButton()
+ ActionRow.Action action = actionFactory.createNearbyButton();
+ if (action != null) {
+ actions.add(action);
+ }
+ return actions;
+ }
+
private static void logContentPreviewWarning(Uri uri) {
// The ContentResolver already logs the exception. Log something more informative.
Log.w(TAG, "Could not load (" + uri.toString() + ") thumbnail/name for preview. If "
@@ -475,19 +505,6 @@ public final class ChooserContentPreviewUi {
}
}
- private static void addActionButton(ViewGroup parent, Button b, int iconMargin) {
- if (b == null) {
- return;
- }
- final ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams(
- LayoutParams.WRAP_CONTENT,
- LayoutParams.WRAP_CONTENT
- );
- final int gap = iconMargin / 2;
- lp.setMarginsRelative(gap, 0, gap, 0);
- parent.addView(b, lp);
- }
-
private static FileInfo extractFileInfo(Uri uri, ContentResolver resolver) {
String fileName = null;
boolean hasThumbnail = false;
diff --git a/java/src/com/android/intentresolver/widget/ActionRow.kt b/java/src/com/android/intentresolver/widget/ActionRow.kt
new file mode 100644
index 00000000..1be48f34
--- /dev/null
+++ b/java/src/com/android/intentresolver/widget/ActionRow.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2022 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.intentresolver.widget
+
+import android.annotation.LayoutRes
+import android.content.Context
+import android.content.res.Resources.ID_NULL
+import android.graphics.drawable.Drawable
+import android.os.Parcelable
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.widget.Button
+import android.widget.LinearLayout
+import com.android.intentresolver.R
+
+// TODO: extract an interface out of the class, use it in layout hierarchy an have a layout inflater
+// to instantiate the right view based on a flag value.
+class ActionRow : LinearLayout {
+ constructor(context: Context) : this(context, null)
+ constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
+ constructor(
+ context: Context, attrs: AttributeSet?, defStyleAttr: Int
+ ) : this(context, attrs, defStyleAttr, 0)
+
+ constructor(
+ context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int
+ ) : super(context, attrs, defStyleAttr, defStyleRes) {
+ orientation = HORIZONTAL
+ }
+
+ @LayoutRes
+ private val itemLayout = R.layout.chooser_action_button
+ private val itemMargin =
+ context.resources.getDimensionPixelSize(R.dimen.resolver_icon_margin) / 2
+ private var actions: List<Action> = emptyList()
+
+ override fun onRestoreInstanceState(state: Parcelable?) {
+ super.onRestoreInstanceState(state)
+ setActions(actions)
+ }
+
+ fun setActions(actions: List<Action>) {
+ removeAllViews()
+ this.actions = ArrayList(actions)
+ for (action in actions) {
+ addAction(action)
+ }
+ }
+
+ private fun addAction(action: Action) {
+ val b = LayoutInflater.from(context).inflate(itemLayout, null) as Button
+ if (action.icon != null) {
+ val size = resources
+ .getDimensionPixelSize(R.dimen.chooser_action_button_icon_size)
+ action.icon.setBounds(0, 0, size, size)
+ b.setCompoundDrawablesRelative(action.icon, null, null, null)
+ }
+ b.text = action.label ?: ""
+ b.setOnClickListener {
+ action.onClicked.run()
+ }
+ b.id = action.id
+ addView(b)
+ }
+
+ override fun generateDefaultLayoutParams(): LayoutParams =
+ super.generateDefaultLayoutParams().apply {
+ setMarginsRelative(itemMargin, 0, itemMargin, 0)
+ }
+
+ class Action @JvmOverloads constructor(
+ // TODO: apparently, IDs set to this field are used in unit tests only; evaluate whether we
+ // get rid of them
+ val id: Int = ID_NULL,
+ val label: CharSequence?,
+ val icon: Drawable?,
+ val onClicked: Runnable,
+ )
+}