Home | History | Annotate | Download | only in car
      1 package com.android.systemui.statusbar.car;
      2 
      3 import android.content.Context;
      4 import android.content.Intent;
      5 import android.content.res.TypedArray;
      6 import android.graphics.drawable.Drawable;
      7 import android.os.UserHandle;
      8 import android.util.AttributeSet;
      9 import android.util.Log;
     10 import android.view.View;
     11 import android.widget.ImageView;
     12 import android.widget.LinearLayout;
     13 
     14 import com.android.keyguard.AlphaOptimizedImageButton;
     15 import com.android.systemui.Dependency;
     16 import com.android.systemui.R;
     17 
     18 /**
     19  * CarFacetButton is a ui component designed to be used as a shortcut for an app of a defined
     20  * category. It can also render a indicator impling that there are more options of apps to launch
     21  * using this component. This is done with a "More icon" currently an arrow as defined in the layout
     22  * file. The class is to serve as an example.
     23  * Usage example: A button that allows a user to select a music app and indicate that there are
     24  * other music apps installed.
     25  */
     26 public class CarFacetButton extends LinearLayout {
     27     private static final String FACET_FILTER_DELIMITER = ";";
     28     /**
     29      * Extra information to be sent to a helper to make the decision of what app to launch when
     30      * clicked.
     31      */
     32     private static final String EXTRA_FACET_CATEGORIES = "categories";
     33     private static final String EXTRA_FACET_PACKAGES = "packages";
     34     private static final String EXTRA_FACET_ID = "filter_id";
     35     private static final String EXTRA_FACET_LAUNCH_PICKER = "launch_picker";
     36 
     37     private Context mContext;
     38     private AlphaOptimizedImageButton mIcon;
     39     private AlphaOptimizedImageButton mMoreIcon;
     40     private boolean mSelected = false;
     41     private String[] mComponentNames;
     42     /** App categories that are to be used with this widget */
     43     private String[] mFacetCategories;
     44     /** App packages that are allowed to be used with this widget */
     45     private String[] mFacetPackages;
     46     private int mIconResourceId;
     47     /**
     48      * If defined in the xml this will be the icon that's rendered when the button is marked as
     49      * selected
     50      */
     51     private int mSelectedIconResourceId;
     52     private boolean mUseMoreIcon = true;
     53     private float mSelectedAlpha = 1f;
     54     private float mUnselectedAlpha = 1f;
     55 
     56 
     57     public CarFacetButton(Context context, AttributeSet attrs) {
     58         super(context, attrs);
     59         mContext = context;
     60         View.inflate(context, R.layout.car_facet_button, this);
     61 
     62         // extract custom attributes
     63         TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CarFacetButton);
     64         setupIntents(typedArray);
     65         setupIcons(typedArray);
     66         CarFacetButtonController carFacetButtonController = Dependency.get(
     67                 CarFacetButtonController.class);
     68         carFacetButtonController.addFacetButton(this);
     69 
     70     }
     71 
     72     /**
     73      * Reads the custom attributes to setup click handlers for this component.
     74      */
     75     private void setupIntents(TypedArray typedArray) {
     76         String intentString = typedArray.getString(R.styleable.CarFacetButton_intent);
     77         String longPressIntentString = typedArray.getString(R.styleable.CarFacetButton_longIntent);
     78         String categoryString = typedArray.getString(R.styleable.CarFacetButton_categories);
     79         String packageString = typedArray.getString(R.styleable.CarFacetButton_packages);
     80         String componentNameString =
     81                 typedArray.getString(R.styleable.CarFacetButton_componentNames);
     82         try {
     83             final Intent intent = Intent.parseUri(intentString, Intent.URI_INTENT_SCHEME);
     84             intent.putExtra(EXTRA_FACET_ID, Integer.toString(getId()));
     85 
     86             if (packageString != null) {
     87                 mFacetPackages = packageString.split(FACET_FILTER_DELIMITER);
     88                 intent.putExtra(EXTRA_FACET_PACKAGES, mFacetPackages);
     89             }
     90             if (categoryString != null) {
     91                 mFacetCategories = categoryString.split(FACET_FILTER_DELIMITER);
     92                 intent.putExtra(EXTRA_FACET_CATEGORIES, mFacetCategories);
     93             }
     94             if (componentNameString != null) {
     95                 mComponentNames = componentNameString.split(FACET_FILTER_DELIMITER);
     96             }
     97 
     98             setOnClickListener(v -> {
     99                 intent.putExtra(EXTRA_FACET_LAUNCH_PICKER, mSelected);
    100                 mContext.startActivityAsUser(intent, UserHandle.CURRENT);
    101             });
    102 
    103             if (longPressIntentString != null) {
    104                 final Intent longPressIntent = Intent.parseUri(longPressIntentString,
    105                         Intent.URI_INTENT_SCHEME);
    106                 setOnLongClickListener(v -> {
    107                     mContext.startActivityAsUser(longPressIntent, UserHandle.CURRENT);
    108                     return true;
    109                 });
    110             }
    111         } catch (Exception e) {
    112             throw new RuntimeException("Failed to attach intent", e);
    113         }
    114     }
    115 
    116 
    117     private void setupIcons(TypedArray styledAttributes) {
    118         mSelectedAlpha = styledAttributes.getFloat(
    119                 R.styleable.CarFacetButton_selectedAlpha, mSelectedAlpha);
    120         mUnselectedAlpha = styledAttributes.getFloat(
    121                 R.styleable.CarFacetButton_unselectedAlpha, mUnselectedAlpha);
    122         mIcon = findViewById(R.id.car_nav_button_icon);
    123         mIcon.setScaleType(ImageView.ScaleType.CENTER);
    124         mIcon.setClickable(false);
    125         mIcon.setAlpha(mUnselectedAlpha);
    126         mIconResourceId = styledAttributes.getResourceId(R.styleable.CarFacetButton_icon, 0);
    127         mIcon.setImageResource(mIconResourceId);
    128         mSelectedIconResourceId = styledAttributes.getResourceId(
    129                 R.styleable.CarFacetButton_selectedIcon, mIconResourceId);
    130 
    131         mMoreIcon = findViewById(R.id.car_nav_button_more_icon);
    132         mMoreIcon.setClickable(false);
    133         mMoreIcon.setAlpha(mSelectedAlpha);
    134         mMoreIcon.setVisibility(GONE);
    135         mUseMoreIcon = styledAttributes.getBoolean(R.styleable.CarFacetButton_useMoreIcon, true);
    136     }
    137 
    138     /**
    139      * @return The app categories the component represents
    140      */
    141     public String[] getCategories() {
    142         if (mFacetCategories == null) {
    143             return new String[0];
    144         }
    145         return mFacetCategories;
    146     }
    147 
    148     /**
    149      * @return The valid packages that should be considered.
    150      */
    151     public String[] getFacetPackages() {
    152         if (mFacetPackages == null) {
    153             return new String[0];
    154         }
    155         return mFacetPackages;
    156     }
    157 
    158     public String[] getComponentName() {
    159         if (mComponentNames == null) {
    160             return new String[0];
    161         }
    162         return mComponentNames;
    163     }
    164 
    165     /**
    166      * Updates the alpha of the icons to "selected" and shows the "More icon"
    167      * @param selected true if the view must be selected, false otherwise
    168      */
    169     public void setSelected(boolean selected) {
    170         super.setSelected(selected);
    171         setSelected(selected, selected);
    172     }
    173 
    174     /**
    175      * Updates the visual state to let the user know if it's been selected.
    176      * @param selected true if should update the alpha of the icon to selected, false otherwise
    177      * @param showMoreIcon true if the "more icon" should be shown, false otherwise. Note this
    178      *                     is ignored if the attribute useMoreIcon is set to false
    179      */
    180     public void setSelected(boolean selected, boolean showMoreIcon) {
    181         mSelected = selected;
    182         mIcon.setAlpha(mSelected ? mSelectedAlpha : mUnselectedAlpha);
    183         mIcon.setImageResource(mSelected ? mSelectedIconResourceId : mIconResourceId);
    184         if (mUseMoreIcon) {
    185             mMoreIcon.setVisibility(showMoreIcon ? VISIBLE : GONE);
    186         }
    187     }
    188 }
    189