1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.wm.shell.common; 18 19 import android.content.Context; 20 import android.content.res.TypedArray; 21 import android.graphics.drawable.Drawable; 22 import android.graphics.drawable.Icon; 23 import android.os.Handler; 24 import android.util.AttributeSet; 25 import android.view.LayoutInflater; 26 import android.view.View; 27 import android.widget.ImageView; 28 import android.widget.RelativeLayout; 29 30 import com.android.wm.shell.R; 31 32 /** 33 * A common action button for TV window menu layouts. 34 */ 35 public class TvWindowMenuActionButton extends RelativeLayout { 36 private final ImageView mIconImageView; 37 private final View mButtonBackgroundView; 38 39 private Icon mCurrentIcon; 40 TvWindowMenuActionButton(Context context)41 public TvWindowMenuActionButton(Context context) { 42 this(context, null, 0, 0); 43 } 44 TvWindowMenuActionButton(Context context, AttributeSet attrs)45 public TvWindowMenuActionButton(Context context, AttributeSet attrs) { 46 this(context, attrs, 0, 0); 47 } 48 TvWindowMenuActionButton(Context context, AttributeSet attrs, int defStyleAttr)49 public TvWindowMenuActionButton(Context context, AttributeSet attrs, int defStyleAttr) { 50 this(context, attrs, defStyleAttr, 0); 51 } 52 TvWindowMenuActionButton( Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)53 public TvWindowMenuActionButton( 54 Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 55 super(context, attrs, defStyleAttr, defStyleRes); 56 final LayoutInflater inflater = (LayoutInflater) getContext() 57 .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 58 inflater.inflate(R.layout.tv_window_menu_action_button, this); 59 60 mIconImageView = findViewById(R.id.icon); 61 mButtonBackgroundView = findViewById(R.id.background); 62 63 final int[] values = new int[]{android.R.attr.src, android.R.attr.text}; 64 final TypedArray typedArray = context.obtainStyledAttributes(attrs, values, defStyleAttr, 65 defStyleRes); 66 67 setImageResource(typedArray.getResourceId(0, 0)); 68 final int textResId = typedArray.getResourceId(1, 0); 69 if (textResId != 0) { 70 setTextAndDescription(textResId); 71 } 72 typedArray.recycle(); 73 74 setIsCustomCloseAction(false); 75 } 76 77 /** 78 * Sets the drawable for the button with the given drawable. 79 */ setImageDrawable(Drawable d)80 public void setImageDrawable(Drawable d) { 81 mIconImageView.setImageDrawable(d); 82 } 83 84 /** 85 * Sets the drawable for the button with the given resource id. 86 */ setImageResource(int resId)87 public void setImageResource(int resId) { 88 if (resId != 0) { 89 mIconImageView.setImageResource(resId); 90 } 91 } 92 setImageIconAsync(Icon icon, Handler handler)93 public void setImageIconAsync(Icon icon, Handler handler) { 94 mCurrentIcon = icon; 95 // Remove old image while waiting for the new one to load. 96 mIconImageView.setImageDrawable(null); 97 if (icon.getType() == Icon.TYPE_URI || icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP) { 98 // Disallow loading icon from content URI 99 return; 100 } 101 icon.loadDrawableAsync(mContext, d -> { 102 // The image hasn't been set any other way and the drawable belongs to the most 103 // recently set Icon. 104 if (mIconImageView.getDrawable() == null && mCurrentIcon == icon) { 105 mIconImageView.setImageDrawable(d); 106 } 107 }, handler); 108 } 109 110 /** 111 * Sets the text for description the with the given string. 112 */ setTextAndDescription(CharSequence text)113 public void setTextAndDescription(CharSequence text) { 114 setContentDescription(text); 115 } 116 117 /** 118 * Sets the text and description with the given string resource id. 119 */ setTextAndDescription(int resId)120 public void setTextAndDescription(int resId) { 121 setTextAndDescription(getContext().getString(resId)); 122 } 123 124 /** 125 * Marks this button as a custom close action button. 126 * This changes the style of the action button to highlight that this action finishes the 127 * Picture-in-Picture activity. 128 * 129 * @param isCustomCloseAction sets or unsets this button as a custom close action button. 130 */ setIsCustomCloseAction(boolean isCustomCloseAction)131 public void setIsCustomCloseAction(boolean isCustomCloseAction) { 132 mIconImageView.setImageTintList( 133 getResources().getColorStateList( 134 isCustomCloseAction ? R.color.tv_window_menu_close_icon 135 : R.color.tv_window_menu_icon)); 136 mButtonBackgroundView.setBackgroundTintList(getResources() 137 .getColorStateList(isCustomCloseAction ? R.color.tv_window_menu_close_icon_bg 138 : R.color.tv_window_menu_icon_bg)); 139 } 140 141 @Override toString()142 public String toString() { 143 if (getContentDescription() == null) { 144 return TvWindowMenuActionButton.class.getSimpleName(); 145 } 146 return getContentDescription().toString(); 147 } 148 149 } 150