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