BrowseFragment.java revision e34cae48707e70442aca13e1b4ab55757292828d
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.support.v17.leanback.R; 17import android.support.v17.leanback.widget.HorizontalGridView; 18import android.support.v17.leanback.widget.Presenter; 19import android.support.v17.leanback.widget.PresenterSelector; 20import android.support.v17.leanback.widget.VerticalGridView; 21import android.support.v17.leanback.widget.Row; 22import android.support.v17.leanback.widget.ObjectAdapter; 23import android.support.v17.leanback.widget.OnItemSelectedListener; 24import android.support.v17.leanback.widget.OnItemClickedListener; 25import android.support.v17.leanback.widget.SearchOrbView; 26import android.util.Log; 27import android.util.SparseIntArray; 28import android.app.Fragment; 29import android.content.res.TypedArray; 30import android.os.Bundle; 31import android.view.LayoutInflater; 32import android.view.View; 33import android.view.View.OnClickListener; 34import android.view.ViewGroup; 35import android.view.ViewGroup.MarginLayoutParams; 36import android.widget.ImageView; 37import android.widget.TextView; 38import android.graphics.drawable.Drawable; 39 40import java.util.ArrayList; 41 42import static android.support.v7.widget.RecyclerView.NO_POSITION; 43 44/** 45 * Wrapper fragment for leanback browse screens. Composed of a 46 * RowsFragment and a HeadersFragment. 47 * 48 */ 49public class BrowseFragment extends Fragment { 50 private static final String TAG = "BrowseFragment"; 51 private static boolean DEBUG = false; 52 53 /** The fastlane navigation panel is enabled and shown by default. */ 54 public static final int HEADERS_ENABLED = 1; 55 56 /** The fastlane navigation panel is enabled and hidden by default. */ 57 public static final int HEADERS_HIDDEN = 2; 58 59 /** The fastlane navigation panel is disabled and will never be shown. */ 60 public static final int HEADERS_DISABLED = 3; 61 62 private RowsFragment mRowsFragment; 63 private HeadersFragment mHeadersFragment; 64 65 private ObjectAdapter mAdapter; 66 67 private Params mParams; 68 private BrowseFrameLayout mBrowseFrame; 69 private ImageView mBadgeView; 70 private TextView mTitleView; 71 private ViewGroup mBrowseTitle; 72 private SearchOrbView mSearchOrbView; 73 private boolean mShowingTitle = true; 74 private boolean mShowingHeaders = true; 75 private boolean mCanShowHeaders = true; 76 private int mContainerListMarginLeft; 77 private int mContainerListAlignTop; 78 private OnItemSelectedListener mExternalOnItemSelectedListener; 79 private OnClickListener mExternalOnSearchClickedListener; 80 private OnItemClickedListener mOnItemClickedListener; 81 private int mSelectedPosition = -1; 82 83 private PresenterSelector mHeaderPresenterSelector; 84 85 // transition related: 86 private static TransitionHelper sTransitionHelper = TransitionHelper.getInstance(); 87 private static int sReparentHeaderId = View.generateViewId(); 88 private Object mSceneWithTitle; 89 private Object mSceneWithoutTitle; 90 private Object mSceneWithHeaders; 91 private Object mSceneWithoutHeaders; 92 private Object mTitleTransition; 93 private Object mHeadersTransition; 94 private int mHeadersTransitionStartDelay; 95 96 private static final String ARG_TITLE = BrowseFragment.class.getCanonicalName() + ".title"; 97 private static final String ARG_BADGE_URI = BrowseFragment.class.getCanonicalName() + ".badge"; 98 private static final String ARG_HEADERS_STATE = 99 BrowseFragment.class.getCanonicalName() + ".headersState"; 100 101 /** 102 * @param args Bundle to use for the arguments, if null a new Bundle will be created. 103 */ 104 public static Bundle createArgs(Bundle args, String title, String badgeUri) { 105 return createArgs(args, title, badgeUri, HEADERS_ENABLED); 106 } 107 108 public static Bundle createArgs(Bundle args, String title, String badgeUri, int headersState) { 109 if (args == null) { 110 args = new Bundle(); 111 } 112 args.putString(ARG_TITLE, title); 113 args.putString(ARG_BADGE_URI, badgeUri); 114 args.putInt(ARG_HEADERS_STATE, headersState); 115 return args; 116 } 117 118 public static class Params { 119 private String mTitle; 120 private Drawable mBadgeDrawable; 121 private int mHeadersState; 122 123 /** 124 * Sets the badge image. 125 */ 126 public void setBadgeImage(Drawable drawable) { 127 mBadgeDrawable = drawable; 128 } 129 130 /** 131 * Returns the badge image. 132 */ 133 public Drawable getBadgeImage() { 134 return mBadgeDrawable; 135 } 136 137 /** 138 * Sets a title for the browse fragment. 139 */ 140 public void setTitle(String title) { 141 mTitle = title; 142 } 143 144 /** 145 * Returns the title for the browse fragment. 146 */ 147 public String getTitle() { 148 return mTitle; 149 } 150 151 /** 152 * Sets the state for the headers column in the browse fragment. 153 */ 154 public void setHeadersState(int headersState) { 155 if (headersState < HEADERS_ENABLED || headersState > HEADERS_DISABLED) { 156 Log.e(TAG, "Invalid headers state: " + headersState 157 + ", default to enabled and shown."); 158 mHeadersState = HEADERS_ENABLED; 159 } else { 160 mHeadersState = headersState; 161 } 162 } 163 164 /** 165 * Returns the state for the headers column in the browse fragment. 166 */ 167 public int getHeadersState() { 168 return mHeadersState; 169 } 170 } 171 172 /** 173 * Set browse parameters. 174 */ 175 public void setBrowseParams(Params params) { 176 mParams = params; 177 setBadgeDrawable(mParams.mBadgeDrawable); 178 setTitle(mParams.mTitle); 179 setHeadersState(mParams.mHeadersState); 180 } 181 182 /** 183 * Returns browse parameters. 184 */ 185 public Params getBrowseParams() { 186 return mParams; 187 } 188 189 /** 190 * Sets the list of rows for the fragment. 191 */ 192 public void setAdapter(ObjectAdapter adapter) { 193 mAdapter = adapter; 194 if (mRowsFragment != null) { 195 mRowsFragment.setAdapter(adapter); 196 mHeadersFragment.setAdapter(adapter); 197 } 198 } 199 200 /** 201 * Returns the list of rows. 202 */ 203 public ObjectAdapter getAdapter() { 204 return mAdapter; 205 } 206 207 /** 208 * Sets an item selection listener. 209 */ 210 public void setOnItemSelectedListener(OnItemSelectedListener listener) { 211 mExternalOnItemSelectedListener = listener; 212 } 213 214 /** 215 * Sets an item clicked listener on the fragment. 216 * OnItemClickedListener will override {@link View.OnClickListener} that 217 * item presenter sets during {@link Presenter#onCreateViewHolder(ViewGroup)}. 218 * So in general, developer should choose one of the listeners but not both. 219 */ 220 public void setOnItemClickedListener(OnItemClickedListener listener) { 221 mOnItemClickedListener = listener; 222 if (mRowsFragment != null) { 223 mRowsFragment.setOnItemClickedListener(listener); 224 } 225 } 226 227 /** 228 * Returns the item Clicked listener. 229 */ 230 public OnItemClickedListener getOnItemClickedListener() { 231 return mOnItemClickedListener; 232 } 233 234 /** 235 * Sets a click listener for the search affordance. 236 * 237 * The presence of a listener will change the visibility of the search affordance in the 238 * title area. When set to non-null the title area will contain a call to search action. 239 * 240 * The listener onClick method will be invoked when the user click on the search action. 241 * 242 * @param listener The listener. 243 */ 244 public void setOnSearchClickedListener(View.OnClickListener listener) { 245 mExternalOnSearchClickedListener = listener; 246 if (mSearchOrbView != null) { 247 mSearchOrbView.setOnOrbClickedListener(listener); 248 } 249 } 250 251 private void onHeadersTransitionStart(boolean withHeaders) { 252 mRowsFragment.getVerticalGridView().setAnimateChildLayout(false); 253 mRowsFragment.getVerticalGridView().setFocusSearchDisabled(true); 254 mHeadersFragment.getVerticalGridView().setFocusSearchDisabled(true); 255 createHeadersTransition(withHeaders); 256 } 257 258 private boolean isVerticalScrolling() { 259 // don't run transition 260 return mHeadersFragment.getVerticalGridView().getScrollState() 261 != HorizontalGridView.SCROLL_STATE_IDLE 262 || mRowsFragment.getVerticalGridView().getScrollState() 263 != HorizontalGridView.SCROLL_STATE_IDLE; 264 } 265 266 private final BrowseFrameLayout.OnFocusSearchListener mOnFocusSearchListener = 267 new BrowseFrameLayout.OnFocusSearchListener() { 268 @Override 269 public View onFocusSearch(View focused, int direction) { 270 // If fastlane is disabled, just return null. 271 if (!mCanShowHeaders) return null; 272 273 // if fast lane is running transition, focus stays 274 if (mHeadersTransition != null) return focused; 275 if (DEBUG) Log.v(TAG, "onFocusSearch focused " + focused + " + direction " + direction); 276 if (direction == View.FOCUS_LEFT) { 277 if (isVerticalScrolling() || mShowingHeaders) { 278 return focused; 279 } 280 return mHeadersFragment.getVerticalGridView(); 281 } else if (direction == View.FOCUS_RIGHT) { 282 if (isVerticalScrolling() || !mShowingHeaders) { 283 return focused; 284 } 285 return mRowsFragment.getVerticalGridView(); 286 } else if (focused == mSearchOrbView && direction == View.FOCUS_DOWN) { 287 return mShowingHeaders ? mHeadersFragment.getVerticalGridView() : 288 mRowsFragment.getVerticalGridView(); 289 290 } else if (focused != mSearchOrbView && mSearchOrbView.getVisibility() == View.VISIBLE 291 && direction == View.FOCUS_UP) { 292 return mSearchOrbView; 293 294 } else { 295 return null; 296 } 297 } 298 }; 299 300 private final BrowseFrameLayout.OnChildFocusListener mOnChildFocusListener = 301 new BrowseFrameLayout.OnChildFocusListener() { 302 @Override 303 public void onRequestChildFocus(View child, View focused) { 304 int childId = child.getId(); 305 if (mHeadersTransition != null) return; 306 if (childId == R.id.browse_container_dock && mShowingHeaders) { 307 mShowingHeaders = false; 308 onHeadersTransitionStart(false); 309 sTransitionHelper.runTransition(mSceneWithoutHeaders, mHeadersTransition); 310 } else if (childId == R.id.browse_headers_dock && !mShowingHeaders) { 311 mShowingHeaders = true; 312 //mHeadersFragment.getView().setAlpha(1f); 313 onHeadersTransitionStart(true); 314 sTransitionHelper.runTransition(mSceneWithHeaders, mHeadersTransition); 315 } 316 } 317 }; 318 319 @Override 320 public void onCreate(Bundle savedInstanceState) { 321 super.onCreate(savedInstanceState); 322 TypedArray ta = getActivity().obtainStyledAttributes(R.styleable.LeanbackTheme); 323 mContainerListMarginLeft = (int) ta.getDimension( 324 R.styleable.LeanbackTheme_browseRowsMarginStart, 0); 325 mContainerListAlignTop = (int) ta.getDimension( 326 R.styleable.LeanbackTheme_browseRowsMarginTop, 0); 327 ta.recycle(); 328 mHeadersTransitionStartDelay = getResources() 329 .getInteger(R.integer.lb_browse_headers_transition_delay); 330 } 331 332 @Override 333 public View onCreateView(LayoutInflater inflater, ViewGroup container, 334 Bundle savedInstanceState) { 335 if (getChildFragmentManager().findFragmentById(R.id.browse_container_dock) == null) { 336 mRowsFragment = new RowsFragment(); 337 mHeadersFragment = new HeadersFragment(); 338 getChildFragmentManager().beginTransaction() 339 .replace(R.id.browse_headers_dock, mHeadersFragment) 340 .replace(R.id.browse_container_dock, mRowsFragment).commit(); 341 } else { 342 mHeadersFragment = (HeadersFragment) getChildFragmentManager() 343 .findFragmentById(R.id.browse_headers_dock); 344 mRowsFragment = (RowsFragment) getChildFragmentManager() 345 .findFragmentById(R.id.browse_container_dock); 346 } 347 mRowsFragment.setAdapter(mAdapter); 348 if (mHeaderPresenterSelector != null) { 349 mHeadersFragment.setPresenterSelector(mHeaderPresenterSelector); 350 } 351 mHeadersFragment.setAdapter(mAdapter); 352 353 mRowsFragment.setOnItemSelectedListener(mRowSelectedListener); 354 mHeadersFragment.setOnItemSelectedListener(mHeaderSelectedListener); 355 mHeadersFragment.setOnHeaderClickedListener(mHeaderClickedListener); 356 mRowsFragment.setOnItemClickedListener(mOnItemClickedListener); 357 358 View root = inflater.inflate(R.layout.lb_browse_fragment, container, false); 359 360 mBrowseFrame = (BrowseFrameLayout) root.findViewById(R.id.browse_frame); 361 mBrowseFrame.setOnFocusSearchListener(mOnFocusSearchListener); 362 mBrowseFrame.setOnChildFocusListener(mOnChildFocusListener); 363 364 mBrowseTitle = (ViewGroup) root.findViewById(R.id.browse_title_group); 365 mBadgeView = (ImageView) mBrowseTitle.findViewById(R.id.browse_badge); 366 mTitleView = (TextView) mBrowseTitle.findViewById(R.id.browse_title); 367 mSearchOrbView = (SearchOrbView) mBrowseTitle.findViewById(R.id.browse_orb); 368 if (mExternalOnSearchClickedListener != null) { 369 mSearchOrbView.setOnOrbClickedListener(mExternalOnSearchClickedListener); 370 } 371 372 readArguments(getArguments()); 373 if (mParams != null) { 374 setBadgeDrawable(mParams.mBadgeDrawable); 375 setTitle(mParams.mTitle); 376 setHeadersState(mParams.mHeadersState); 377 } 378 379 mSceneWithTitle = sTransitionHelper.createScene(mBrowseFrame, new Runnable() { 380 @Override 381 public void run() { 382 showTitle(true); 383 } 384 }); 385 mSceneWithoutTitle = sTransitionHelper.createScene(mBrowseFrame, new Runnable() { 386 @Override 387 public void run() { 388 showTitle(false); 389 } 390 }); 391 mSceneWithHeaders = sTransitionHelper.createScene(mBrowseFrame, new Runnable() { 392 @Override 393 public void run() { 394 showHeaders(true); 395 } 396 }); 397 mSceneWithoutHeaders = sTransitionHelper.createScene(mBrowseFrame, new Runnable() { 398 @Override 399 public void run() { 400 showHeaders(false); 401 } 402 }); 403 mTitleTransition = sTransitionHelper.createAutoTransition(); 404 sTransitionHelper.excludeChildren(mTitleTransition, R.id.browse_headers, true); 405 sTransitionHelper.excludeChildren(mTitleTransition, R.id.container_list, true); 406 407 return root; 408 } 409 410 private void createHeadersTransition(boolean withHeaders) { 411 ArrayList<View> fastHeaders = new ArrayList<View>(); 412 ArrayList<Integer> fastHeaderPositions = new ArrayList<Integer>(); 413 ArrayList<View> headers = new ArrayList<View>(); 414 ArrayList<Integer> headerPositions = new ArrayList<Integer>(); 415 416 mHeadersFragment.getHeaderViews(fastHeaders, fastHeaderPositions); 417 mRowsFragment.getHeaderViews(headers, headerPositions); 418 419 mHeadersTransition = sTransitionHelper.createTransitionSet(true); 420 sTransitionHelper.excludeChildren(mHeadersTransition, R.id.browse_title_group, true); 421 Object changeBounds = sTransitionHelper.createChangeBounds(true); 422 Object fadeIn = sTransitionHelper.createFadeTransition(TransitionHelper.FADE_IN); 423 Object fadeOut = sTransitionHelper.createFadeTransition(TransitionHelper.FADE_OUT); 424 if (!withHeaders) { 425 sTransitionHelper.setChangeBoundsDefaultStartDelay(changeBounds, 426 mHeadersTransitionStartDelay); 427 } 428 429 for (int i = 0; i < headerPositions.size(); i++) { 430 Integer position = headerPositions.get(i); 431 if (position == mSelectedPosition) { 432 headers.get(i).setId(sReparentHeaderId); 433 sTransitionHelper.setChangeBoundsStartDelay(changeBounds, sReparentHeaderId, 434 withHeaders ? mHeadersTransitionStartDelay : 0); 435 sTransitionHelper.exclude(fadeIn, headers.get(i), true); 436 sTransitionHelper.exclude(fadeOut, headers.get(i), true); 437 } else { 438 headers.get(i).setId(View.NO_ID); 439 } 440 } 441 for (int i = 0; i < fastHeaderPositions.size(); i++) { 442 Integer position = fastHeaderPositions.get(i); 443 if (position == mSelectedPosition) { 444 fastHeaders.get(i).setId(sReparentHeaderId); 445 sTransitionHelper.setChangeBoundsStartDelay(changeBounds, sReparentHeaderId, 446 withHeaders ? mHeadersTransitionStartDelay : 0); 447 sTransitionHelper.exclude(fadeIn, fastHeaders.get(i), true); 448 sTransitionHelper.exclude(fadeOut, fastHeaders.get(i), true); 449 } else { 450 fastHeaders.get(i).setId(View.NO_ID); 451 } 452 } 453 454 sTransitionHelper.addTransition(mHeadersTransition, fadeOut); 455 sTransitionHelper.addTransition(mHeadersTransition, changeBounds); 456 sTransitionHelper.addTransition(mHeadersTransition, fadeIn); 457 458 sTransitionHelper.setTransitionCompleteListener(mHeadersTransition, new Runnable() { 459 @Override 460 public void run() { 461 mHeadersTransition = null; 462 // TODO: deal fragment destroy view properly 463 VerticalGridView rowsGridView = mRowsFragment.getVerticalGridView(); 464 if (rowsGridView != null) { 465 rowsGridView.setAnimateChildLayout(true); 466 rowsGridView.setFocusSearchDisabled(false); 467 if (!mShowingHeaders && !rowsGridView.hasFocus()) { 468 rowsGridView.requestFocus(); 469 } 470 } 471 VerticalGridView headerGridView = mHeadersFragment.getVerticalGridView(); 472 if (headerGridView != null) { 473 headerGridView.setFocusSearchDisabled(false); 474 headerGridView.invalidate(); 475 if (mShowingHeaders && !headerGridView.hasFocus()) { 476 headerGridView.requestFocus(); 477 } 478 } 479 } 480 }); 481 } 482 483 public void setHeaderPresenterSelector(PresenterSelector headerPresenterSelector) { 484 mHeaderPresenterSelector = headerPresenterSelector; 485 if (mHeadersFragment != null) { 486 mHeadersFragment.setPresenterSelector(mHeaderPresenterSelector); 487 } 488 } 489 490 private void showTitle(boolean show) { 491 mBrowseTitle.setVisibility(show ? View.VISIBLE : View.GONE); 492 } 493 494 private void showHeaders(boolean show) { 495 if (DEBUG) Log.v(TAG, "showHeaders " + show); 496 mHeadersFragment.setHeadersVisiblity(show); 497 498 View containerList = mRowsFragment.getView(); 499 MarginLayoutParams lp; 500 lp = (MarginLayoutParams) containerList.getLayoutParams(); 501 lp.leftMargin = show ? mContainerListMarginLeft : 0; 502 containerList.setLayoutParams(lp); 503 mRowsFragment.setExpand(!show); 504 } 505 506 private HeadersFragment.OnHeaderClickedListener mHeaderClickedListener = 507 new HeadersFragment.OnHeaderClickedListener() { 508 @Override 509 public void onHeaderClicked() { 510 if (!mCanShowHeaders || !mShowingHeaders) return; 511 512 if (mHeadersTransition != null) { 513 return; 514 } 515 mShowingHeaders = false; 516 onHeadersTransitionStart(false); 517 sTransitionHelper.runTransition(mSceneWithoutHeaders, mHeadersTransition); 518 mRowsFragment.getVerticalGridView().requestFocus(); 519 } 520 }; 521 522 private OnItemSelectedListener mRowSelectedListener = new OnItemSelectedListener() { 523 @Override 524 public void onItemSelected(Object item, Row row) { 525 int position = mRowsFragment.getVerticalGridView().getSelectedPosition(); 526 if (DEBUG) Log.v(TAG, "row selected position " + position); 527 onRowSelected(position); 528 if (mExternalOnItemSelectedListener != null) { 529 mExternalOnItemSelectedListener.onItemSelected(item, row); 530 } 531 } 532 }; 533 534 private OnItemSelectedListener mHeaderSelectedListener = new OnItemSelectedListener() { 535 @Override 536 public void onItemSelected(Object item, Row row) { 537 int position = mHeadersFragment.getVerticalGridView().getSelectedPosition(); 538 if (DEBUG) Log.v(TAG, "header selected position " + position); 539 onRowSelected(position); 540 } 541 }; 542 543 private void onRowSelected(int position) { 544 if (position != mSelectedPosition) { 545 mSetSelectionRunnable.mPosition = position; 546 mBrowseFrame.getHandler().post(mSetSelectionRunnable); 547 548 if (position == 0) { 549 if (!mShowingTitle) { 550 sTransitionHelper.runTransition(mSceneWithTitle, mTitleTransition); 551 mShowingTitle = true; 552 } 553 } else if (mShowingTitle) { 554 sTransitionHelper.runTransition(mSceneWithoutTitle, mTitleTransition); 555 mShowingTitle = false; 556 } 557 } 558 } 559 560 private class SetSelectionRunnable implements Runnable { 561 int mPosition; 562 @Override 563 public void run() { 564 setSelection(mPosition); 565 } 566 } 567 568 private final SetSelectionRunnable mSetSelectionRunnable = new SetSelectionRunnable(); 569 570 private void setSelection(int position) { 571 if (position != NO_POSITION) { 572 mRowsFragment.setSelectedPosition(position); 573 mHeadersFragment.setSelectedPosition(position); 574 } 575 mSelectedPosition = position; 576 } 577 578 private void setVerticalVerticalGridViewLayout(VerticalGridView listview, int extraOffset) { 579 // align the top edge of item to a fixed position 580 listview.setItemAlignmentOffset(0); 581 listview.setItemAlignmentOffsetPercent(VerticalGridView.ITEM_ALIGN_OFFSET_PERCENT_DISABLED); 582 listview.setWindowAlignmentOffset(mContainerListAlignTop + extraOffset); 583 listview.setWindowAlignmentOffsetPercent(VerticalGridView.WINDOW_ALIGN_OFFSET_PERCENT_DISABLED); 584 listview.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_NO_EDGE); 585 } 586 587 /** 588 * Setup dimensions that are only meaningful when the child Fragments are inside 589 * BrowseFragment. 590 */ 591 private void setupChildFragmentsLayout() { 592 VerticalGridView headerList = mHeadersFragment.getVerticalGridView(); 593 VerticalGridView containerList = mRowsFragment.getVerticalGridView(); 594 595 // Both fragments list view has the same alignment 596 setVerticalVerticalGridViewLayout(headerList, 16); 597 setVerticalVerticalGridViewLayout(containerList, 0); 598 } 599 600 @Override 601 public void onStart() { 602 super.onStart(); 603 setupChildFragmentsLayout(); 604 if (mCanShowHeaders && mShowingHeaders && mHeadersFragment.getView() != null) { 605 mHeadersFragment.getView().requestFocus(); 606 } else if ((!mCanShowHeaders || !mShowingHeaders) 607 && mRowsFragment.getView() != null) { 608 mRowsFragment.getView().requestFocus(); 609 } 610 showHeaders(mCanShowHeaders && mShowingHeaders); 611 } 612 613 private void readArguments(Bundle args) { 614 if (args == null) { 615 return; 616 } 617 if (args.containsKey(ARG_TITLE)) { 618 setTitle(args.getString(ARG_TITLE)); 619 } 620 621 if (args.containsKey(ARG_BADGE_URI)) { 622 setBadgeUri(args.getString(ARG_BADGE_URI)); 623 } 624 625 if (args.containsKey(ARG_HEADERS_STATE)) { 626 setHeadersState(args.getInt(ARG_HEADERS_STATE)); 627 } 628 } 629 630 private void setBadgeUri(String badgeUri) { 631 // TODO - need a drawable downloader 632 } 633 634 private void setBadgeDrawable(Drawable drawable) { 635 if (mBadgeView == null) { 636 return; 637 } 638 mBadgeView.setImageDrawable(drawable); 639 if (drawable != null) { 640 mBadgeView.setVisibility(View.VISIBLE); 641 } else { 642 mBadgeView.setVisibility(View.GONE); 643 } 644 } 645 646 private void setTitle(String title) { 647 if (mTitleView != null) { 648 mTitleView.setText(title); 649 } 650 } 651 652 private void setHeadersState(int headersState) { 653 if (DEBUG) Log.v(TAG, "setHeadersState " + headersState); 654 switch (headersState) { 655 case HEADERS_ENABLED: 656 mCanShowHeaders = true; 657 mShowingHeaders = true; 658 break; 659 case HEADERS_HIDDEN: 660 mCanShowHeaders = true; 661 mShowingHeaders = false; 662 break; 663 case HEADERS_DISABLED: 664 mCanShowHeaders = false; 665 mShowingHeaders = false; 666 break; 667 default: 668 Log.w(TAG, "Unknown headers state: " + headersState); 669 break; 670 } 671 } 672} 673