diff options
Diffstat (limited to 'android/app/slice/views/ActionRow.java')
-rw-r--r-- | android/app/slice/views/ActionRow.java | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/android/app/slice/views/ActionRow.java b/android/app/slice/views/ActionRow.java new file mode 100644 index 00000000..c7d99f7f --- /dev/null +++ b/android/app/slice/views/ActionRow.java @@ -0,0 +1,201 @@ +/* + * 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.views; + +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); + } +} |