BrandedFragment.java revision a373804d10f93a9488adc35cf6ce44dce09b3778
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14package android.support.v17.leanback.app; 15 16import android.app.Fragment; 17import android.graphics.drawable.Drawable; 18import android.os.Bundle; 19import android.support.v17.leanback.R; 20import android.support.v17.leanback.widget.SearchOrbView; 21import android.support.v17.leanback.widget.TitleHelper; 22import android.support.v17.leanback.widget.TitleViewAdapter; 23import android.util.TypedValue; 24import android.view.LayoutInflater; 25import android.view.View; 26import android.view.ViewGroup; 27 28/** 29 * Fragment class for managing search and branding using a view that implements 30 * {@link TitleViewAdapter.Provider}. 31 */ 32public class BrandedFragment extends Fragment { 33 34 // BUNDLE attribute for title is showing 35 private static final String TITLE_SHOW = "titleShow"; 36 37 private boolean mShowingTitle = true; 38 private CharSequence mTitle; 39 private Drawable mBadgeDrawable; 40 private View mTitleView; 41 private TitleViewAdapter mTitleViewAdapter; 42 private SearchOrbView.Colors mSearchAffordanceColors; 43 private boolean mSearchAffordanceColorSet; 44 private View.OnClickListener mExternalOnSearchClickedListener; 45 private TitleHelper mTitleHelper; 46 47 /** 48 * Called by {@link #installTitleView(LayoutInflater, ViewGroup, Bundle)} to inflate 49 * title view. Default implementation uses layout file lb_browse_title. 50 * Subclass may override and use its own layout, the layout must have a descendant with id 51 * browse_title_group that implements {@link TitleViewAdapter.Provider}. Subclass may return 52 * null if no title is needed. 53 * 54 * @param inflater The LayoutInflater object that can be used to inflate 55 * any views in the fragment, 56 * @param parent Parent of title view. 57 * @param savedInstanceState If non-null, this fragment is being re-constructed 58 * from a previous saved state as given here. 59 * @return Title view which must have a descendant with id browse_title_group that implements 60 * {@link TitleViewAdapter.Provider}, or null for no title view. 61 */ 62 public View onInflateTitleView(LayoutInflater inflater, ViewGroup parent, 63 Bundle savedInstanceState) { 64 TypedValue typedValue = new TypedValue(); 65 boolean found = parent.getContext().getTheme().resolveAttribute( 66 R.attr.browseTitleViewLayout, typedValue, true); 67 return inflater.inflate(found ? typedValue.resourceId : R.layout.lb_browse_title, 68 parent, false); 69 } 70 71 /** 72 * Inflate title view and add to parent. This method should be called in 73 * {@link Fragment#onCreateView(LayoutInflater, ViewGroup, Bundle)}. 74 * @param inflater The LayoutInflater object that can be used to inflate 75 * any views in the fragment, 76 * @param parent Parent of title view. 77 * @param savedInstanceState If non-null, this fragment is being re-constructed 78 * from a previous saved state as given here. 79 */ 80 public void installTitleView(LayoutInflater inflater, ViewGroup parent, 81 Bundle savedInstanceState) { 82 View titleLayoutRoot = onInflateTitleView(inflater, parent, savedInstanceState); 83 if (titleLayoutRoot != null) { 84 parent.addView(titleLayoutRoot); 85 setTitleView(titleLayoutRoot.findViewById(R.id.browse_title_group)); 86 } else { 87 setTitleView(null); 88 } 89 } 90 91 /** 92 * Sets the view that implemented {@link TitleViewAdapter}. 93 * @param titleView The view that implemented {@link TitleViewAdapter.Provider}. 94 */ 95 public void setTitleView(View titleView) { 96 mTitleView = titleView; 97 if (mTitleView == null) { 98 mTitleViewAdapter = null; 99 mTitleHelper = null; 100 } else { 101 mTitleViewAdapter = ((TitleViewAdapter.Provider) mTitleView).getTitleViewAdapter(); 102 mTitleViewAdapter.setTitle(mTitle); 103 mTitleViewAdapter.setBadgeDrawable(mBadgeDrawable); 104 if (mSearchAffordanceColorSet) { 105 mTitleViewAdapter.setSearchAffordanceColors(mSearchAffordanceColors); 106 } 107 if (mExternalOnSearchClickedListener != null) { 108 setOnSearchClickedListener(mExternalOnSearchClickedListener); 109 } 110 if (getView() instanceof ViewGroup) { 111 mTitleHelper = new TitleHelper((ViewGroup) getView(), mTitleView); 112 } 113 } 114 } 115 116 /** 117 * Returns the view that implements {@link TitleViewAdapter.Provider}. 118 * @return The view that implements {@link TitleViewAdapter.Provider}. 119 */ 120 public View getTitleView() { 121 return mTitleView; 122 } 123 124 /** 125 * Returns the {@link TitleViewAdapter} implemented by title view. 126 * @return The {@link TitleViewAdapter} implemented by title view. 127 */ 128 public TitleViewAdapter getTitleViewAdapter() { 129 return mTitleViewAdapter; 130 } 131 132 /** 133 * Returns the {@link TitleHelper}. 134 */ 135 TitleHelper getTitleHelper() { 136 return mTitleHelper; 137 } 138 139 @Override 140 public void onSaveInstanceState(Bundle outState) { 141 super.onSaveInstanceState(outState); 142 outState.putBoolean(TITLE_SHOW, mShowingTitle); 143 } 144 145 @Override 146 public void onViewCreated(View view, Bundle savedInstanceState) { 147 super.onViewCreated(view, savedInstanceState); 148 if (savedInstanceState != null) { 149 mShowingTitle = savedInstanceState.getBoolean(TITLE_SHOW); 150 } 151 if (mTitleView != null && view instanceof ViewGroup) { 152 mTitleHelper = new TitleHelper((ViewGroup) view, mTitleView); 153 } 154 } 155 156 @Override 157 public void onDestroyView() { 158 super.onDestroyView(); 159 mTitleHelper = null; 160 } 161 162 /** 163 * Shows or hides the title view. 164 * @param show True to show title view, false to hide title view. 165 */ 166 public void showTitle(boolean show) { 167 // TODO: handle interruptions? 168 if (show == mShowingTitle) { 169 return; 170 } 171 mShowingTitle = show; 172 if (mTitleHelper != null) { 173 mTitleHelper.showTitle(show); 174 } 175 } 176 177 /** 178 * Changes title view's components visibility and shows title. 179 * @param flags Flags representing the visibility of components inside title view. 180 * @see TitleViewAdapter#SEARCH_VIEW_VISIBLE 181 * @see TitleViewAdapter#BRANDING_VIEW_VISIBLE 182 * @see TitleViewAdapter#FULL_VIEW_VISIBLE 183 * @see TitleViewAdapter#updateComponentsVisibility(int) 184 */ 185 public void showTitle(int flags) { 186 if (mTitleViewAdapter != null) { 187 mTitleViewAdapter.updateComponentsVisibility(flags); 188 } 189 showTitle(true); 190 } 191 192 /** 193 * Sets the drawable displayed in the fragment title. 194 * 195 * @param drawable The Drawable to display in the fragment title. 196 */ 197 public void setBadgeDrawable(Drawable drawable) { 198 if (mBadgeDrawable != drawable) { 199 mBadgeDrawable = drawable; 200 if (mTitleViewAdapter != null) { 201 mTitleViewAdapter.setBadgeDrawable(drawable); 202 } 203 } 204 } 205 206 /** 207 * Returns the badge drawable used in the fragment title. 208 * @return The badge drawable used in the fragment title. 209 */ 210 public Drawable getBadgeDrawable() { 211 return mBadgeDrawable; 212 } 213 214 /** 215 * Sets title text for the fragment. 216 * 217 * @param title The title text of the fragment. 218 */ 219 public void setTitle(CharSequence title) { 220 mTitle = title; 221 if (mTitleViewAdapter != null) { 222 mTitleViewAdapter.setTitle(title); 223 } 224 } 225 226 /** 227 * Returns the title text for the fragment. 228 * @return Title text for the fragment. 229 */ 230 public CharSequence getTitle() { 231 return mTitle; 232 } 233 234 /** 235 * Sets a click listener for the search affordance. 236 * 237 * <p>The presence of a listener will change the visibility of the search 238 * affordance in the fragment title. When set to non-null, the title will 239 * contain an element that a user may click to begin a search. 240 * 241 * <p>The listener's {@link View.OnClickListener#onClick onClick} method 242 * will be invoked when the user clicks on the search element. 243 * 244 * @param listener The listener to call when the search element is clicked. 245 */ 246 public void setOnSearchClickedListener(View.OnClickListener listener) { 247 mExternalOnSearchClickedListener = listener; 248 if (mTitleViewAdapter != null) { 249 mTitleViewAdapter.setOnSearchClickedListener(listener); 250 } 251 } 252 253 /** 254 * Sets the {@link android.support.v17.leanback.widget.SearchOrbView.Colors} used to draw the 255 * search affordance. 256 * 257 * @param colors Colors used to draw search affordance. 258 */ 259 public void setSearchAffordanceColors(SearchOrbView.Colors colors) { 260 mSearchAffordanceColors = colors; 261 mSearchAffordanceColorSet = true; 262 if (mTitleViewAdapter != null) { 263 mTitleViewAdapter.setSearchAffordanceColors(mSearchAffordanceColors); 264 } 265 } 266 267 /** 268 * Returns the {@link android.support.v17.leanback.widget.SearchOrbView.Colors} 269 * used to draw the search affordance. 270 */ 271 public SearchOrbView.Colors getSearchAffordanceColors() { 272 if (mSearchAffordanceColorSet) { 273 return mSearchAffordanceColors; 274 } 275 if (mTitleViewAdapter == null) { 276 throw new IllegalStateException("Fragment views not yet created"); 277 } 278 return mTitleViewAdapter.getSearchAffordanceColors(); 279 } 280 281 /** 282 * Sets the color used to draw the search affordance. 283 * A default brighter color will be set by the framework. 284 * 285 * @param color The color to use for the search affordance. 286 */ 287 public void setSearchAffordanceColor(int color) { 288 setSearchAffordanceColors(new SearchOrbView.Colors(color)); 289 } 290 291 /** 292 * Returns the color used to draw the search affordance. 293 */ 294 public int getSearchAffordanceColor() { 295 return getSearchAffordanceColors().color; 296 } 297 298 @Override 299 public void onStart() { 300 super.onStart(); 301 if (mTitleViewAdapter != null) { 302 showTitle(mShowingTitle); 303 mTitleViewAdapter.setAnimationEnabled(true); 304 } 305 } 306 307 @Override 308 public void onPause() { 309 if (mTitleViewAdapter != null) { 310 mTitleViewAdapter.setAnimationEnabled(false); 311 } 312 super.onPause(); 313 } 314 315 @Override 316 public void onResume() { 317 super.onResume(); 318 if (mTitleViewAdapter != null) { 319 mTitleViewAdapter.setAnimationEnabled(true); 320 } 321 } 322 323 /** 324 * Returns true/false to indicate the visibility of TitleView. 325 * 326 * @return boolean to indicate whether or not it's showing the title. 327 */ 328 public final boolean isShowingTitle() { 329 return mShowingTitle; 330 } 331 332} 333