1 package com.android.car.media.widgets; 2 3 import android.car.drivingstate.CarUxRestrictions; 4 import android.content.Context; 5 import android.content.Intent; 6 import android.graphics.drawable.Drawable; 7 import android.view.View; 8 9 import androidx.annotation.NonNull; 10 import androidx.annotation.Nullable; 11 12 import com.android.car.media.R; 13 import com.android.car.media.common.MediaItemMetadata; 14 import com.android.car.media.common.source.MediaSource; 15 import com.android.car.ui.toolbar.MenuItem; 16 import com.android.car.ui.toolbar.Toolbar; 17 import com.android.car.ui.toolbar.ToolbarController; 18 19 import java.util.Arrays; 20 import java.util.List; 21 import java.util.Objects; 22 23 /** 24 * Media template application bar. The callers should set properties via the public methods (e.g., 25 * {@link #setItems}, {@link #setTitle}, {@link #setHasSettings}), and set the visibility of the 26 * views via {@link #setState}. A detailed explanation of all possible states of this application 27 * bar can be seen at {@link Toolbar.State}. 28 */ 29 public class AppBarController { 30 31 private static final int MEDIA_UX_RESTRICTION_DEFAULT = 32 CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP; 33 private static final int MEDIA_UX_RESTRICTION_NONE = CarUxRestrictions.UX_RESTRICTIONS_BASELINE; 34 35 private int mMaxTabs; 36 private final ToolbarController mToolbarController; 37 38 private final boolean mUseSourceLogoForAppSelector; 39 40 @NonNull 41 private AppBarListener mListener = new AppBarListener(); 42 private MenuItem mSearch; 43 private MenuItem mSettings; 44 private MenuItem mEqualizer; 45 private MenuItem mAppSelector; 46 47 private boolean mSearchSupported; 48 private boolean mShowSearchIfSupported; 49 private String mSearchQuery; 50 51 private Intent mAppSelectorIntent; 52 53 /** 54 * Application bar listener 55 */ 56 public static class AppBarListener { 57 /** 58 * Invoked when the user selects an item from the tabs 59 */ onTabSelected(MediaItemMetadata item)60 protected void onTabSelected(MediaItemMetadata item) {} 61 62 /** 63 * Invoked when the user clicks on the settings button. 64 */ onSettingsSelection()65 protected void onSettingsSelection() {} 66 67 /** 68 * Invoked when the user clicks on the equalizer button. 69 */ onEqualizerSelection()70 protected void onEqualizerSelection() {} 71 72 /** 73 * Invoked when the user submits a search query. 74 */ onSearch(String query)75 protected void onSearch(String query) {} 76 77 /** 78 * Invoked when the user clicks on the search button 79 */ onSearchSelection()80 protected void onSearchSelection() {} 81 } 82 AppBarController(Context context, ToolbarController controller)83 public AppBarController(Context context, ToolbarController controller) { 84 mToolbarController = controller; 85 mMaxTabs = context.getResources().getInteger(R.integer.max_tabs); 86 87 mUseSourceLogoForAppSelector = 88 context.getResources().getBoolean(R.bool.use_media_source_logo_for_app_selector); 89 90 mAppSelectorIntent = MediaSource.getSourceSelectorIntent(context, false); 91 92 mToolbarController.registerOnTabSelectedListener(tab -> 93 mListener.onTabSelected(((MediaItemTab) tab).getItem())); 94 mToolbarController.registerOnSearchListener(query -> { 95 mSearchQuery = query; 96 mListener.onSearch(query); 97 }); 98 mToolbarController.registerOnSearchCompletedListener( 99 () -> mListener.onSearch(mSearchQuery)); 100 mSearch = MenuItem.builder(context) 101 .setToSearch() 102 .setOnClickListener(v -> mListener.onSearchSelection()) 103 .build(); 104 mSettings = MenuItem.builder(context) 105 .setToSettings() 106 .setUxRestrictions(MEDIA_UX_RESTRICTION_DEFAULT) 107 .setOnClickListener(v -> mListener.onSettingsSelection()) 108 .build(); 109 mEqualizer = MenuItem.builder(context) 110 .setTitle(R.string.menu_item_sound_settings_title) 111 .setIcon(R.drawable.ic_equalizer) 112 .setOnClickListener(v -> mListener.onEqualizerSelection()) 113 .build(); 114 mAppSelector = MenuItem.builder(context) 115 .setTitle(R.string.menu_item_app_selector_title) 116 .setTinted(!mUseSourceLogoForAppSelector) 117 .setIcon(mUseSourceLogoForAppSelector 118 ? null : context.getDrawable(R.drawable.ic_app_switch)) 119 .setOnClickListener(m -> context.startActivity(mAppSelectorIntent)) 120 .build(); 121 mToolbarController.setMenuItems( 122 Arrays.asList(mSearch, mEqualizer, mSettings, mAppSelector)); 123 124 setAppLauncherSupported(mAppSelectorIntent != null); 125 } 126 127 /** 128 * Sets a listener of this application bar events. In order to avoid memory leaks, consumers 129 * must reset this reference by setting the listener to null. 130 */ setListener(AppBarListener listener)131 public void setListener(AppBarListener listener) { 132 mListener = listener; 133 } 134 135 /** 136 * Updates the list of items to show in the application bar tabs. 137 * 138 * @param items list of tabs to show, or null if no tabs should be shown. 139 */ setItems(@ullable List<MediaItemMetadata> items)140 public void setItems(@Nullable List<MediaItemMetadata> items) { 141 mToolbarController.clearAllTabs(); 142 143 if (items != null && !items.isEmpty()) { 144 int count = 0; 145 for (MediaItemMetadata item : items) { 146 mToolbarController.addTab(new MediaItemTab(item)); 147 148 count++; 149 if (count >= mMaxTabs) { 150 break; 151 } 152 } 153 } 154 } 155 156 /** Sets whether the source has settings (not all screens show it). */ setHasSettings(boolean hasSettings)157 public void setHasSettings(boolean hasSettings) { 158 mSettings.setVisible(hasSettings); 159 } 160 161 /** Sets whether the source's settings is distraction optimized. */ setSettingsDistractionOptimized(boolean isDistractionOptimized)162 public void setSettingsDistractionOptimized(boolean isDistractionOptimized) { 163 mSettings.setUxRestrictions(isDistractionOptimized 164 ? MEDIA_UX_RESTRICTION_NONE 165 : MEDIA_UX_RESTRICTION_DEFAULT); 166 } 167 168 /** Sets whether the source has equalizer support. */ setHasEqualizer(boolean hasEqualizer)169 public void setHasEqualizer(boolean hasEqualizer) { 170 mEqualizer.setVisible(hasEqualizer); 171 } 172 173 /** 174 * Sets whether search is supported 175 */ setSearchSupported(boolean supported)176 public void setSearchSupported(boolean supported) { 177 mSearchSupported = supported; 178 updateSearchVisibility(); 179 } 180 181 /** Sets whether to show the search MenuItem if supported */ showSearchIfSupported(boolean show)182 public void showSearchIfSupported(boolean show) { 183 mShowSearchIfSupported = show; 184 updateSearchVisibility(); 185 } 186 updateSearchVisibility()187 private void updateSearchVisibility() { 188 mSearch.setVisible(mShowSearchIfSupported && mSearchSupported); 189 } 190 191 /** 192 * Sets whether launching app selector is supported 193 */ setAppLauncherSupported(boolean supported)194 private void setAppLauncherSupported(boolean supported) { 195 mAppSelector.setVisible(supported); 196 } 197 198 /** 199 * Updates the currently active item 200 */ setActiveItem(MediaItemMetadata item)201 public void setActiveItem(MediaItemMetadata item) { 202 for (int i = 0; i < mToolbarController.getTabCount(); i++) { 203 MediaItemTab mediaItemTab = (MediaItemTab) mToolbarController.getTab(i); 204 boolean match = item != null && Objects.equals( 205 item.getId(), 206 mediaItemTab.getItem().getId()); 207 if (match) { 208 mToolbarController.selectTab(i); 209 return; 210 } 211 } 212 } 213 setSearchQuery(String query)214 public void setSearchQuery(String query) { 215 mToolbarController.setSearchQuery(query); 216 } 217 setLogo(Drawable drawable)218 public void setLogo(Drawable drawable) { 219 if (mUseSourceLogoForAppSelector) { 220 mAppSelector.setIcon(drawable); 221 } else { 222 mToolbarController.setLogo(drawable); 223 } 224 } 225 setSearchIcon(Drawable drawable)226 public void setSearchIcon(Drawable drawable) { 227 mToolbarController.setSearchIcon(drawable); 228 } 229 setTitle(CharSequence title)230 public void setTitle(CharSequence title) { 231 mToolbarController.setTitle(title); 232 } 233 setTitle(int title)234 public void setTitle(int title) { 235 mToolbarController.setTitle(title); 236 } 237 setState(Toolbar.State state)238 public void setState(Toolbar.State state) { 239 mToolbarController.setState(state); 240 } 241 setMenuItems(List<MenuItem> items)242 public void setMenuItems(List<MenuItem> items) { 243 mToolbarController.setMenuItems(items); 244 } 245 setBackgroundShown(boolean shown)246 public void setBackgroundShown(boolean shown) { 247 mToolbarController.setBackgroundShown(shown); 248 } 249 setNavButtonMode(Toolbar.NavButtonMode mode)250 public void setNavButtonMode(Toolbar.NavButtonMode mode) { 251 mToolbarController.setNavButtonMode(mode); 252 } 253 254 /** See {@link ToolbarController#canShowSearchResultItems}. */ canShowSearchResultsView()255 public boolean canShowSearchResultsView() { 256 return mToolbarController.canShowSearchResultsView(); 257 } 258 259 /** See {@link ToolbarController#setSearchResultsView}. */ setSearchResultsView(View view)260 public void setSearchResultsView(View view) { 261 mToolbarController.setSearchResultsView(view); 262 } 263 } 264