Merge "Remove SliceView (its moving to support)"
diff --git a/api/current.txt b/api/current.txt
index b1ca3e8..c6d5430 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7053,27 +7053,6 @@
}
-package android.app.slice.widget {
-
- public class SliceView extends android.view.ViewGroup {
- ctor public SliceView(android.content.Context);
- ctor public SliceView(android.content.Context, android.util.AttributeSet);
- ctor public SliceView(android.content.Context, android.util.AttributeSet, int);
- ctor public SliceView(android.content.Context, android.util.AttributeSet, int, int);
- method public void clearSlice();
- method public java.lang.String getMode();
- method protected void onLayout(boolean, int, int, int, int);
- method public void setMode(java.lang.String);
- method public void setScrollable(boolean);
- method public boolean setSlice(android.net.Uri);
- method public void showSlice(android.app.slice.Slice);
- field public static final java.lang.String MODE_LARGE = "SLICE_LARGE";
- field public static final java.lang.String MODE_SHORTCUT = "SLICE_ICON";
- field public static final java.lang.String MODE_SMALL = "SLICE_SMALL";
- }
-
-}
-
package android.app.usage {
public final class ConfigurationStats implements android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index 592bd3d..94e3786 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -7497,27 +7497,6 @@
}
-package android.app.slice.widget {
-
- public class SliceView extends android.view.ViewGroup {
- ctor public SliceView(android.content.Context);
- ctor public SliceView(android.content.Context, android.util.AttributeSet);
- ctor public SliceView(android.content.Context, android.util.AttributeSet, int);
- ctor public SliceView(android.content.Context, android.util.AttributeSet, int, int);
- method public void clearSlice();
- method public java.lang.String getMode();
- method protected void onLayout(boolean, int, int, int, int);
- method public void setMode(java.lang.String);
- method public void setScrollable(boolean);
- method public boolean setSlice(android.net.Uri);
- method public void showSlice(android.app.slice.Slice);
- field public static final java.lang.String MODE_LARGE = "SLICE_LARGE";
- field public static final java.lang.String MODE_SHORTCUT = "SLICE_ICON";
- field public static final java.lang.String MODE_SMALL = "SLICE_SMALL";
- }
-
-}
-
package android.app.usage {
public final class CacheQuotaHint implements android.os.Parcelable {
diff --git a/api/test-current.txt b/api/test-current.txt
index 98615ee..aebf380 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -7127,27 +7127,6 @@
}
-package android.app.slice.widget {
-
- public class SliceView extends android.view.ViewGroup {
- ctor public SliceView(android.content.Context);
- ctor public SliceView(android.content.Context, android.util.AttributeSet);
- ctor public SliceView(android.content.Context, android.util.AttributeSet, int);
- ctor public SliceView(android.content.Context, android.util.AttributeSet, int, int);
- method public void clearSlice();
- method public java.lang.String getMode();
- method protected void onLayout(boolean, int, int, int, int);
- method public void setMode(java.lang.String);
- method public void setScrollable(boolean);
- method public boolean setSlice(android.net.Uri);
- method public void showSlice(android.app.slice.Slice);
- field public static final java.lang.String MODE_LARGE = "SLICE_LARGE";
- field public static final java.lang.String MODE_SHORTCUT = "SLICE_ICON";
- field public static final java.lang.String MODE_SMALL = "SLICE_SMALL";
- }
-
-}
-
package android.app.usage {
public final class ConfigurationStats implements android.os.Parcelable {
diff --git a/core/java/android/app/slice/Slice.java b/core/java/android/app/slice/Slice.java
index 616a5be..a4aeb67 100644
--- a/core/java/android/app/slice/Slice.java
+++ b/core/java/android/app/slice/Slice.java
@@ -62,7 +62,6 @@
* 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";
@@ -109,9 +108,9 @@
*/
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.
+ * Hint to indicate that this content should not be shown in larger renderings
+ * of Slices. This content may be used to populate the shortcut/icon
+ * format of the slice.
* @hide
*/
public static final String HINT_HIDDEN = "hidden";
diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java
index 05f4ce6..4f9c168 100644
--- a/core/java/android/app/slice/SliceProvider.java
+++ b/core/java/android/app/slice/SliceProvider.java
@@ -17,7 +17,6 @@
import android.Manifest.permission;
import android.annotation.NonNull;
-import android.app.slice.widget.SliceView;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
@@ -132,7 +131,6 @@
*
* @return Uri representing the slice associated with the provided intent.
* @see {@link Slice}
- * @see {@link SliceView#setSlice(Intent)}
*/
public @NonNull Uri onMapIntentToUri(Intent intent) {
throw new UnsupportedOperationException(
diff --git a/core/java/android/app/slice/widget/ActionRow.java b/core/java/android/app/slice/widget/ActionRow.java
deleted file mode 100644
index c96e6304..0000000
--- a/core/java/android/app/slice/widget/ActionRow.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (C) 2017 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 android.app.slice.widget;
-
-import android.app.PendingIntent;
-import android.app.PendingIntent.CanceledException;
-import android.app.RemoteInput;
-import android.app.slice.Slice;
-import android.app.slice.SliceItem;
-import android.app.slice.SliceQuery;
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.Color;
-import android.graphics.drawable.Icon;
-import android.os.AsyncTask;
-import android.util.TypedValue;
-import android.view.View;
-import android.view.ViewParent;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.ImageView.ScaleType;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-/**
- * @hide
- */
-public class ActionRow extends FrameLayout {
-
- private static final int MAX_ACTIONS = 5;
- private final int mSize;
- private final int mIconPadding;
- private final LinearLayout mActionsGroup;
- private final boolean mFullActions;
- private int mColor = Color.BLACK;
-
- public ActionRow(Context context, boolean fullActions) {
- super(context);
- mFullActions = fullActions;
- mSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 48,
- context.getResources().getDisplayMetrics());
- mIconPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12,
- context.getResources().getDisplayMetrics());
- mActionsGroup = new LinearLayout(context);
- mActionsGroup.setOrientation(LinearLayout.HORIZONTAL);
- mActionsGroup.setLayoutParams(
- new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
- addView(mActionsGroup);
- }
-
- private void setColor(int color) {
- mColor = color;
- for (int i = 0; i < mActionsGroup.getChildCount(); i++) {
- View view = mActionsGroup.getChildAt(i);
- SliceItem item = (SliceItem) view.getTag();
- boolean tint = !item.hasHint(Slice.HINT_NO_TINT);
- if (tint) {
- ((ImageView) view).setImageTintList(ColorStateList.valueOf(mColor));
- }
- }
- }
-
- private ImageView addAction(Icon icon, boolean allowTint, SliceItem image) {
- ImageView imageView = new ImageView(getContext());
- imageView.setPadding(mIconPadding, mIconPadding, mIconPadding, mIconPadding);
- imageView.setScaleType(ScaleType.FIT_CENTER);
- imageView.setImageIcon(icon);
- if (allowTint) {
- imageView.setImageTintList(ColorStateList.valueOf(mColor));
- }
- imageView.setBackground(SliceViewUtil.getDrawable(getContext(),
- android.R.attr.selectableItemBackground));
- imageView.setTag(image);
- addAction(imageView);
- return imageView;
- }
-
- /**
- * Set the actions and color for this action row.
- */
- public void setActions(SliceItem actionRow, SliceItem defColor) {
- removeAllViews();
- mActionsGroup.removeAllViews();
- addView(mActionsGroup);
-
- SliceItem color = SliceQuery.find(actionRow, SliceItem.TYPE_COLOR);
- if (color == null) {
- color = defColor;
- }
- if (color != null) {
- setColor(color.getColor());
- }
- SliceQuery.findAll(actionRow, SliceItem.TYPE_ACTION).forEach(action -> {
- if (mActionsGroup.getChildCount() >= MAX_ACTIONS) {
- return;
- }
- SliceItem image = SliceQuery.find(action, SliceItem.TYPE_IMAGE);
- if (image == null) {
- return;
- }
- boolean tint = !image.hasHint(Slice.HINT_NO_TINT);
- SliceItem input = SliceQuery.find(action, SliceItem.TYPE_REMOTE_INPUT);
- if (input != null && input.getRemoteInput().getAllowFreeFormInput()) {
- addAction(image.getIcon(), tint, image).setOnClickListener(
- v -> handleRemoteInputClick(v, action.getAction(), input.getRemoteInput()));
- createRemoteInputView(mColor, getContext());
- } else {
- addAction(image.getIcon(), tint, image).setOnClickListener(v -> AsyncTask.execute(
- () -> {
- try {
- action.getAction().send();
- } catch (CanceledException e) {
- e.printStackTrace();
- }
- }));
- }
- });
- setVisibility(getChildCount() != 0 ? View.VISIBLE : View.GONE);
- }
-
- private void addAction(View child) {
- mActionsGroup.addView(child, new LinearLayout.LayoutParams(mSize, mSize, 1));
- }
-
- private void createRemoteInputView(int color, Context context) {
- View riv = RemoteInputView.inflate(context, this);
- riv.setVisibility(View.INVISIBLE);
- addView(riv, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
- riv.setBackgroundColor(color);
- }
-
- private boolean handleRemoteInputClick(View view, PendingIntent pendingIntent,
- RemoteInput input) {
- if (input == null) {
- return false;
- }
-
- ViewParent p = view.getParent().getParent();
- RemoteInputView riv = null;
- while (p != null) {
- if (p instanceof View) {
- View pv = (View) p;
- riv = findRemoteInputView(pv);
- if (riv != null) {
- break;
- }
- }
- p = p.getParent();
- }
- if (riv == null) {
- return false;
- }
-
- int width = view.getWidth();
- if (view instanceof TextView) {
- // Center the reveal on the text which might be off-center from the TextView
- TextView tv = (TextView) view;
- if (tv.getLayout() != null) {
- int innerWidth = (int) tv.getLayout().getLineWidth(0);
- innerWidth += tv.getCompoundPaddingLeft() + tv.getCompoundPaddingRight();
- width = Math.min(width, innerWidth);
- }
- }
- int cx = view.getLeft() + width / 2;
- int cy = view.getTop() + view.getHeight() / 2;
- int w = riv.getWidth();
- int h = riv.getHeight();
- int r = Math.max(
- Math.max(cx + cy, cx + (h - cy)),
- Math.max((w - cx) + cy, (w - cx) + (h - cy)));
-
- riv.setRevealParameters(cx, cy, r);
- riv.setPendingIntent(pendingIntent);
- riv.setRemoteInput(new RemoteInput[] {
- input
- }, input);
- riv.focusAnimated();
- return true;
- }
-
- private RemoteInputView findRemoteInputView(View v) {
- if (v == null) {
- return null;
- }
- return (RemoteInputView) v.findViewWithTag(RemoteInputView.VIEW_TAG);
- }
-}
diff --git a/core/java/android/app/slice/widget/GridView.java b/core/java/android/app/slice/widget/GridView.java
deleted file mode 100644
index 793abc0..0000000
--- a/core/java/android/app/slice/widget/GridView.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (C) 2017 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 android.app.slice.widget;
-
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-
-import android.app.slice.Slice;
-import android.app.slice.SliceItem;
-import android.app.slice.widget.LargeSliceAdapter.SliceListView;
-import android.content.Context;
-import android.graphics.Color;
-import android.util.AttributeSet;
-import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.ImageView.ScaleType;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import com.android.internal.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @hide
- */
-public class GridView extends LinearLayout implements SliceListView {
-
- private static final String TAG = "GridView";
-
- private static final int MAX_IMAGES = 3;
- private static final int MAX_ALL = 5;
- private boolean mIsAllImages;
-
- public GridView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- if (mIsAllImages) {
- int width = MeasureSpec.getSize(widthMeasureSpec);
- int height = width / getChildCount();
- heightMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.EXACTLY,
- height);
- getLayoutParams().height = height;
- for (int i = 0; i < getChildCount(); i++) {
- getChildAt(i).getLayoutParams().height = height;
- }
- }
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
-
- @Override
- public void setSliceItem(SliceItem slice) {
- mIsAllImages = true;
- removeAllViews();
- int total = 1;
- if (slice.getType() == SliceItem.TYPE_SLICE) {
- List<SliceItem> items = slice.getSlice().getItems();
- total = items.size();
- for (int i = 0; i < total; i++) {
- SliceItem item = items.get(i);
- if (isFull()) {
- continue;
- }
- if (!addItem(item)) {
- mIsAllImages = false;
- }
- }
- } else {
- if (!isFull()) {
- if (!addItem(slice)) {
- mIsAllImages = false;
- }
- }
- }
- if (total > getChildCount() && mIsAllImages) {
- addExtraCount(total - getChildCount());
- }
- }
-
- private void addExtraCount(int numExtra) {
- View last = getChildAt(getChildCount() - 1);
- FrameLayout frame = new FrameLayout(getContext());
- frame.setLayoutParams(last.getLayoutParams());
-
- removeView(last);
- frame.addView(last, new LayoutParams(MATCH_PARENT, MATCH_PARENT));
-
- TextView v = new TextView(getContext());
- v.setTextColor(Color.WHITE);
- v.setBackgroundColor(0x4d000000);
- v.setText(getResources().getString(R.string.slice_more_content, numExtra));
- v.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18);
- v.setGravity(Gravity.CENTER);
- frame.addView(v, new LayoutParams(MATCH_PARENT, MATCH_PARENT));
-
- addView(frame);
- }
-
- private boolean isFull() {
- return getChildCount() >= (mIsAllImages ? MAX_IMAGES : MAX_ALL);
- }
-
- /**
- * 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());
- v.setScaleType(ScaleType.CENTER_CROP);
- addView(v, new LayoutParams(0, MATCH_PARENT, 1));
- return true;
- } else {
- LinearLayout v = new LinearLayout(getContext());
- int s = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
- 12, getContext().getResources().getDisplayMetrics());
- v.setPadding(0, s, 0, 0);
- v.setOrientation(LinearLayout.VERTICAL);
- v.setGravity(Gravity.CENTER_HORIZONTAL);
- // TODO: Unify sporadic inflates that happen throughout the code.
- ArrayList<SliceItem> items = new ArrayList<>();
- if (item.getType() == SliceItem.TYPE_SLICE) {
- 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:
- boolean title = false;
- if ((item.hasAnyHints(new String[] {
- Slice.HINT_LARGE, Slice.HINT_TITLE
- }))) {
- title = true;
- }
- TextView tv = (TextView) LayoutInflater.from(context).inflate(
- title ? R.layout.slice_title : R.layout.slice_secondary_text, null);
- tv.setText(i.getText());
- v.addView(tv);
- break;
- case SliceItem.TYPE_IMAGE:
- ImageView iv = new ImageView(context);
- iv.setImageIcon(i.getIcon());
- if (item.hasHint(Slice.HINT_LARGE)) {
- iv.setLayoutParams(new LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
- } else {
- int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
- 48, context.getResources().getDisplayMetrics());
- iv.setLayoutParams(new LayoutParams(size, size));
- }
- v.addView(iv);
- break;
- case SliceItem.TYPE_REMOTE_VIEW:
- v.addView(i.getRemoteView().apply(context, v));
- break;
- case SliceItem.TYPE_COLOR:
- // TODO: Support color to tint stuff here.
- break;
- }
- });
- addView(v, new LayoutParams(0, WRAP_CONTENT, 1));
- return false;
- }
- }
-}
diff --git a/core/java/android/app/slice/widget/LargeSliceAdapter.java b/core/java/android/app/slice/widget/LargeSliceAdapter.java
deleted file mode 100644
index 267fff6..0000000
--- a/core/java/android/app/slice/widget/LargeSliceAdapter.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (C) 2017 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 android.app.slice.widget;
-
-import android.app.slice.Slice;
-import android.app.slice.SliceItem;
-import android.app.slice.SliceQuery;
-import android.app.slice.widget.LargeSliceAdapter.SliceViewHolder;
-import android.content.Context;
-import android.util.ArrayMap;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.FrameLayout;
-
-import com.android.internal.R;
-import com.android.internal.widget.RecyclerView;
-import com.android.internal.widget.RecyclerView.ViewHolder;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * @hide
- */
-public class LargeSliceAdapter extends RecyclerView.Adapter<SliceViewHolder> {
-
- public static final int TYPE_DEFAULT = 1;
- public static final int TYPE_HEADER = 2;
- public static final int TYPE_GRID = 3;
- public static final int TYPE_MESSAGE = 4;
- public static final int TYPE_MESSAGE_LOCAL = 5;
- public static final int TYPE_REMOTE_VIEWS = 6;
-
- private final IdGenerator mIdGen = new IdGenerator();
- private final Context mContext;
- private List<SliceWrapper> mSlices = new ArrayList<>();
- private SliceItem mColor;
-
- public LargeSliceAdapter(Context context) {
- mContext = context;
- setHasStableIds(true);
- }
-
- /**
- * Set the {@link SliceItem}'s to be displayed in the adapter and the accent color.
- */
- public void setSliceItems(List<SliceItem> slices, SliceItem color) {
- mColor = color;
- mIdGen.resetUsage();
- mSlices = slices.stream().map(s -> new SliceWrapper(s, mIdGen))
- .collect(Collectors.toList());
- notifyDataSetChanged();
- }
-
- @Override
- public SliceViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- View v = inflateForType(viewType);
- v.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
- return new SliceViewHolder(v);
- }
-
- @Override
- public int getItemViewType(int position) {
- return mSlices.get(position).mType;
- }
-
- @Override
- public long getItemId(int position) {
- return mSlices.get(position).mId;
- }
-
- @Override
- public int getItemCount() {
- return mSlices.size();
- }
-
- @Override
- public void onBindViewHolder(SliceViewHolder holder, int position) {
- SliceWrapper slice = mSlices.get(position);
- if (holder.mSliceView != null) {
- holder.mSliceView.setColor(mColor);
- holder.mSliceView.setSliceItem(slice.mItem);
- } else if (slice.mType == TYPE_REMOTE_VIEWS) {
- FrameLayout frame = (FrameLayout) holder.itemView;
- frame.removeAllViews();
- frame.addView(slice.mItem.getRemoteView().apply(mContext, frame));
- }
- }
-
- private View inflateForType(int viewType) {
- switch (viewType) {
- case TYPE_REMOTE_VIEWS:
- return new FrameLayout(mContext);
- case TYPE_GRID:
- return LayoutInflater.from(mContext).inflate(R.layout.slice_grid, null);
- case TYPE_MESSAGE:
- return LayoutInflater.from(mContext).inflate(R.layout.slice_message, null);
- case TYPE_MESSAGE_LOCAL:
- return LayoutInflater.from(mContext).inflate(R.layout.slice_message_local, null);
- }
- return new SmallTemplateView(mContext);
- }
-
- protected static class SliceWrapper {
- private final SliceItem mItem;
- private final int mType;
- private final long mId;
-
- public SliceWrapper(SliceItem item, IdGenerator idGen) {
- mItem = item;
- mType = getType(item);
- mId = idGen.getId(item);
- }
-
- public static int getType(SliceItem item) {
- if (item.getType() == SliceItem.TYPE_REMOTE_VIEW) {
- return TYPE_REMOTE_VIEWS;
- }
- if (item.hasHint(Slice.HINT_MESSAGE)) {
- // TODO: Better way to determine me or not? Something more like Messaging style.
- if (SliceQuery.find(item, -1, Slice.HINT_SOURCE, null) != null) {
- return TYPE_MESSAGE;
- } else {
- return TYPE_MESSAGE_LOCAL;
- }
- }
- if (item.hasHint(Slice.HINT_HORIZONTAL)) {
- return TYPE_GRID;
- }
- return TYPE_DEFAULT;
- }
- }
-
- /**
- * A {@link ViewHolder} for presenting slices in {@link LargeSliceAdapter}.
- */
- public static class SliceViewHolder extends ViewHolder {
- public final SliceListView mSliceView;
-
- public SliceViewHolder(View itemView) {
- super(itemView);
- mSliceView = itemView instanceof SliceListView ? (SliceListView) itemView : null;
- }
- }
-
- /**
- * View slices being displayed in {@link LargeSliceAdapter}.
- */
- public interface SliceListView {
- /**
- * Set the slice item for this view.
- */
- void setSliceItem(SliceItem slice);
-
- /**
- * Set the color for the items in this view.
- */
- default void setColor(SliceItem color) {
-
- }
- }
-
- private static class IdGenerator {
- private long mNextLong = 0;
- private final ArrayMap<String, Long> mCurrentIds = new ArrayMap<>();
- private final ArrayMap<String, Integer> mUsedIds = new ArrayMap<>();
-
- public long getId(SliceItem item) {
- String str = genString(item);
- if (!mCurrentIds.containsKey(str)) {
- mCurrentIds.put(str, mNextLong++);
- }
- long id = mCurrentIds.get(str);
- int index = mUsedIds.getOrDefault(str, 0);
- mUsedIds.put(str, index + 1);
- return id + index * 10000;
- }
-
- private String genString(SliceItem item) {
- StringBuilder builder = new StringBuilder();
- SliceQuery.stream(item).forEach(i -> {
- builder.append(i.getType());
- i.removeHint(Slice.HINT_SELECTED);
- builder.append(i.getHints());
- switch (i.getType()) {
- case SliceItem.TYPE_REMOTE_VIEW:
- builder.append(i.getRemoteView());
- break;
- case SliceItem.TYPE_IMAGE:
- builder.append(i.getIcon());
- break;
- case SliceItem.TYPE_TEXT:
- builder.append(i.getText());
- break;
- case SliceItem.TYPE_COLOR:
- builder.append(i.getColor());
- break;
- }
- });
- return builder.toString();
- }
-
- public void resetUsage() {
- mUsedIds.clear();
- }
- }
-}
diff --git a/core/java/android/app/slice/widget/LargeTemplateView.java b/core/java/android/app/slice/widget/LargeTemplateView.java
deleted file mode 100644
index 788f6fb..0000000
--- a/core/java/android/app/slice/widget/LargeTemplateView.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2017 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 android.app.slice.widget;
-
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-
-import android.app.slice.Slice;
-import android.app.slice.SliceItem;
-import android.app.slice.SliceQuery;
-import android.app.slice.widget.SliceView.SliceModeView;
-import android.content.Context;
-import android.util.TypedValue;
-
-import com.android.internal.widget.LinearLayoutManager;
-import com.android.internal.widget.RecyclerView;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @hide
- */
-public class LargeTemplateView extends SliceModeView {
-
- private final LargeSliceAdapter mAdapter;
- private final RecyclerView mRecyclerView;
- private final int mDefaultHeight;
- private final int mMaxHeight;
- private Slice mSlice;
- private boolean mIsScrollable;
-
- public LargeTemplateView(Context context) {
- super(context);
-
- mRecyclerView = new RecyclerView(getContext());
- mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
- mAdapter = new LargeSliceAdapter(context);
- mRecyclerView.setAdapter(mAdapter);
- addView(mRecyclerView);
- mDefaultHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 200,
- getResources().getDisplayMetrics());
- mMaxHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 200,
- getResources().getDisplayMetrics());
- }
-
- @Override
- public String getMode() {
- return SliceView.MODE_LARGE;
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- mRecyclerView.getLayoutParams().height = WRAP_CONTENT;
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- if (mRecyclerView.getMeasuredHeight() > mMaxHeight
- || (mSlice != null && mSlice.hasHint(Slice.HINT_PARTIAL))) {
- mRecyclerView.getLayoutParams().height = mDefaultHeight;
- } else {
- mRecyclerView.getLayoutParams().height = mRecyclerView.getMeasuredHeight();
- }
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
-
- @Override
- public void setSlice(Slice slice) {
- SliceItem color = SliceQuery.find(slice, SliceItem.TYPE_COLOR);
- mSlice = slice;
- List<SliceItem> items = new ArrayList<>();
- boolean[] hasHeader = new boolean[1];
- if (slice.hasHint(Slice.HINT_LIST)) {
- addList(slice, items);
- } else {
- slice.getItems().forEach(item -> {
- 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)) {
- addList(item.getSlice(), items);
- } else if (item.hasHint(Slice.HINT_LIST_ITEM)) {
- items.add(item);
- } else if (!hasHeader[0]) {
- hasHeader[0] = true;
- items.add(0, item);
- } else {
- item.addHint(Slice.HINT_LIST_ITEM);
- items.add(item);
- }
- });
- }
- mAdapter.setSliceItems(items, color);
- }
-
- private void addList(Slice slice, List<SliceItem> items) {
- List<SliceItem> sliceItems = slice.getItems();
- sliceItems.forEach(i -> {
- if (!i.hasHint(Slice.HINT_HIDDEN) && i.getType() != SliceItem.TYPE_COLOR) {
- i.addHint(Slice.HINT_LIST_ITEM);
- items.add(i);
- }
- });
- }
-
- /**
- * Whether or not the content in this template should be scrollable.
- */
- public void setScrollable(boolean isScrollable) {
- // TODO -- restrict / enable how much this view can show
- mIsScrollable = isScrollable;
- }
-}
diff --git a/core/java/android/app/slice/widget/MessageView.java b/core/java/android/app/slice/widget/MessageView.java
deleted file mode 100644
index 3124398..0000000
--- a/core/java/android/app/slice/widget/MessageView.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2017 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 android.app.slice.widget;
-
-import android.app.slice.Slice;
-import android.app.slice.SliceItem;
-import android.app.slice.SliceQuery;
-import android.app.slice.widget.LargeSliceAdapter.SliceListView;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.text.SpannableStringBuilder;
-import android.util.AttributeSet;
-import android.util.TypedValue;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-/**
- * @hide
- */
-public class MessageView extends LinearLayout implements SliceListView {
-
- private TextView mDetails;
- private ImageView mIcon;
-
- public MessageView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mDetails = findViewById(android.R.id.summary);
- mIcon = findViewById(android.R.id.icon);
- }
-
- @Override
- public void setSliceItem(SliceItem slice) {
- SliceItem source = SliceQuery.find(slice, SliceItem.TYPE_IMAGE, Slice.HINT_SOURCE, null);
- if (source != null) {
- final int iconSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
- 24, getContext().getResources().getDisplayMetrics());
- // TODO try and turn this into a drawable
- Bitmap iconBm = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888);
- Canvas iconCanvas = new Canvas(iconBm);
- Drawable d = source.getIcon().loadDrawable(getContext());
- d.setBounds(0, 0, iconSize, iconSize);
- d.draw(iconCanvas);
- mIcon.setImageBitmap(SliceViewUtil.getCircularBitmap(iconBm));
- }
- SpannableStringBuilder builder = new SpannableStringBuilder();
- SliceQuery.findAll(slice, SliceItem.TYPE_TEXT).forEach(text -> {
- if (builder.length() != 0) {
- builder.append('\n');
- }
- builder.append(text.getText());
- });
- mDetails.setText(builder.toString());
- }
-
-}
diff --git a/core/java/android/app/slice/widget/RemoteInputView.java b/core/java/android/app/slice/widget/RemoteInputView.java
deleted file mode 100644
index 6eff5af..0000000
--- a/core/java/android/app/slice/widget/RemoteInputView.java
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * Copyright (C) 2017 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 android.app.slice.widget;
-
-import android.animation.Animator;
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.app.RemoteInput;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ShortcutManager;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewAnimationUtils;
-import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.inputmethod.CompletionInfo;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputConnection;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.EditText;
-import android.widget.ImageButton;
-import android.widget.LinearLayout;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import com.android.internal.R;
-
-/**
- * Host for the remote input.
- *
- * @hide
- */
-// TODO this should be unified with SystemUI RemoteInputView (b/67527720)
-public class RemoteInputView extends LinearLayout implements View.OnClickListener, TextWatcher {
-
- private static final String TAG = "RemoteInput";
-
- /**
- * A marker object that let's us easily find views of this class.
- */
- public static final Object VIEW_TAG = new Object();
-
- private RemoteEditText mEditText;
- private ImageButton mSendButton;
- private ProgressBar mProgressBar;
- private PendingIntent mPendingIntent;
- private RemoteInput[] mRemoteInputs;
- private RemoteInput mRemoteInput;
-
- private int mRevealCx;
- private int mRevealCy;
- private int mRevealR;
- private boolean mResetting;
-
- public RemoteInputView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- mProgressBar = findViewById(R.id.remote_input_progress);
- mSendButton = findViewById(R.id.remote_input_send);
- mSendButton.setOnClickListener(this);
-
- mEditText = (RemoteEditText) getChildAt(0);
- mEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
- @Override
- public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
- final boolean isSoftImeEvent = event == null
- && (actionId == EditorInfo.IME_ACTION_DONE
- || actionId == EditorInfo.IME_ACTION_NEXT
- || actionId == EditorInfo.IME_ACTION_SEND);
- final boolean isKeyboardEnterKey = event != null
- && KeyEvent.isConfirmKey(event.getKeyCode())
- && event.getAction() == KeyEvent.ACTION_DOWN;
-
- if (isSoftImeEvent || isKeyboardEnterKey) {
- if (mEditText.length() > 0) {
- sendRemoteInput();
- }
- // Consume action to prevent IME from closing.
- return true;
- }
- return false;
- }
- });
- mEditText.addTextChangedListener(this);
- mEditText.setInnerFocusable(false);
- mEditText.mRemoteInputView = this;
- }
-
- private void sendRemoteInput() {
- Bundle results = new Bundle();
- results.putString(mRemoteInput.getResultKey(), mEditText.getText().toString());
- Intent fillInIntent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- RemoteInput.addResultsToIntent(mRemoteInputs, fillInIntent,
- results);
-
- mEditText.setEnabled(false);
- mSendButton.setVisibility(INVISIBLE);
- mProgressBar.setVisibility(VISIBLE);
- mEditText.mShowImeOnInputConnection = false;
-
- // Tell ShortcutManager that this package has been "activated". ShortcutManager
- // will reset the throttling for this package.
- // Strictly speaking, the intent receiver may be different from the intent creator,
- // but that's an edge case, and also because we can't always know which package will receive
- // an intent, so we just reset for the creator.
- getContext().getSystemService(ShortcutManager.class).onApplicationActive(
- mPendingIntent.getCreatorPackage(),
- getContext().getUserId());
-
- try {
- mPendingIntent.send(mContext, 0, fillInIntent);
- reset();
- } catch (PendingIntent.CanceledException e) {
- Log.i(TAG, "Unable to send remote input result", e);
- Toast.makeText(mContext, "Failure sending pending intent for inline reply :(",
- Toast.LENGTH_SHORT).show();
- reset();
- }
- }
-
- /**
- * Creates a remote input view.
- */
- public static RemoteInputView inflate(Context context, ViewGroup root) {
- RemoteInputView v = (RemoteInputView) LayoutInflater.from(context).inflate(
- R.layout.slice_remote_input, root, false);
- v.setTag(VIEW_TAG);
- return v;
- }
-
- @Override
- public void onClick(View v) {
- if (v == mSendButton) {
- sendRemoteInput();
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- super.onTouchEvent(event);
-
- // We never want for a touch to escape to an outer view or one we covered.
- return true;
- }
-
- private void onDefocus() {
- setVisibility(INVISIBLE);
- }
-
- /**
- * Set the pending intent for remote input.
- */
- public void setPendingIntent(PendingIntent pendingIntent) {
- mPendingIntent = pendingIntent;
- }
-
- /**
- * Set the remote inputs for this view.
- */
- public void setRemoteInput(RemoteInput[] remoteInputs, RemoteInput remoteInput) {
- mRemoteInputs = remoteInputs;
- mRemoteInput = remoteInput;
- mEditText.setHint(mRemoteInput.getLabel());
- }
-
- /**
- * Focuses the remote input view.
- */
- public void focusAnimated() {
- if (getVisibility() != VISIBLE) {
- Animator animator = ViewAnimationUtils.createCircularReveal(
- this, mRevealCx, mRevealCy, 0, mRevealR);
- animator.setDuration(200);
- animator.start();
- }
- focus();
- }
-
- private void focus() {
- setVisibility(VISIBLE);
- mEditText.setInnerFocusable(true);
- mEditText.mShowImeOnInputConnection = true;
- mEditText.setSelection(mEditText.getText().length());
- mEditText.requestFocus();
- updateSendButton();
- }
-
- private void reset() {
- mResetting = true;
-
- mEditText.getText().clear();
- mEditText.setEnabled(true);
- mSendButton.setVisibility(VISIBLE);
- mProgressBar.setVisibility(INVISIBLE);
- updateSendButton();
- onDefocus();
-
- mResetting = false;
- }
-
- @Override
- public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
- if (mResetting && child == mEditText) {
- // Suppress text events if it happens during resetting. Ideally this would be
- // suppressed by the text view not being shown, but that doesn't work here because it
- // needs to stay visible for the animation.
- return false;
- }
- return super.onRequestSendAccessibilityEvent(child, event);
- }
-
- private void updateSendButton() {
- mSendButton.setEnabled(mEditText.getText().length() != 0);
- }
-
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- updateSendButton();
- }
-
- /**
- * Tries to find an action that matches the current pending intent of this view and updates its
- * state to that of the found action
- *
- * @return true if a matching action was found, false otherwise
- */
- public boolean updatePendingIntentFromActions(Notification.Action[] actions) {
- if (mPendingIntent == null || actions == null) {
- return false;
- }
- Intent current = mPendingIntent.getIntent();
- if (current == null) {
- return false;
- }
-
- for (Notification.Action a : actions) {
- RemoteInput[] inputs = a.getRemoteInputs();
- if (a.actionIntent == null || inputs == null) {
- continue;
- }
- Intent candidate = a.actionIntent.getIntent();
- if (!current.filterEquals(candidate)) {
- continue;
- }
-
- RemoteInput input = null;
- for (RemoteInput i : inputs) {
- if (i.getAllowFreeFormInput()) {
- input = i;
- }
- }
- if (input == null) {
- continue;
- }
- setPendingIntent(a.actionIntent);
- setRemoteInput(inputs, input);
- return true;
- }
- return false;
- }
-
- /**
- * @hide
- */
- public void setRevealParameters(int cx, int cy, int r) {
- mRevealCx = cx;
- mRevealCy = cy;
- mRevealR = r;
- }
-
- @Override
- public void dispatchStartTemporaryDetach() {
- super.dispatchStartTemporaryDetach();
- // Detach the EditText temporarily such that it doesn't get onDetachedFromWindow and
- // won't lose IME focus.
- detachViewFromParent(mEditText);
- }
-
- @Override
- public void dispatchFinishTemporaryDetach() {
- if (isAttachedToWindow()) {
- attachViewToParent(mEditText, 0, mEditText.getLayoutParams());
- } else {
- removeDetachedView(mEditText, false /* animate */);
- }
- super.dispatchFinishTemporaryDetach();
- }
-
- /**
- * An EditText that changes appearance based on whether it's focusable and becomes un-focusable
- * whenever the user navigates away from it or it becomes invisible.
- */
- public static class RemoteEditText extends EditText {
-
- private final Drawable mBackground;
- private RemoteInputView mRemoteInputView;
- boolean mShowImeOnInputConnection;
-
- public RemoteEditText(Context context, AttributeSet attrs) {
- super(context, attrs);
- mBackground = getBackground();
- }
-
- private void defocusIfNeeded(boolean animate) {
- if (mRemoteInputView != null || isTemporarilyDetached()) {
- if (isTemporarilyDetached()) {
- // We might get reattached but then the other one of HUN / expanded might steal
- // our focus, so we'll need to save our text here.
- }
- return;
- }
- if (isFocusable() && isEnabled()) {
- setInnerFocusable(false);
- if (mRemoteInputView != null) {
- mRemoteInputView.onDefocus();
- }
- mShowImeOnInputConnection = false;
- }
- }
-
- @Override
- protected void onVisibilityChanged(View changedView, int visibility) {
- super.onVisibilityChanged(changedView, visibility);
-
- if (!isShown()) {
- defocusIfNeeded(false /* animate */);
- }
- }
-
- @Override
- protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
- super.onFocusChanged(focused, direction, previouslyFocusedRect);
- if (!focused) {
- defocusIfNeeded(true /* animate */);
- }
- }
-
- @Override
- public void getFocusedRect(Rect r) {
- super.getFocusedRect(r);
- r.top = mScrollY;
- r.bottom = mScrollY + (mBottom - mTop);
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- // Eat the DOWN event here to prevent any default behavior.
- return true;
- }
- return super.onKeyDown(keyCode, event);
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- defocusIfNeeded(true /* animate */);
- return true;
- }
- return super.onKeyUp(keyCode, event);
- }
-
- @Override
- public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
- final InputConnection inputConnection = super.onCreateInputConnection(outAttrs);
-
- if (mShowImeOnInputConnection && inputConnection != null) {
- final InputMethodManager imm = InputMethodManager.getInstance();
- if (imm != null) {
- // onCreateInputConnection is called by InputMethodManager in the middle of
- // setting up the connection to the IME; wait with requesting the IME until that
- // work has completed.
- post(new Runnable() {
- @Override
- public void run() {
- imm.viewClicked(RemoteEditText.this);
- imm.showSoftInput(RemoteEditText.this, 0);
- }
- });
- }
- }
-
- return inputConnection;
- }
-
- @Override
- public void onCommitCompletion(CompletionInfo text) {
- clearComposingText();
- setText(text.getText());
- setSelection(getText().length());
- }
-
- void setInnerFocusable(boolean focusable) {
- setFocusableInTouchMode(focusable);
- setFocusable(focusable);
- setCursorVisible(focusable);
-
- if (focusable) {
- requestFocus();
- setBackground(mBackground);
- } else {
- setBackground(null);
- }
-
- }
- }
-}
diff --git a/core/java/android/app/slice/widget/ShortcutView.java b/core/java/android/app/slice/widget/ShortcutView.java
deleted file mode 100644
index 0b7ad0d..0000000
--- a/core/java/android/app/slice/widget/ShortcutView.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2017 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 android.app.slice.widget;
-
-import android.app.PendingIntent;
-import android.app.PendingIntent.CanceledException;
-import android.app.slice.Slice;
-import android.app.slice.SliceItem;
-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
- */
-public class ShortcutView extends SliceModeView {
-
- private static final String TAG = "ShortcutView";
-
- private Uri mUri;
- private PendingIntent mAction;
- private SliceItem mLabel;
- private SliceItem mIcon;
-
- private int mLargeIconSize;
- private int mSmallIconSize;
-
- public ShortcutView(Context context) {
- super(context);
- 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();
- determineShortcutItems(getContext(), slice);
- SliceItem colorItem = SliceQuery.find(slice, SliceItem.TYPE_COLOR);
- if (colorItem == null) {
- colorItem = SliceQuery.find(slice, SliceItem.TYPE_COLOR);
- }
- // TODO: pick better default colour
- final int color = colorItem != null ? colorItem.getColor() : Color.GRAY;
- ShapeDrawable circle = new ShapeDrawable(new OvalShape());
- circle.setTint(color);
- setBackground(circle);
- if (mIcon != null) {
- final boolean isLarge = mIcon.hasHint(Slice.HINT_LARGE);
- final int iconSize = isLarge ? mLargeIconSize : mSmallIconSize;
- SliceViewUtil.createCircledIcon(getContext(), color, iconSize, mIcon.getIcon(),
- isLarge, this /* parent */);
- mUri = slice.getUri();
- setClickable(true);
- } else {
- setClickable(false);
- }
- }
-
- @Override
- public String getMode() {
- return SliceView.MODE_SHORTCUT;
- }
-
- @Override
- public boolean performClick() {
- if (!callOnClick()) {
- try {
- if (mAction != null) {
- mAction.send();
- } else {
- Intent intent = new Intent(Intent.ACTION_VIEW).setData(mUri);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- getContext().startActivity(intent);
- }
- } catch (CanceledException e) {
- e.printStackTrace();
- }
- }
- 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
deleted file mode 100644
index fa1b64c..0000000
--- a/core/java/android/app/slice/widget/SliceView.java
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * Copyright (C) 2017 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 android.app.slice.widget;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.StringDef;
-import android.app.slice.Slice;
-import android.app.slice.SliceItem;
-import android.app.slice.SliceQuery;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.database.ContentObserver;
-import android.graphics.drawable.ColorDrawable;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Looper;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-
-import com.android.internal.R;
-import com.android.internal.util.Preconditions;
-
-import java.util.List;
-
-/**
- * A view for displaying a {@link Slice} which is a piece of app content and actions. SliceView is
- * able to present slice content in a templated format outside of the associated app. The way this
- * content is displayed depends on the structure of the slice, the hints associated with the
- * content, and the mode that SliceView is configured for. The modes that SliceView supports are:
- * <ul>
- * <li><b>Shortcut</b>: A shortcut is presented as an icon and a text label representing the main
- * content or action associated with the slice.</li>
- * <li><b>Small</b>: The small format has a restricted height and can present a single
- * {@link SliceItem} or a limited collection of items.</li>
- * <li><b>Large</b>: The large format displays multiple small templates in a list, if scrolling is
- * not enabled (see {@link #setScrollable(boolean)}) the view will show as many items as it can
- * comfortably fit.</li>
- * </ul>
- * <p>
- * When constructing a slice, the contents of it can be annotated with hints, these provide the OS
- * with some information on how the content should be displayed. For example, text annotated with
- * {@link Slice#HINT_TITLE} would be placed in the title position of a template. A slice annotated
- * with {@link Slice#HINT_LIST} would present the child items of that slice in a list.
- * <p>
- * SliceView can be provided a slice via a uri {@link #setSlice(Uri)} in which case a content
- * observer will be set for that uri and the view will update if there are any changes to the slice.
- * To use this the app must have a special permission to bind to the slice (see
- * {@link android.Manifest.permission#BIND_SLICE}).
- * <p>
- * Example usage:
- *
- * <pre class="prettyprint">
- * SliceView v = new SliceView(getContext());
- * v.setMode(desiredMode);
- * v.setSlice(sliceUri);
- * </pre>
- */
-public class SliceView extends ViewGroup {
-
- private static final String TAG = "SliceView";
-
- /**
- * @hide
- */
- public abstract static class SliceModeView extends FrameLayout {
-
- public SliceModeView(Context context) {
- super(context);
- }
-
- /**
- * @return the mode of the slice being presented.
- */
- public abstract String getMode();
-
- /**
- * @param slice the slice to show in this view.
- */
- public abstract void setSlice(Slice slice);
- }
-
- /**
- * @hide
- */
- @StringDef({
- MODE_SMALL, MODE_LARGE, MODE_SHORTCUT
- })
- public @interface SliceMode {}
-
- /**
- * Mode indicating this slice should be presented in small template format.
- */
- public static final String MODE_SMALL = "SLICE_SMALL";
- /**
- * Mode indicating this slice should be presented in large template format.
- */
- public static final String MODE_LARGE = "SLICE_LARGE";
- /**
- * 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";
-
- /**
- * Will select the type of slice binding based on size of the View. TODO: Put in some info about
- * that selection.
- */
- private static final String MODE_AUTO = "auto";
-
- private String mMode = MODE_AUTO;
- private SliceModeView mCurrentView;
- private final ActionRow mActions;
- private Slice mCurrentSlice;
- private boolean mShowActions = true;
- private boolean mIsScrollable;
- private SliceObserver mObserver;
- private final int mShortcutSize;
-
- public SliceView(Context context) {
- this(context, null);
- }
-
- public SliceView(Context context, @Nullable AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public SliceView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public SliceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- mObserver = new SliceObserver(new Handler(Looper.getMainLooper()));
- mActions = new ActionRow(mContext, true);
- mActions.setBackground(new ColorDrawable(0xffeeeeee));
- mCurrentView = new LargeTemplateView(mContext);
- addView(mCurrentView, getChildLp(mCurrentView));
- addView(mActions, getChildLp(mActions));
- mShortcutSize = getContext().getResources()
- .getDimensionPixelSize(R.dimen.slice_shortcut_size);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- measureChildren(widthMeasureSpec, heightMeasureSpec);
- int actionHeight = mActions.getVisibility() != View.GONE
- ? mActions.getMeasuredHeight()
- : 0;
- int newHeightSpec = MeasureSpec.makeMeasureSpec(
- mCurrentView.getMeasuredHeight() + actionHeight, MeasureSpec.EXACTLY);
- int width = MeasureSpec.getSize(widthMeasureSpec);
- setMeasuredDimension(width, newHeightSpec);
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- mCurrentView.layout(l, t, l + mCurrentView.getMeasuredWidth(),
- t + mCurrentView.getMeasuredHeight());
- if (mActions.getVisibility() != View.GONE) {
- mActions.layout(l, mCurrentView.getMeasuredHeight(), l + mActions.getMeasuredWidth(),
- mCurrentView.getMeasuredHeight() + mActions.getMeasuredHeight());
- }
- }
-
- /**
- * Populates this view with the {@link Slice} associated with the provided {@link Intent}. To
- * use this method your app must have the permission
- * {@link android.Manifest.permission#BIND_SLICE}).
- * <p>
- * Setting a slice differs from {@link #showSlice(Slice)} because it will ensure the view is
- * updated with the slice identified by the provided intent changes. The lifecycle of this
- * observer is handled by SliceView in {@link #onAttachedToWindow()} and
- * {@link #onDetachedFromWindow()}. To unregister this observer outside of that you can call
- * {@link #clearSlice}.
- *
- * @return true if a slice was found for the provided intent.
- * @hide
- */
- public boolean setSlice(@Nullable Intent intent) {
- Slice s = Slice.bindSlice(mContext, intent);
- if (s != null) {
- return setSlice(s.getUri());
- }
- return s != null;
- }
-
- /**
- * Populates this view with the {@link Slice} associated with the provided {@link Uri}. To use
- * this method your app must have the permission
- * {@link android.Manifest.permission#BIND_SLICE}).
- * <p>
- * Setting a slice differs from {@link #showSlice(Slice)} because it will ensure the view is
- * updated when the slice identified by the provided URI changes. The lifecycle of this observer
- * is handled by SliceView in {@link #onAttachedToWindow()} and {@link #onDetachedFromWindow()}.
- * To unregister this observer outside of that you can call {@link #clearSlice}.
- *
- * @return true if a slice was found for the provided uri.
- */
- public boolean setSlice(@NonNull Uri sliceUri) {
- Preconditions.checkNotNull(sliceUri,
- "Uri cannot be null, to remove the slice use clearSlice()");
- if (sliceUri == null) {
- clearSlice();
- return false;
- }
- validate(sliceUri);
- Slice s = Slice.bindSlice(mContext.getContentResolver(), sliceUri);
- if (s != null) {
- if (mObserver != null) {
- getContext().getContentResolver().unregisterContentObserver(mObserver);
- }
- mObserver = new SliceObserver(new Handler(Looper.getMainLooper()));
- if (isAttachedToWindow()) {
- registerSlice(sliceUri);
- }
- mCurrentSlice = s;
- reinflate();
- }
- return s != null;
- }
-
- /**
- * Populates this view to the provided {@link Slice}.
- * <p>
- * This does not register a content observer on the URI that the slice is backed by so it will
- * not update if the content changes. To have the view update when the content changes use
- * {@link #setSlice(Uri)} instead. Unlike {@link #setSlice(Uri)}, this method does not require
- * any special permissions.
- */
- public void showSlice(@NonNull Slice slice) {
- Preconditions.checkNotNull(slice,
- "Slice cannot be null, to remove the slice use clearSlice()");
- clearSlice();
- mCurrentSlice = slice;
- reinflate();
- }
-
- /**
- * Unregisters the change observer that is set when using {@link #setSlice}. Normally this is
- * done automatically during {@link #onDetachedFromWindow()}.
- * <p>
- * It is safe to call this method multiple times.
- */
- public void clearSlice() {
- mCurrentSlice = null;
- if (mObserver != null) {
- getContext().getContentResolver().unregisterContentObserver(mObserver);
- mObserver = null;
- }
- }
-
- /**
- * Set the mode this view should present in.
- */
- public void setMode(@SliceMode String mode) {
- setMode(mode, false /* animate */);
- }
-
- /**
- * Set whether this view should allow scrollable content when presenting in {@link #MODE_LARGE}.
- */
- public void setScrollable(boolean isScrollable) {
- mIsScrollable = isScrollable;
- reinflate();
- }
-
- /**
- * @hide
- */
- public void setMode(@SliceMode String mode, boolean animate) {
- if (animate) {
- Log.e(TAG, "Animation not supported yet");
- }
- mMode = mode;
- reinflate();
- }
-
- /**
- * @return the mode this view is presenting in.
- */
- public @SliceMode String getMode() {
- if (mMode.equals(MODE_AUTO)) {
- return MODE_LARGE;
- }
- return mMode;
- }
-
- /**
- * @hide
- *
- * Whether this view should show a row of actions with it.
- */
- public void setShowActionRow(boolean show) {
- mShowActions = show;
- reinflate();
- }
-
- private SliceModeView createView(String mode) {
- switch (mode) {
- case MODE_SHORTCUT:
- return new ShortcutView(getContext());
- case MODE_SMALL:
- return new SmallTemplateView(getContext());
- }
- return new LargeTemplateView(getContext());
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- registerSlice(mCurrentSlice != null ? mCurrentSlice.getUri() : null);
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- if (mObserver != null) {
- getContext().getContentResolver().unregisterContentObserver(mObserver);
- mObserver = null;
- }
- }
-
- private void registerSlice(Uri sliceUri) {
- if (sliceUri == null || mObserver == null) {
- return;
- }
- mContext.getContentResolver().registerContentObserver(sliceUri,
- false /* notifyForDescendants */, mObserver);
- }
-
- private void reinflate() {
- if (mCurrentSlice == null) {
- return;
- }
- // TODO: Smarter mapping here from one state to the next.
- SliceItem color = SliceQuery.find(mCurrentSlice, SliceItem.TYPE_COLOR);
- List<SliceItem> items = mCurrentSlice.getItems();
- SliceItem actionRow = SliceQuery.find(mCurrentSlice, SliceItem.TYPE_SLICE,
- Slice.HINT_ACTIONS,
- Slice.HINT_ALT);
- String mode = getMode();
- if (!mode.equals(mCurrentView.getMode())) {
- removeAllViews();
- mCurrentView = createView(mode);
- addView(mCurrentView, getChildLp(mCurrentView));
- addView(mActions, getChildLp(mActions));
- }
- if (mode.equals(MODE_LARGE)) {
- ((LargeTemplateView) mCurrentView).setScrollable(mIsScrollable);
- }
- if (items.size() > 1 || (items.size() != 0 && items.get(0) != actionRow)) {
- mCurrentView.setVisibility(View.VISIBLE);
- mCurrentView.setSlice(mCurrentSlice);
- } else {
- mCurrentView.setVisibility(View.GONE);
- }
-
- boolean showActions = mShowActions && actionRow != null
- && !mode.equals(MODE_SHORTCUT);
- if (showActions) {
- mActions.setActions(actionRow, color);
- mActions.setVisibility(View.VISIBLE);
- } else {
- mActions.setVisibility(View.GONE);
- }
- }
-
- private LayoutParams getChildLp(View child) {
- if (child instanceof ShortcutView) {
- return new LayoutParams(mShortcutSize, mShortcutSize);
- } else {
- return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
- }
- }
-
- private static void validate(Uri sliceUri) {
- if (!ContentResolver.SCHEME_CONTENT.equals(sliceUri.getScheme())) {
- throw new RuntimeException("Invalid uri " + sliceUri);
- }
- if (sliceUri.getPathSegments().size() == 0) {
- throw new RuntimeException("Invalid uri " + sliceUri);
- }
- }
-
- private class SliceObserver extends ContentObserver {
- SliceObserver(Handler handler) {
- super(handler);
- }
-
- @Override
- public void onChange(boolean selfChange) {
- this.onChange(selfChange, null);
- }
-
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- Slice s = Slice.bindSlice(mContext.getContentResolver(), uri);
- mCurrentSlice = s;
- reinflate();
- }
- }
-}
diff --git a/core/java/android/app/slice/widget/SliceViewUtil.java b/core/java/android/app/slice/widget/SliceViewUtil.java
deleted file mode 100644
index 1cf0055..0000000
--- a/core/java/android/app/slice/widget/SliceViewUtil.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (C) 2017 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 android.app.slice.widget;
-
-import android.annotation.ColorInt;
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.content.res.TypedArray;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.Canvas;
-import android.graphics.Color;
-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;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-
-/**
- * A bunch of utilities for slice UI.
- *
- * @hide
- */
-public class SliceViewUtil {
-
- /**
- * @hide
- */
- @ColorInt
- public static int getColorAccent(Context context) {
- return getColorAttr(context, android.R.attr.colorAccent);
- }
-
- /**
- * @hide
- */
- @ColorInt
- public static int getColorError(Context context) {
- return getColorAttr(context, android.R.attr.colorError);
- }
-
- /**
- * @hide
- */
- @ColorInt
- public static int getDefaultColor(Context context, int resId) {
- final ColorStateList list = context.getResources().getColorStateList(resId,
- context.getTheme());
-
- return list.getDefaultColor();
- }
-
- /**
- * @hide
- */
- @ColorInt
- public static int getDisabled(Context context, int inputColor) {
- return applyAlphaAttr(context, android.R.attr.disabledAlpha, inputColor);
- }
-
- /**
- * @hide
- */
- @ColorInt
- public static int applyAlphaAttr(Context context, int attr, int inputColor) {
- TypedArray ta = context.obtainStyledAttributes(new int[] {
- attr
- });
- float alpha = ta.getFloat(0, 0);
- ta.recycle();
- return applyAlpha(alpha, inputColor);
- }
-
- /**
- * @hide
- */
- @ColorInt
- public static int applyAlpha(float alpha, int inputColor) {
- alpha *= Color.alpha(inputColor);
- return Color.argb((int) (alpha), Color.red(inputColor), Color.green(inputColor),
- Color.blue(inputColor));
- }
-
- /**
- * @hide
- */
- @ColorInt
- public static int getColorAttr(Context context, int attr) {
- TypedArray ta = context.obtainStyledAttributes(new int[] {
- attr
- });
- @ColorInt
- int colorAccent = ta.getColor(0, 0);
- ta.recycle();
- return colorAccent;
- }
-
- /**
- * @hide
- */
- public static int getThemeAttr(Context context, int attr) {
- TypedArray ta = context.obtainStyledAttributes(new int[] {
- attr
- });
- int theme = ta.getResourceId(0, 0);
- ta.recycle();
- return theme;
- }
-
- /**
- * @hide
- */
- public static Drawable getDrawable(Context context, int attr) {
- TypedArray ta = context.obtainStyledAttributes(new int[] {
- attr
- });
- Drawable drawable = ta.getDrawable(0);
- ta.recycle();
- return drawable;
- }
-
- /**
- * @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);
- v.setImageIcon(icon);
- parent.addView(v);
- FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
- if (isLarge) {
- // XXX better way to convert from icon -> bitmap or crop an icon (?)
- Bitmap iconBm = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888);
- Canvas iconCanvas = new Canvas(iconBm);
- v.layout(0, 0, iconSize, iconSize);
- v.draw(iconCanvas);
- v.setImageBitmap(getCircularBitmap(iconBm));
- } else {
- v.setColorFilter(Color.WHITE);
- }
- lp.width = iconSize;
- lp.height = iconSize;
- lp.gravity = Gravity.CENTER;
- }
-
- /**
- * @hide
- */
- public static Bitmap getCircularBitmap(Bitmap bitmap) {
- Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
- bitmap.getHeight(), Config.ARGB_8888);
- Canvas canvas = new Canvas(output);
- final Paint paint = new Paint();
- final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
- paint.setAntiAlias(true);
- canvas.drawARGB(0, 0, 0, 0);
- canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2,
- bitmap.getWidth() / 2, paint);
- paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
- canvas.drawBitmap(bitmap, rect, rect, paint);
- return output;
- }
-}
diff --git a/core/java/android/app/slice/widget/SmallTemplateView.java b/core/java/android/app/slice/widget/SmallTemplateView.java
deleted file mode 100644
index 1c4c5df..0000000
--- a/core/java/android/app/slice/widget/SmallTemplateView.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2017 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 android.app.slice.widget;
-
-import android.app.PendingIntent.CanceledException;
-import android.app.slice.Slice;
-import android.app.slice.SliceItem;
-import android.app.slice.SliceQuery;
-import android.app.slice.widget.LargeSliceAdapter.SliceListView;
-import android.app.slice.widget.SliceView.SliceModeView;
-import android.content.Context;
-import android.os.AsyncTask;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import com.android.internal.R;
-
-import java.text.Format;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-/**
- * Small template is also used to construct list items for use with {@link LargeTemplateView}.
- *
- * @hide
- */
-public class SmallTemplateView extends SliceModeView implements SliceListView {
-
- private static final String TAG = "SmallTemplateView";
-
- private int mIconSize;
- private int mPadding;
-
- private LinearLayout mStartContainer;
- private TextView mTitleText;
- private TextView mSecondaryText;
- private LinearLayout mEndContainer;
-
- public SmallTemplateView(Context context) {
- super(context);
- inflate(context, R.layout.slice_small_template, this);
- mIconSize = getContext().getResources().getDimensionPixelSize(R.dimen.slice_icon_size);
- mPadding = getContext().getResources().getDimensionPixelSize(R.dimen.slice_padding);
-
- mStartContainer = (LinearLayout) findViewById(android.R.id.icon_frame);
- mTitleText = (TextView) findViewById(android.R.id.title);
- mSecondaryText = (TextView) findViewById(android.R.id.summary);
- mEndContainer = (LinearLayout) findViewById(android.R.id.widget_frame);
- }
-
- @Override
- public String getMode() {
- return SliceView.MODE_SMALL;
- }
-
- @Override
- public void setSliceItem(SliceItem slice) {
- resetViews();
- SliceItem colorItem = SliceQuery.find(slice, SliceItem.TYPE_COLOR);
- int color = colorItem != null ? colorItem.getColor() : -1;
-
- // Look for any title elements
- List<SliceItem> titleItems = SliceQuery.findAll(slice, -1, Slice.HINT_TITLE,
- null);
- boolean hasTitleText = false;
- boolean hasTitleItem = false;
- for (int i = 0; i < titleItems.size(); i++) {
- SliceItem item = titleItems.get(i);
- if (!hasTitleItem) {
- // icon, action icon, or timestamp
- if (item.getType() == SliceItem.TYPE_ACTION) {
- hasTitleItem = addIcon(item, color, mStartContainer);
- } else if (item.getType() == SliceItem.TYPE_IMAGE) {
- addIcon(item, color, mStartContainer);
- hasTitleItem = true;
- } else if (item.getType() == SliceItem.TYPE_TIMESTAMP) {
- TextView tv = new TextView(getContext());
- tv.setText(convertTimeToString(item.getTimestamp()));
- hasTitleItem = true;
- }
- }
- if (!hasTitleText && item.getType() == SliceItem.TYPE_TEXT) {
- mTitleText.setText(item.getText());
- hasTitleText = true;
- }
- if (hasTitleText && hasTitleItem) {
- break;
- }
- }
- mTitleText.setVisibility(hasTitleText ? View.VISIBLE : View.GONE);
- mStartContainer.setVisibility(hasTitleItem ? View.VISIBLE : View.GONE);
-
- if (slice.getType() != SliceItem.TYPE_SLICE) {
- return;
- }
-
- // Deal with remaining items
- int itemCount = 0;
- boolean hasSummary = false;
- ArrayList<SliceItem> sliceItems = new ArrayList<SliceItem>(
- slice.getSlice().getItems());
- for (int i = 0; i < sliceItems.size(); i++) {
- SliceItem item = sliceItems.get(i);
- if (!hasSummary && item.getType() == SliceItem.TYPE_TEXT
- && !item.hasHint(Slice.HINT_TITLE)) {
- // TODO -- Should combine all text items?
- mSecondaryText.setText(item.getText());
- hasSummary = true;
- }
- if (itemCount <= 3) {
- if (item.getType() == SliceItem.TYPE_ACTION) {
- if (addIcon(item, color, mEndContainer)) {
- itemCount++;
- }
- } else if (item.getType() == SliceItem.TYPE_IMAGE) {
- addIcon(item, color, mEndContainer);
- itemCount++;
- } else if (item.getType() == SliceItem.TYPE_TIMESTAMP) {
- TextView tv = new TextView(getContext());
- tv.setText(convertTimeToString(item.getTimestamp()));
- mEndContainer.addView(tv);
- itemCount++;
- } else if (item.getType() == SliceItem.TYPE_SLICE) {
- List<SliceItem> subItems = item.getSlice().getItems();
- for (int j = 0; j < subItems.size(); j++) {
- sliceItems.add(subItems.get(j));
- }
- }
- }
- }
- }
-
- @Override
- public void setSlice(Slice slice) {
- setSliceItem(new SliceItem(slice, SliceItem.TYPE_SLICE,
- slice.getHints().toArray(new String[slice.getHints().size()])));
- }
-
- /**
- * @return Whether an icon was added.
- */
- private boolean addIcon(SliceItem sliceItem, int color, LinearLayout container) {
- SliceItem image = null;
- SliceItem action = null;
- if (sliceItem.getType() == SliceItem.TYPE_ACTION) {
- image = SliceQuery.find(sliceItem.getSlice(), SliceItem.TYPE_IMAGE);
- action = sliceItem;
- } else if (sliceItem.getType() == SliceItem.TYPE_IMAGE) {
- image = sliceItem;
- }
- if (image != null) {
- ImageView iv = new ImageView(getContext());
- iv.setImageIcon(image.getIcon());
- if (action != null) {
- final SliceItem sliceAction = action;
- iv.setOnClickListener(v -> AsyncTask.execute(
- () -> {
- try {
- sliceAction.getAction().send();
- } catch (CanceledException e) {
- e.printStackTrace();
- }
- }));
- iv.setBackground(SliceViewUtil.getDrawable(getContext(),
- android.R.attr.selectableItemBackground));
- }
- if (color != -1 && !sliceItem.hasHint(Slice.HINT_NO_TINT)) {
- iv.setColorFilter(color);
- }
- container.addView(iv);
- LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) iv.getLayoutParams();
- lp.width = mIconSize;
- lp.height = mIconSize;
- lp.setMarginStart(mPadding);
- return true;
- }
- return false;
- }
-
- private String convertTimeToString(long time) {
- // TODO -- figure out what format(s) we support
- Date date = new Date(time);
- Format format = new SimpleDateFormat("MM dd yyyy HH:mm:ss");
- return format.format(date);
- }
-
- private void resetViews() {
- mStartContainer.removeAllViews();
- mEndContainer.removeAllViews();
- mTitleText.setText(null);
- mSecondaryText.setText(null);
- }
-}