diff options
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/app/slice/Slice.java | 15 | ||||
| -rw-r--r-- | core/java/android/app/slice/widget/GridView.java | 6 | ||||
| -rw-r--r-- | core/java/android/app/slice/widget/LargeTemplateView.java | 15 | ||||
| -rw-r--r-- | core/java/android/app/slice/widget/ShortcutView.java | 99 | ||||
| -rw-r--r-- | core/java/android/app/slice/widget/SliceView.java | 4 | ||||
| -rw-r--r-- | core/java/android/app/slice/widget/SliceViewUtil.java | 16 |
6 files changed, 135 insertions, 20 deletions
diff --git a/core/java/android/app/slice/Slice.java b/core/java/android/app/slice/Slice.java index f6b6b869ae0f..1ce89d2a009b 100644 --- a/core/java/android/app/slice/Slice.java +++ b/core/java/android/app/slice/Slice.java @@ -21,6 +21,7 @@ import android.annotation.Nullable; import android.annotation.StringDef; import android.app.PendingIntent; import android.app.RemoteInput; +import android.app.slice.widget.SliceView; import android.content.ContentResolver; import android.content.IContentProvider; import android.graphics.drawable.Icon; @@ -54,7 +55,12 @@ public final class Slice implements Parcelable { public @interface SliceHint{ } /** - * Hint that this content is a title of other content in the slice. + * Hint that this content is a title of other content in the slice. This can also indicate that + * the content should be used in the shortcut representation of the slice (icon, label, action), + * normally this should be indicated by adding the hint on the action containing that content. + * + * @see SliceView#MODE_SHORTCUT + * @see SliceItem#TYPE_ACTION */ public static final String HINT_TITLE = "title"; /** @@ -100,6 +106,13 @@ public final class Slice implements Parcelable { */ public static final String HINT_NO_TINT = "no_tint"; /** + * Hint to indicate that this content should not be shown in the {@link SliceView#MODE_SMALL} + * and {@link SliceView#MODE_LARGE} modes of SliceView. This content may be used to populate + * the {@link SliceView#MODE_SHORTCUT} format of the slice. + * @hide + */ + public static final String HINT_HIDDEN = "hidden"; + /** * Hint to indicate that this slice is incomplete and an update will be sent once * loading is complete. Slices which contain HINT_PARTIAL will not be cached by the * OS and should not be cached by apps. diff --git a/core/java/android/app/slice/widget/GridView.java b/core/java/android/app/slice/widget/GridView.java index 67a3c671ba0c..793abc05a489 100644 --- a/core/java/android/app/slice/widget/GridView.java +++ b/core/java/android/app/slice/widget/GridView.java @@ -126,6 +126,9 @@ public class GridView extends LinearLayout implements SliceListView { * Returns true if this item is just an image. */ private boolean addItem(SliceItem item) { + if (item.hasHint(Slice.HINT_HIDDEN)) { + return false; + } if (item.getType() == SliceItem.TYPE_IMAGE) { ImageView v = new ImageView(getContext()); v.setImageIcon(item.getIcon()); @@ -145,6 +148,9 @@ public class GridView extends LinearLayout implements SliceListView { items.addAll(item.getSlice().getItems()); } items.forEach(i -> { + if (i.hasHint(Slice.HINT_HIDDEN)) { + return; + } Context context = getContext(); switch (i.getType()) { case SliceItem.TYPE_TEXT: diff --git a/core/java/android/app/slice/widget/LargeTemplateView.java b/core/java/android/app/slice/widget/LargeTemplateView.java index f45b2a8f6671..788f6fb6d10a 100644 --- a/core/java/android/app/slice/widget/LargeTemplateView.java +++ b/core/java/android/app/slice/widget/LargeTemplateView.java @@ -85,9 +85,14 @@ public class LargeTemplateView extends SliceModeView { addList(slice, items); } else { slice.getItems().forEach(item -> { - if (item.hasHint(Slice.HINT_ACTIONS)) { + if (item.hasHint(Slice.HINT_HIDDEN)) { + // If it's hidden we don't show it + return; + } else if (item.hasHint(Slice.HINT_ACTIONS)) { + // Action groups don't show in lists return; } else if (item.getType() == SliceItem.TYPE_COLOR) { + // A color is not a list item return; } else if (item.getType() == SliceItem.TYPE_SLICE && item.hasHint(Slice.HINT_LIST)) { @@ -108,8 +113,12 @@ public class LargeTemplateView extends SliceModeView { private void addList(Slice slice, List<SliceItem> items) { List<SliceItem> sliceItems = slice.getItems(); - sliceItems.forEach(i -> i.addHint(Slice.HINT_LIST_ITEM)); - items.addAll(sliceItems); + sliceItems.forEach(i -> { + if (!i.hasHint(Slice.HINT_HIDDEN) && i.getType() != SliceItem.TYPE_COLOR) { + i.addHint(Slice.HINT_LIST_ITEM); + items.add(i); + } + }); } /** diff --git a/core/java/android/app/slice/widget/ShortcutView.java b/core/java/android/app/slice/widget/ShortcutView.java index 0bca8ce283cc..0b7ad0d667dd 100644 --- a/core/java/android/app/slice/widget/ShortcutView.java +++ b/core/java/android/app/slice/widget/ShortcutView.java @@ -24,13 +24,20 @@ import android.app.slice.SliceQuery; import android.app.slice.widget.SliceView.SliceModeView; import android.content.Context; import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.ProviderInfo; +import android.content.res.Resources; import android.graphics.Color; +import android.graphics.drawable.Drawable; import android.graphics.drawable.ShapeDrawable; import android.graphics.drawable.shapes.OvalShape; import android.net.Uri; import com.android.internal.R; +import java.util.List; + /** * @hide */ @@ -38,27 +45,26 @@ public class ShortcutView extends SliceModeView { private static final String TAG = "ShortcutView"; - private PendingIntent mAction; private Uri mUri; + private PendingIntent mAction; + private SliceItem mLabel; + private SliceItem mIcon; + private int mLargeIconSize; private int mSmallIconSize; public ShortcutView(Context context) { super(context); - mSmallIconSize = getContext().getResources().getDimensionPixelSize(R.dimen.slice_icon_size); + final Resources res = getResources(); + mSmallIconSize = res.getDimensionPixelSize(R.dimen.slice_icon_size); + mLargeIconSize = res.getDimensionPixelSize(R.dimen.slice_shortcut_size); } @Override public void setSlice(Slice slice) { removeAllViews(); - SliceItem sliceItem = SliceQuery.find(slice, SliceItem.TYPE_ACTION); - SliceItem iconItem = SliceQuery.getPrimaryIcon(slice); - SliceItem textItem = sliceItem != null - ? SliceQuery.find(sliceItem, SliceItem.TYPE_TEXT) - : SliceQuery.find(slice, SliceItem.TYPE_TEXT); - SliceItem colorItem = sliceItem != null - ? SliceQuery.find(sliceItem, SliceItem.TYPE_COLOR) - : SliceQuery.find(slice, SliceItem.TYPE_COLOR); + determineShortcutItems(getContext(), slice); + SliceItem colorItem = SliceQuery.find(slice, SliceItem.TYPE_COLOR); if (colorItem == null) { colorItem = SliceQuery.find(slice, SliceItem.TYPE_COLOR); } @@ -67,13 +73,11 @@ public class ShortcutView extends SliceModeView { ShapeDrawable circle = new ShapeDrawable(new OvalShape()); circle.setTint(color); setBackground(circle); - if (iconItem != null) { - final boolean isLarge = iconItem.hasHint(Slice.HINT_LARGE); + if (mIcon != null) { + final boolean isLarge = mIcon.hasHint(Slice.HINT_LARGE); final int iconSize = isLarge ? mLargeIconSize : mSmallIconSize; - SliceViewUtil.createCircledIcon(getContext(), color, iconSize, iconItem.getIcon(), + SliceViewUtil.createCircledIcon(getContext(), color, iconSize, mIcon.getIcon(), isLarge, this /* parent */); - mAction = sliceItem != null ? sliceItem.getAction() - : null; mUri = slice.getUri(); setClickable(true); } else { @@ -103,4 +107,69 @@ public class ShortcutView extends SliceModeView { } return true; } + + /** + * Looks at the slice and determines which items are best to use to compose the shortcut. + */ + private void determineShortcutItems(Context context, Slice slice) { + List<String> h = slice.getHints(); + SliceItem sliceItem = new SliceItem(slice, SliceItem.TYPE_SLICE, + h.toArray(new String[h.size()])); + SliceItem titleItem = SliceQuery.find(slice, SliceItem.TYPE_ACTION, + Slice.HINT_TITLE, null); + + if (titleItem != null) { + // Preferred case: hinted action containing hinted image and text + mAction = titleItem.getAction(); + mIcon = SliceQuery.find(titleItem.getSlice(), SliceItem.TYPE_IMAGE, Slice.HINT_TITLE, + null); + mLabel = SliceQuery.find(titleItem.getSlice(), SliceItem.TYPE_TEXT, Slice.HINT_TITLE, + null); + } else { + // No hinted action; just use the first one + SliceItem actionItem = SliceQuery.find(sliceItem, SliceItem.TYPE_ACTION, (String) null, + null); + mAction = (actionItem != null) ? actionItem.getAction() : null; + } + // First fallback: any hinted image and text + if (mIcon == null) { + mIcon = SliceQuery.find(sliceItem, SliceItem.TYPE_IMAGE, Slice.HINT_TITLE, + null); + } + if (mLabel == null) { + mLabel = SliceQuery.find(sliceItem, SliceItem.TYPE_TEXT, Slice.HINT_TITLE, + null); + } + // Second fallback: first image and text + if (mIcon == null) { + mIcon = SliceQuery.find(sliceItem, SliceItem.TYPE_IMAGE, (String) null, + null); + } + if (mLabel == null) { + mLabel = SliceQuery.find(sliceItem, SliceItem.TYPE_TEXT, (String) null, + null); + } + // Final fallback: use app info + if (mIcon == null || mLabel == null || mAction == null) { + PackageManager pm = context.getPackageManager(); + ProviderInfo providerInfo = pm.resolveContentProvider( + slice.getUri().getAuthority(), 0); + ApplicationInfo appInfo = providerInfo.applicationInfo; + if (appInfo != null) { + if (mIcon == null) { + Drawable icon = appInfo.loadDefaultIcon(pm); + mIcon = new SliceItem(SliceViewUtil.createIconFromDrawable(icon), + SliceItem.TYPE_IMAGE, new String[] {Slice.HINT_LARGE}); + } + if (mLabel == null) { + mLabel = new SliceItem(pm.getApplicationLabel(appInfo), + SliceItem.TYPE_TEXT, null); + } + if (mAction == null) { + mAction = PendingIntent.getActivity(context, 0, + pm.getLaunchIntentForPackage(appInfo.packageName), 0); + } + } + } + } } diff --git a/core/java/android/app/slice/widget/SliceView.java b/core/java/android/app/slice/widget/SliceView.java index 5bafbc03cac6..c5835620c595 100644 --- a/core/java/android/app/slice/widget/SliceView.java +++ b/core/java/android/app/slice/widget/SliceView.java @@ -115,7 +115,9 @@ public class SliceView extends ViewGroup { */ public static final String MODE_LARGE = "SLICE_LARGE"; /** - * Mode indicating this slice should be presented as an icon. + * Mode indicating this slice should be presented as an icon. A shortcut requires an intent, + * icon, and label. This can be indicated by using {@link Slice#HINT_TITLE} on an action in a + * slice. */ public static final String MODE_SHORTCUT = "SLICE_ICON"; diff --git a/core/java/android/app/slice/widget/SliceViewUtil.java b/core/java/android/app/slice/widget/SliceViewUtil.java index 036699834927..1cf0055bcfe8 100644 --- a/core/java/android/app/slice/widget/SliceViewUtil.java +++ b/core/java/android/app/slice/widget/SliceViewUtil.java @@ -28,6 +28,7 @@ import android.graphics.Paint; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.view.Gravity; @@ -141,6 +142,21 @@ public class SliceViewUtil { /** * @hide */ + public static Icon createIconFromDrawable(Drawable d) { + if (d instanceof BitmapDrawable) { + return Icon.createWithBitmap(((BitmapDrawable) d).getBitmap()); + } + Bitmap b = Bitmap.createBitmap(d.getIntrinsicWidth(), d.getIntrinsicHeight(), + Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(b); + d.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + d.draw(canvas); + return Icon.createWithBitmap(b); + } + + /** + * @hide + */ public static void createCircledIcon(Context context, int color, int iconSize, Icon icon, boolean isLarge, ViewGroup parent) { ImageView v = new ImageView(context); |
