PreferenceActivity.java revision b3cf10ffa8ff9cac0da8b23a0d84076b3f501400
1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.preference; 18 19import com.android.internal.util.XmlUtils; 20 21import org.xmlpull.v1.XmlPullParser; 22import org.xmlpull.v1.XmlPullParserException; 23 24import android.app.Fragment; 25import android.app.ListActivity; 26import android.content.Context; 27import android.content.Intent; 28import android.content.res.Configuration; 29import android.content.res.TypedArray; 30import android.content.res.XmlResourceParser; 31import android.graphics.drawable.Drawable; 32import android.os.Bundle; 33import android.os.Handler; 34import android.os.Message; 35import android.text.TextUtils; 36import android.util.AttributeSet; 37import android.util.Log; 38import android.util.Xml; 39import android.view.LayoutInflater; 40import android.view.View; 41import android.view.ViewGroup; 42import android.view.View.OnClickListener; 43import android.widget.ArrayAdapter; 44import android.widget.Button; 45import android.widget.ImageView; 46import android.widget.ListView; 47import android.widget.TextView; 48 49import java.io.IOException; 50import java.util.ArrayList; 51import java.util.List; 52 53/** 54 * This is the base class for an activity to show a hierarchy of preferences 55 * to the user. Prior to {@link android.os.Build.VERSION_CODES#HONEYCOMB} 56 * this class only allowed the display of a single set of preference; this 57 * functionality should now be found in the new {@link PreferenceFragment} 58 * class. If you are using PreferenceActivity in its old mode, the documentation 59 * there applies to the deprecated APIs here. 60 * 61 * <p>This activity shows one or more headers of preferences, each of with 62 * is associated with a {@link PreferenceFragment} to display the preferences 63 * of that header. The actual layout and display of these associations can 64 * however vary; currently there are two major approaches it may take: 65 * 66 * <ul> 67 * <li>On a small screen it may display only the headers as a single list 68 * when first launched. Selecting one of the header items will re-launch 69 * the activity with it only showing the PreferenceFragment of that header. 70 * <li>On a large screen in may display both the headers and current 71 * PreferenceFragment together as panes. Selecting a header item switches 72 * to showing the correct PreferenceFragment for that item. 73 * </ul> 74 * 75 * <p>Subclasses of PreferenceActivity should implement 76 * {@link #onBuildHeaders} to populate the header list with the desired 77 * items. Doing this implicitly switches the class into its new "headers 78 * + fragments" mode rather than the old style of just showing a single 79 * preferences list. 80 * 81 * <a name="SampleCode"></a> 82 * <h3>Sample Code</h3> 83 * 84 * <p>The following sample code shows a simple preference activity that 85 * has two different sets of preferences. The implementation, consisting 86 * of the activity itself as well as its two preference fragments is:</p> 87 * 88 * {@sample development/samples/ApiDemos/src/com/example/android/apis/preference/PreferenceWithHeaders.java 89 * activity} 90 * 91 * <p>The preference_headers resource describes the headers to be displayed 92 * and the fragments associated with them. It is: 93 * 94 * {@sample development/samples/ApiDemos/res/xml/preference_headers.xml headers} 95 * 96 * <p>The first header is shown by Prefs1Fragment, which populates itself 97 * from the following XML resource:</p> 98 * 99 * {@sample development/samples/ApiDemos/res/xml/fragmented_preferences.xml preferences} 100 * 101 * <p>Note that this XML resource contains a preference screen holding another 102 * fragment, the Prefs1FragmentInner implemented here. This allows the user 103 * to traverse down a hierarchy of preferences; pressing back will pop each 104 * fragment off the stack to return to the previous preferences. 105 * 106 * <p>See {@link PreferenceFragment} for information on implementing the 107 * fragments themselves. 108 */ 109public abstract class PreferenceActivity extends ListActivity implements 110 PreferenceManager.OnPreferenceTreeClickListener, 111 PreferenceFragment.OnPreferenceStartFragmentCallback { 112 private static final String TAG = "PreferenceActivity"; 113 114 private static final String PREFERENCES_TAG = "android:preferences"; 115 116 private static final String EXTRA_PREFS_SHOW_FRAGMENT = ":android:show_fragment"; 117 118 private static final String EXTRA_PREFS_NO_HEADERS = ":android:no_headers"; 119 120 private static final String BACK_STACK_PREFS = ":android:prefs"; 121 122 // extras that allow any preference activity to be launched as part of a wizard 123 124 // show Back and Next buttons? takes boolean parameter 125 // Back will then return RESULT_CANCELED and Next RESULT_OK 126 private static final String EXTRA_PREFS_SHOW_BUTTON_BAR = "extra_prefs_show_button_bar"; 127 128 // specify custom text for the Back or Next buttons, or cause a button to not appear 129 // at all by setting it to null 130 private static final String EXTRA_PREFS_SET_NEXT_TEXT = "extra_prefs_set_next_text"; 131 private static final String EXTRA_PREFS_SET_BACK_TEXT = "extra_prefs_set_back_text"; 132 133 // --- State for new mode when showing a list of headers + prefs fragment 134 135 private final ArrayList<Header> mHeaders = new ArrayList<Header>(); 136 137 private HeaderAdapter mAdapter; 138 139 private View mPrefsContainer; 140 141 private boolean mSinglePane; 142 143 // --- State for old mode when showing a single preference list 144 145 private PreferenceManager mPreferenceManager; 146 147 private Bundle mSavedInstanceState; 148 149 // --- Common state 150 151 private Button mNextButton; 152 153 /** 154 * The starting request code given out to preference framework. 155 */ 156 private static final int FIRST_REQUEST_CODE = 100; 157 158 private static final int MSG_BIND_PREFERENCES = 0; 159 private Handler mHandler = new Handler() { 160 @Override 161 public void handleMessage(Message msg) { 162 switch (msg.what) { 163 164 case MSG_BIND_PREFERENCES: 165 bindPreferences(); 166 break; 167 } 168 } 169 }; 170 171 private class HeaderViewHolder { 172 ImageView icon; 173 TextView title; 174 TextView summary; 175 } 176 177 private class HeaderAdapter extends ArrayAdapter<Header> { 178 private LayoutInflater mInflater; 179 180 public HeaderAdapter(Context context, List<Header> objects) { 181 super(context, 0, objects); 182 mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 183 } 184 185 @Override 186 public View getView(int position, View convertView, ViewGroup parent) { 187 HeaderViewHolder holder; 188 View view; 189 190 if (convertView == null) { 191 view = mInflater.inflate(com.android.internal.R.layout.preference_list_item, 192 parent, false); 193 holder = new HeaderViewHolder(); 194 holder.icon = (ImageView)view.findViewById( 195 com.android.internal.R.id.icon); 196 holder.title = (TextView)view.findViewById( 197 com.android.internal.R.id.title); 198 holder.summary = (TextView)view.findViewById( 199 com.android.internal.R.id.summary); 200 view.setTag(holder); 201 } else { 202 view = convertView; 203 holder = (HeaderViewHolder)view.getTag(); 204 } 205 206 Header header = getItem(position); 207 if (header.icon != null) holder.icon.setImageDrawable(header.icon); 208 else if (header.iconRes != 0) holder.icon.setImageResource(header.iconRes); 209 if (header.title != null) holder.title.setText(header.title); 210 if (header.summary != null) holder.summary.setText(header.summary); 211 212 return view; 213 } 214 } 215 216 /** 217 * Description of a single Header item that the user can select. 218 */ 219 public static class Header { 220 /** 221 * Title of the header that is shown to the user. 222 * @attr ref android.R.styleable#PreferenceHeader_title 223 */ 224 CharSequence title; 225 226 /** 227 * Optional summary describing what this header controls. 228 * @attr ref android.R.styleable#PreferenceHeader_summary 229 */ 230 CharSequence summary; 231 232 /** 233 * Optional icon resource to show for this header. 234 * @attr ref android.R.styleable#PreferenceHeader_icon 235 */ 236 int iconRes; 237 238 /** 239 * Optional icon drawable to show for this header. (If this is non-null, 240 * the iconRes will be ignored.) 241 */ 242 Drawable icon; 243 244 /** 245 * Full class name of the fragment to display when this header is 246 * selected. 247 * @attr ref android.R.styleable#PreferenceHeader_fragment 248 */ 249 String fragment; 250 } 251 252 @Override 253 protected void onCreate(Bundle savedInstanceState) { 254 super.onCreate(savedInstanceState); 255 256 setContentView(com.android.internal.R.layout.preference_list_content); 257 258 mPrefsContainer = findViewById(com.android.internal.R.id.prefs); 259 boolean hidingHeaders = onIsHidingHeaders(); 260 mSinglePane = hidingHeaders || !onIsMultiPane(); 261 String initialFragment = getIntent().getStringExtra(EXTRA_PREFS_SHOW_FRAGMENT); 262 263 if (initialFragment != null && mSinglePane) { 264 // If we are just showing a fragment, we want to run in 265 // new fragment mode, but don't need to compute and show 266 // the headers. 267 getListView().setVisibility(View.GONE); 268 mPrefsContainer.setVisibility(View.VISIBLE); 269 switchToHeader(initialFragment); 270 271 } else { 272 // We need to try to build the headers. 273 onBuildHeaders(mHeaders); 274 275 // If there are headers, then at this point we need to show 276 // them and, depending on the screen, we may also show in-line 277 // the currently selected preference fragment. 278 if (mHeaders.size() > 0) { 279 mAdapter = new HeaderAdapter(this, mHeaders); 280 setListAdapter(mAdapter); 281 if (!mSinglePane) { 282 mPrefsContainer.setVisibility(View.VISIBLE); 283 switchToHeader(initialFragment != null 284 ? initialFragment : onGetInitialFragment()); 285 } 286 287 // If there are no headers, we are in the old "just show a screen 288 // of preferences" mode. 289 } else { 290 mPreferenceManager = new PreferenceManager(this, FIRST_REQUEST_CODE); 291 mPreferenceManager.setOnPreferenceTreeClickListener(this); 292 } 293 } 294 295 getListView().setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); 296 297 // see if we should show Back/Next buttons 298 Intent intent = getIntent(); 299 if (intent.getBooleanExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false)) { 300 301 findViewById(com.android.internal.R.id.button_bar).setVisibility(View.VISIBLE); 302 303 Button backButton = (Button)findViewById(com.android.internal.R.id.back_button); 304 backButton.setOnClickListener(new OnClickListener() { 305 public void onClick(View v) { 306 setResult(RESULT_CANCELED); 307 finish(); 308 } 309 }); 310 mNextButton = (Button)findViewById(com.android.internal.R.id.next_button); 311 mNextButton.setOnClickListener(new OnClickListener() { 312 public void onClick(View v) { 313 setResult(RESULT_OK); 314 finish(); 315 } 316 }); 317 318 // set our various button parameters 319 if (intent.hasExtra(EXTRA_PREFS_SET_NEXT_TEXT)) { 320 String buttonText = intent.getStringExtra(EXTRA_PREFS_SET_NEXT_TEXT); 321 if (TextUtils.isEmpty(buttonText)) { 322 mNextButton.setVisibility(View.GONE); 323 } 324 else { 325 mNextButton.setText(buttonText); 326 } 327 } 328 if (intent.hasExtra(EXTRA_PREFS_SET_BACK_TEXT)) { 329 String buttonText = intent.getStringExtra(EXTRA_PREFS_SET_BACK_TEXT); 330 if (TextUtils.isEmpty(buttonText)) { 331 backButton.setVisibility(View.GONE); 332 } 333 else { 334 backButton.setText(buttonText); 335 } 336 } 337 } 338 } 339 340 /** 341 * Called to determine if the activity should run in multi-pane mode. 342 * The default implementation returns true if the screen is large 343 * enough. 344 */ 345 public boolean onIsMultiPane() { 346 Configuration config = getResources().getConfiguration(); 347 if ((config.screenLayout&Configuration.SCREENLAYOUT_SIZE_MASK) 348 == Configuration.SCREENLAYOUT_SIZE_XLARGE 349 && config.orientation == Configuration.ORIENTATION_LANDSCAPE) { 350 return true; 351 } 352 return false; 353 } 354 355 /** 356 * Called to determine whether the header list should be hidden. The 357 * default implementation hides the list if the activity is being re-launched 358 * when not in multi-pane mode. 359 */ 360 public boolean onIsHidingHeaders() { 361 return getIntent().getBooleanExtra(EXTRA_PREFS_NO_HEADERS, false); 362 } 363 364 /** 365 * Called to determine the initial fragment to be shown. The default 366 * implementation simply returns the fragment of the first header. 367 */ 368 public String onGetInitialFragment() { 369 return mHeaders.get(0).fragment; 370 } 371 372 /** 373 * Called when the activity needs its list of headers build. By 374 * implementing this and adding at least one item to the list, you 375 * will cause the activity to run in its modern fragment mode. Note 376 * that this function may not always be called; for example, if the 377 * activity has been asked to display a particular fragment without 378 * the header list, there is no need to build the headers. 379 * 380 * <p>Typical implementations will use {@link #loadHeadersFromResource} 381 * to fill in the list from a resource. 382 * 383 * @param target The list in which to place the headers. 384 */ 385 public void onBuildHeaders(List<Header> target) { 386 } 387 388 /** 389 * Parse the given XML file as a header description, adding each 390 * parsed Header into the target list. 391 * 392 * @param resid The XML resource to load and parse. 393 * @param target The list in which the parsed headers should be placed. 394 */ 395 public void loadHeadersFromResource(int resid, List<Header> target) { 396 XmlResourceParser parser = null; 397 try { 398 parser = getResources().getXml(resid); 399 AttributeSet attrs = Xml.asAttributeSet(parser); 400 401 int type; 402 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 403 && type != XmlPullParser.START_TAG) { 404 } 405 406 String nodeName = parser.getName(); 407 if (!"PreferenceHeaders".equals(nodeName)) { 408 throw new RuntimeException( 409 "XML document must start with <PreferenceHeaders> tag; found" 410 + nodeName + " at " + parser.getPositionDescription()); 411 } 412 413 int outerDepth = parser.getDepth(); 414 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 415 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 416 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 417 continue; 418 } 419 420 nodeName = parser.getName(); 421 if ("Header".equals(nodeName)) { 422 Header header = new Header(); 423 424 TypedArray sa = getResources().obtainAttributes(attrs, 425 com.android.internal.R.styleable.PreferenceHeader); 426 header.title = sa.getText( 427 com.android.internal.R.styleable.PreferenceHeader_title); 428 header.summary = sa.getText( 429 com.android.internal.R.styleable.PreferenceHeader_summary); 430 header.iconRes = sa.getResourceId( 431 com.android.internal.R.styleable.PreferenceHeader_icon, 0); 432 header.fragment = sa.getString( 433 com.android.internal.R.styleable.PreferenceHeader_fragment); 434 sa.recycle(); 435 436 target.add(header); 437 438 XmlUtils.skipCurrentTag(parser); 439 } else { 440 XmlUtils.skipCurrentTag(parser); 441 } 442 } 443 444 } catch (XmlPullParserException e) { 445 throw new RuntimeException("Error parsing headers", e); 446 } catch (IOException e) { 447 throw new RuntimeException("Error parsing headers", e); 448 } finally { 449 if (parser != null) parser.close(); 450 } 451 452 } 453 454 @Override 455 protected void onStop() { 456 super.onStop(); 457 458 if (mPreferenceManager != null) { 459 mPreferenceManager.dispatchActivityStop(); 460 } 461 } 462 463 @Override 464 protected void onDestroy() { 465 super.onDestroy(); 466 467 if (mPreferenceManager != null) { 468 mPreferenceManager.dispatchActivityDestroy(); 469 } 470 } 471 472 @Override 473 protected void onSaveInstanceState(Bundle outState) { 474 super.onSaveInstanceState(outState); 475 476 if (mPreferenceManager != null) { 477 final PreferenceScreen preferenceScreen = getPreferenceScreen(); 478 if (preferenceScreen != null) { 479 Bundle container = new Bundle(); 480 preferenceScreen.saveHierarchyState(container); 481 outState.putBundle(PREFERENCES_TAG, container); 482 } 483 } 484 } 485 486 @Override 487 protected void onRestoreInstanceState(Bundle state) { 488 if (mPreferenceManager != null) { 489 Bundle container = state.getBundle(PREFERENCES_TAG); 490 if (container != null) { 491 final PreferenceScreen preferenceScreen = getPreferenceScreen(); 492 if (preferenceScreen != null) { 493 preferenceScreen.restoreHierarchyState(container); 494 mSavedInstanceState = state; 495 return; 496 } 497 } 498 } 499 500 // Only call this if we didn't save the instance state for later. 501 // If we did save it, it will be restored when we bind the adapter. 502 super.onRestoreInstanceState(state); 503 } 504 505 @Override 506 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 507 super.onActivityResult(requestCode, resultCode, data); 508 509 if (mPreferenceManager != null) { 510 mPreferenceManager.dispatchActivityResult(requestCode, resultCode, data); 511 } 512 } 513 514 @Override 515 public void onContentChanged() { 516 super.onContentChanged(); 517 518 if (mPreferenceManager != null) { 519 postBindPreferences(); 520 } 521 } 522 523 @Override 524 protected void onListItemClick(ListView l, View v, int position, long id) { 525 super.onListItemClick(l, v, position, id); 526 527 if (mAdapter != null) { 528 onHeaderClick(mHeaders.get(position), position); 529 } 530 } 531 532 /** 533 * Called when the user selects an item in the header list. The default 534 * implementation will call either {@link #startWithFragment(String)} 535 * or {@link #switchToHeader(String)} as appropriate. 536 * 537 * @param header The header that was selected. 538 * @param position The header's position in the list. 539 */ 540 public void onHeaderClick(Header header, int position) { 541 if (mSinglePane) { 542 startWithFragment(header.fragment); 543 } else { 544 switchToHeader(header.fragment); 545 } 546 } 547 548 /** 549 * Start a new instance of this activity, showing only the given 550 * preference fragment. When launched in this mode, the header list 551 * will be hidden and the given preference fragment will be instantiated 552 * and fill the entire activity. 553 * 554 * @param fragmentName The name of the fragment to display. 555 */ 556 public void startWithFragment(String fragmentName) { 557 Intent intent = new Intent(Intent.ACTION_MAIN); 558 intent.setClass(this, getClass()); 559 intent.putExtra(EXTRA_PREFS_SHOW_FRAGMENT, fragmentName); 560 intent.putExtra(EXTRA_PREFS_NO_HEADERS, true); 561 startActivity(intent); 562 } 563 564 /** 565 * When in two-pane mode, switch the fragment pane to show the given 566 * preference fragment. 567 * 568 * @param fragmentName The name of the fragment to display. 569 */ 570 public void switchToHeader(String fragmentName) { 571 popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE); 572 573 Fragment f; 574 try { 575 f = Fragment.instantiate(this, fragmentName); 576 } catch (Exception e) { 577 Log.w(TAG, "Failure instantiating fragment " + fragmentName, e); 578 return; 579 } 580 openFragmentTransaction().replace(com.android.internal.R.id.prefs, f).commit(); 581 } 582 583 @Override 584 public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) { 585 Fragment f; 586 try { 587 f = Fragment.instantiate(this, pref.getFragment()); 588 } catch (Exception e) { 589 Log.w(TAG, "Failure instantiating fragment " + pref.getFragment(), e); 590 return false; 591 } 592 openFragmentTransaction().replace(com.android.internal.R.id.prefs, f) 593 .addToBackStack(BACK_STACK_PREFS).commit(); 594 return true; 595 } 596 597 /** 598 * Posts a message to bind the preferences to the list view. 599 * <p> 600 * Binding late is preferred as any custom preference types created in 601 * {@link #onCreate(Bundle)} are able to have their views recycled. 602 */ 603 private void postBindPreferences() { 604 if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) return; 605 mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget(); 606 } 607 608 private void bindPreferences() { 609 final PreferenceScreen preferenceScreen = getPreferenceScreen(); 610 if (preferenceScreen != null) { 611 preferenceScreen.bind(getListView()); 612 if (mSavedInstanceState != null) { 613 super.onRestoreInstanceState(mSavedInstanceState); 614 mSavedInstanceState = null; 615 } 616 } 617 } 618 619 /** 620 * Returns the {@link PreferenceManager} used by this activity. 621 * @return The {@link PreferenceManager}. 622 * 623 * @deprecated This function is not relevant for a modern fragment-based 624 * PreferenceActivity. 625 */ 626 @Deprecated 627 public PreferenceManager getPreferenceManager() { 628 return mPreferenceManager; 629 } 630 631 private void requirePreferenceManager() { 632 if (mPreferenceManager == null) { 633 if (mAdapter == null) { 634 throw new RuntimeException("This should be called after super.onCreate."); 635 } 636 throw new RuntimeException( 637 "Modern two-pane PreferenceActivity requires use of a PreferenceFragment"); 638 } 639 } 640 641 /** 642 * Sets the root of the preference hierarchy that this activity is showing. 643 * 644 * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy. 645 * 646 * @deprecated This function is not relevant for a modern fragment-based 647 * PreferenceActivity. 648 */ 649 @Deprecated 650 public void setPreferenceScreen(PreferenceScreen preferenceScreen) { 651 requirePreferenceManager(); 652 653 if (mPreferenceManager.setPreferences(preferenceScreen) && preferenceScreen != null) { 654 postBindPreferences(); 655 CharSequence title = getPreferenceScreen().getTitle(); 656 // Set the title of the activity 657 if (title != null) { 658 setTitle(title); 659 } 660 } 661 } 662 663 /** 664 * Gets the root of the preference hierarchy that this activity is showing. 665 * 666 * @return The {@link PreferenceScreen} that is the root of the preference 667 * hierarchy. 668 * 669 * @deprecated This function is not relevant for a modern fragment-based 670 * PreferenceActivity. 671 */ 672 @Deprecated 673 public PreferenceScreen getPreferenceScreen() { 674 if (mPreferenceManager != null) { 675 return mPreferenceManager.getPreferenceScreen(); 676 } 677 return null; 678 } 679 680 /** 681 * Adds preferences from activities that match the given {@link Intent}. 682 * 683 * @param intent The {@link Intent} to query activities. 684 * 685 * @deprecated This function is not relevant for a modern fragment-based 686 * PreferenceActivity. 687 */ 688 @Deprecated 689 public void addPreferencesFromIntent(Intent intent) { 690 requirePreferenceManager(); 691 692 setPreferenceScreen(mPreferenceManager.inflateFromIntent(intent, getPreferenceScreen())); 693 } 694 695 /** 696 * Inflates the given XML resource and adds the preference hierarchy to the current 697 * preference hierarchy. 698 * 699 * @param preferencesResId The XML resource ID to inflate. 700 * 701 * @deprecated This function is not relevant for a modern fragment-based 702 * PreferenceActivity. 703 */ 704 @Deprecated 705 public void addPreferencesFromResource(int preferencesResId) { 706 requirePreferenceManager(); 707 708 setPreferenceScreen(mPreferenceManager.inflateFromResource(this, preferencesResId, 709 getPreferenceScreen())); 710 } 711 712 /** 713 * {@inheritDoc} 714 * 715 * @deprecated This function is not relevant for a modern fragment-based 716 * PreferenceActivity. 717 */ 718 @Deprecated 719 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { 720 return false; 721 } 722 723 /** 724 * Finds a {@link Preference} based on its key. 725 * 726 * @param key The key of the preference to retrieve. 727 * @return The {@link Preference} with the key, or null. 728 * @see PreferenceGroup#findPreference(CharSequence) 729 * 730 * @deprecated This function is not relevant for a modern fragment-based 731 * PreferenceActivity. 732 */ 733 @Deprecated 734 public Preference findPreference(CharSequence key) { 735 736 if (mPreferenceManager == null) { 737 return null; 738 } 739 740 return mPreferenceManager.findPreference(key); 741 } 742 743 @Override 744 protected void onNewIntent(Intent intent) { 745 if (mPreferenceManager != null) { 746 mPreferenceManager.dispatchNewIntent(intent); 747 } 748 } 749 750 // give subclasses access to the Next button 751 /** @hide */ 752 protected boolean hasNextButton() { 753 return mNextButton != null; 754 } 755 /** @hide */ 756 protected Button getNextButton() { 757 return mNextButton; 758 } 759} 760