1 /* 2 * Copyright (C) 2010 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 17 package com.android.settings; 18 19 import android.app.Activity; 20 import android.app.Dialog; 21 import android.content.ContentResolver; 22 import android.content.Context; 23 import android.content.DialogInterface; 24 import android.content.Intent; 25 import android.content.pm.PackageManager; 26 import android.os.Bundle; 27 import android.text.TextUtils; 28 import android.util.ArrayMap; 29 import android.util.Log; 30 import android.view.LayoutInflater; 31 import android.view.View; 32 import android.view.ViewGroup; 33 import android.widget.Button; 34 35 import androidx.annotation.VisibleForTesting; 36 import androidx.annotation.XmlRes; 37 import androidx.fragment.app.DialogFragment; 38 import androidx.fragment.app.Fragment; 39 import androidx.preference.Preference; 40 import androidx.preference.PreferenceGroup; 41 import androidx.preference.PreferenceScreen; 42 import androidx.recyclerview.widget.LinearLayoutManager; 43 import androidx.recyclerview.widget.RecyclerView; 44 45 import com.android.settings.core.InstrumentedPreferenceFragment; 46 import com.android.settings.core.instrumentation.InstrumentedDialogFragment; 47 import com.android.settings.search.actionbar.SearchMenuController; 48 import com.android.settings.support.actionbar.HelpMenuController; 49 import com.android.settings.support.actionbar.HelpResourceProvider; 50 import com.android.settings.widget.HighlightablePreferenceGroupAdapter; 51 import com.android.settings.widget.LoadingViewController; 52 import com.android.settingslib.CustomDialogPreferenceCompat; 53 import com.android.settingslib.CustomEditTextPreferenceCompat; 54 import com.android.settingslib.core.instrumentation.Instrumentable; 55 import com.android.settingslib.search.Indexable; 56 import com.android.settingslib.widget.LayoutPreference; 57 58 import java.util.UUID; 59 60 /** 61 * Base class for Settings fragments, with some helper functions and dialog management. 62 */ 63 public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceFragment 64 implements DialogCreatable, HelpResourceProvider, Indexable { 65 66 private static final String TAG = "SettingsPreference"; 67 68 private static final String SAVE_HIGHLIGHTED_KEY = "android:preference_highlighted"; 69 70 private static final int ORDER_FIRST = -1; 71 72 private SettingsDialogFragment mDialogFragment; 73 // Cache the content resolver for async callbacks 74 private ContentResolver mContentResolver; 75 76 private RecyclerView.Adapter mCurrentRootAdapter; 77 private boolean mIsDataSetObserverRegistered = false; 78 private RecyclerView.AdapterDataObserver mDataSetObserver = 79 new RecyclerView.AdapterDataObserver() { 80 @Override 81 public void onChanged() { 82 onDataSetChanged(); 83 } 84 85 @Override 86 public void onItemRangeChanged(int positionStart, int itemCount) { 87 onDataSetChanged(); 88 } 89 90 @Override 91 public void onItemRangeChanged(int positionStart, int itemCount, Object payload) { 92 onDataSetChanged(); 93 } 94 95 @Override 96 public void onItemRangeInserted(int positionStart, int itemCount) { 97 onDataSetChanged(); 98 } 99 100 @Override 101 public void onItemRangeRemoved(int positionStart, int itemCount) { 102 onDataSetChanged(); 103 } 104 105 @Override 106 public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { 107 onDataSetChanged(); 108 } 109 }; 110 111 @VisibleForTesting 112 ViewGroup mPinnedHeaderFrameLayout; 113 114 private LayoutPreference mHeader; 115 116 private View mEmptyView; 117 private LinearLayoutManager mLayoutManager; 118 private ArrayMap<String, Preference> mPreferenceCache; 119 private boolean mAnimationAllowed; 120 121 @VisibleForTesting 122 public HighlightablePreferenceGroupAdapter mAdapter; 123 @VisibleForTesting 124 public boolean mPreferenceHighlighted = false; 125 126 @Override onCreate(Bundle icicle)127 public void onCreate(Bundle icicle) { 128 super.onCreate(icicle); 129 SearchMenuController.init(this /* host */); 130 HelpMenuController.init(this /* host */); 131 132 if (icicle != null) { 133 mPreferenceHighlighted = icicle.getBoolean(SAVE_HIGHLIGHTED_KEY); 134 } 135 HighlightablePreferenceGroupAdapter.adjustInitialExpandedChildCount(this /* host */); 136 } 137 138 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)139 public View onCreateView(LayoutInflater inflater, ViewGroup container, 140 Bundle savedInstanceState) { 141 final View root = super.onCreateView(inflater, container, savedInstanceState); 142 mPinnedHeaderFrameLayout = root.findViewById(R.id.pinned_header); 143 return root; 144 } 145 146 @Override addPreferencesFromResource(@mlRes int preferencesResId)147 public void addPreferencesFromResource(@XmlRes int preferencesResId) { 148 super.addPreferencesFromResource(preferencesResId); 149 checkAvailablePrefs(getPreferenceScreen()); 150 } 151 152 @VisibleForTesting checkAvailablePrefs(PreferenceGroup preferenceGroup)153 void checkAvailablePrefs(PreferenceGroup preferenceGroup) { 154 if (preferenceGroup == null) return; 155 for (int i = 0; i < preferenceGroup.getPreferenceCount(); i++) { 156 Preference pref = preferenceGroup.getPreference(i); 157 if (pref instanceof SelfAvailablePreference 158 && !((SelfAvailablePreference) pref).isAvailable(getContext())) { 159 pref.setVisible(false); 160 } else if (pref instanceof PreferenceGroup) { 161 checkAvailablePrefs((PreferenceGroup) pref); 162 } 163 } 164 } 165 setPinnedHeaderView(int layoutResId)166 public View setPinnedHeaderView(int layoutResId) { 167 final LayoutInflater inflater = getActivity().getLayoutInflater(); 168 final View pinnedHeader = 169 inflater.inflate(layoutResId, mPinnedHeaderFrameLayout, false); 170 setPinnedHeaderView(pinnedHeader); 171 return pinnedHeader; 172 } 173 setPinnedHeaderView(View pinnedHeader)174 public void setPinnedHeaderView(View pinnedHeader) { 175 mPinnedHeaderFrameLayout.addView(pinnedHeader); 176 mPinnedHeaderFrameLayout.setVisibility(View.VISIBLE); 177 } 178 showPinnedHeader(boolean show)179 public void showPinnedHeader(boolean show) { 180 mPinnedHeaderFrameLayout.setVisibility(show ? View.VISIBLE : View.INVISIBLE); 181 } 182 183 @Override onSaveInstanceState(Bundle outState)184 public void onSaveInstanceState(Bundle outState) { 185 super.onSaveInstanceState(outState); 186 187 if (mAdapter != null) { 188 outState.putBoolean(SAVE_HIGHLIGHTED_KEY, mAdapter.isHighlightRequested()); 189 } 190 } 191 192 @Override onActivityCreated(Bundle savedInstanceState)193 public void onActivityCreated(Bundle savedInstanceState) { 194 super.onActivityCreated(savedInstanceState); 195 setHasOptionsMenu(true); 196 } 197 198 @Override onResume()199 public void onResume() { 200 super.onResume(); 201 highlightPreferenceIfNeeded(); 202 } 203 204 @Override onBindPreferences()205 protected void onBindPreferences() { 206 registerObserverIfNeeded(); 207 } 208 209 @Override onUnbindPreferences()210 protected void onUnbindPreferences() { 211 unregisterObserverIfNeeded(); 212 } 213 setLoading(boolean loading, boolean animate)214 public void setLoading(boolean loading, boolean animate) { 215 View loadingContainer = getView().findViewById(R.id.loading_container); 216 LoadingViewController.handleLoadingContainer(loadingContainer, getListView(), 217 !loading /* done */, 218 animate); 219 } 220 registerObserverIfNeeded()221 public void registerObserverIfNeeded() { 222 if (!mIsDataSetObserverRegistered) { 223 if (mCurrentRootAdapter != null) { 224 mCurrentRootAdapter.unregisterAdapterDataObserver(mDataSetObserver); 225 } 226 mCurrentRootAdapter = getListView().getAdapter(); 227 mCurrentRootAdapter.registerAdapterDataObserver(mDataSetObserver); 228 mIsDataSetObserverRegistered = true; 229 onDataSetChanged(); 230 } 231 } 232 unregisterObserverIfNeeded()233 public void unregisterObserverIfNeeded() { 234 if (mIsDataSetObserverRegistered) { 235 if (mCurrentRootAdapter != null) { 236 mCurrentRootAdapter.unregisterAdapterDataObserver(mDataSetObserver); 237 mCurrentRootAdapter = null; 238 } 239 mIsDataSetObserverRegistered = false; 240 } 241 } 242 highlightPreferenceIfNeeded()243 public void highlightPreferenceIfNeeded() { 244 if (!isAdded()) { 245 return; 246 } 247 if (mAdapter != null) { 248 mAdapter.requestHighlight(getView(), getListView()); 249 } 250 } 251 252 /** 253 * Returns initial expanded child count. 254 * <p/> 255 * Only override this method if the initial expanded child must be determined at run time. 256 */ getInitialExpandedChildCount()257 public int getInitialExpandedChildCount() { 258 return 0; 259 } 260 261 /** 262 * Whether preference is allowing to be displayed to the user. 263 * 264 * @param preference to check if it can be displayed to the user (not hidding in expand area). 265 * @return {@code true} when preference is allowing to be displayed to the user. 266 * {@code false} when preference is hidden in expand area and not been displayed to the user. 267 */ isPreferenceExpanded(Preference preference)268 protected boolean isPreferenceExpanded(Preference preference) { 269 return ((mAdapter == null) 270 || (mAdapter.getPreferenceAdapterPosition(preference) != RecyclerView.NO_POSITION)); 271 } 272 onDataSetChanged()273 protected void onDataSetChanged() { 274 highlightPreferenceIfNeeded(); 275 updateEmptyView(); 276 } 277 getHeaderView()278 public LayoutPreference getHeaderView() { 279 return mHeader; 280 } 281 setHeaderView(int resource)282 protected void setHeaderView(int resource) { 283 mHeader = new LayoutPreference(getPrefContext(), resource); 284 mHeader.setSelectable(false); 285 addPreferenceToTop(mHeader); 286 } 287 setHeaderView(View view)288 protected void setHeaderView(View view) { 289 mHeader = new LayoutPreference(getPrefContext(), view); 290 mHeader.setSelectable(false); 291 addPreferenceToTop(mHeader); 292 } 293 addPreferenceToTop(LayoutPreference preference)294 private void addPreferenceToTop(LayoutPreference preference) { 295 preference.setOrder(ORDER_FIRST); 296 if (getPreferenceScreen() != null) { 297 getPreferenceScreen().addPreference(preference); 298 } 299 } 300 301 @Override setPreferenceScreen(PreferenceScreen preferenceScreen)302 public void setPreferenceScreen(PreferenceScreen preferenceScreen) { 303 if (preferenceScreen != null && !preferenceScreen.isAttached()) { 304 // Without ids generated, the RecyclerView won't animate changes to the preferences. 305 preferenceScreen.setShouldUseGeneratedIds(mAnimationAllowed); 306 } 307 super.setPreferenceScreen(preferenceScreen); 308 if (preferenceScreen != null) { 309 if (mHeader != null) { 310 preferenceScreen.addPreference(mHeader); 311 } 312 } 313 } 314 315 @VisibleForTesting updateEmptyView()316 void updateEmptyView() { 317 if (mEmptyView == null) return; 318 if (getPreferenceScreen() != null) { 319 final View listContainer = getActivity().findViewById(android.R.id.list_container); 320 boolean show = (getPreferenceScreen().getPreferenceCount() 321 - (mHeader != null ? 1 : 0)) <= 0 322 || (listContainer != null && listContainer.getVisibility() != View.VISIBLE); 323 mEmptyView.setVisibility(show ? View.VISIBLE : View.GONE); 324 } else { 325 mEmptyView.setVisibility(View.VISIBLE); 326 } 327 } 328 setEmptyView(View v)329 public void setEmptyView(View v) { 330 if (mEmptyView != null) { 331 mEmptyView.setVisibility(View.GONE); 332 } 333 mEmptyView = v; 334 updateEmptyView(); 335 } 336 getEmptyView()337 public View getEmptyView() { 338 return mEmptyView; 339 } 340 341 @Override onCreateLayoutManager()342 public RecyclerView.LayoutManager onCreateLayoutManager() { 343 mLayoutManager = new LinearLayoutManager(getContext()); 344 return mLayoutManager; 345 } 346 347 @Override onCreateAdapter(PreferenceScreen preferenceScreen)348 protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) { 349 final Bundle arguments = getArguments(); 350 mAdapter = new HighlightablePreferenceGroupAdapter(preferenceScreen, 351 arguments == null 352 ? null : arguments.getString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY), 353 mPreferenceHighlighted); 354 return mAdapter; 355 } 356 setAnimationAllowed(boolean animationAllowed)357 protected void setAnimationAllowed(boolean animationAllowed) { 358 mAnimationAllowed = animationAllowed; 359 } 360 cacheRemoveAllPrefs(PreferenceGroup group)361 protected void cacheRemoveAllPrefs(PreferenceGroup group) { 362 mPreferenceCache = new ArrayMap<>(); 363 final int N = group.getPreferenceCount(); 364 for (int i = 0; i < N; i++) { 365 Preference p = group.getPreference(i); 366 if (TextUtils.isEmpty(p.getKey())) { 367 continue; 368 } 369 mPreferenceCache.put(p.getKey(), p); 370 } 371 } 372 getCachedPreference(String key)373 protected Preference getCachedPreference(String key) { 374 return mPreferenceCache != null ? mPreferenceCache.remove(key) : null; 375 } 376 removeCachedPrefs(PreferenceGroup group)377 protected void removeCachedPrefs(PreferenceGroup group) { 378 for (Preference p : mPreferenceCache.values()) { 379 group.removePreference(p); 380 } 381 mPreferenceCache = null; 382 } 383 getCachedCount()384 protected int getCachedCount() { 385 return mPreferenceCache != null ? mPreferenceCache.size() : 0; 386 } 387 388 @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) removePreference(String key)389 public boolean removePreference(String key) { 390 return removePreference(getPreferenceScreen(), key); 391 } 392 393 @VisibleForTesting removePreference(PreferenceGroup group, String key)394 boolean removePreference(PreferenceGroup group, String key) { 395 final int preferenceCount = group.getPreferenceCount(); 396 for (int i = 0; i < preferenceCount; i++) { 397 final Preference preference = group.getPreference(i); 398 final String curKey = preference.getKey(); 399 400 if (TextUtils.equals(curKey, key)) { 401 return group.removePreference(preference); 402 } 403 404 if (preference instanceof PreferenceGroup) { 405 if (removePreference((PreferenceGroup) preference, key)) { 406 return true; 407 } 408 } 409 } 410 return false; 411 } 412 413 /* 414 * The name is intentionally made different from Activity#finish(), so that 415 * users won't misunderstand its meaning. 416 */ finishFragment()417 public final void finishFragment() { 418 getActivity().onBackPressed(); 419 } 420 421 // Some helpers for functions used by the settings fragments when they were activities 422 423 /** 424 * Returns the ContentResolver from the owning Activity. 425 */ getContentResolver()426 protected ContentResolver getContentResolver() { 427 Context context = getActivity(); 428 if (context != null) { 429 mContentResolver = context.getContentResolver(); 430 } 431 return mContentResolver; 432 } 433 434 /** 435 * Returns the specified system service from the owning Activity. 436 */ getSystemService(final String name)437 protected Object getSystemService(final String name) { 438 return getActivity().getSystemService(name); 439 } 440 441 /** 442 * Returns the PackageManager from the owning Activity. 443 */ getPackageManager()444 protected PackageManager getPackageManager() { 445 return getActivity().getPackageManager(); 446 } 447 448 @Override onDetach()449 public void onDetach() { 450 if (isRemoving()) { 451 if (mDialogFragment != null) { 452 mDialogFragment.dismiss(); 453 mDialogFragment = null; 454 } 455 } 456 super.onDetach(); 457 } 458 459 // Dialog management 460 showDialog(int dialogId)461 protected void showDialog(int dialogId) { 462 if (mDialogFragment != null) { 463 Log.e(TAG, "Old dialog fragment not null!"); 464 } 465 mDialogFragment = SettingsDialogFragment.newInstance(this, dialogId); 466 mDialogFragment.show(getChildFragmentManager(), Integer.toString(dialogId)); 467 } 468 469 @Override onCreateDialog(int dialogId)470 public Dialog onCreateDialog(int dialogId) { 471 return null; 472 } 473 474 @Override getDialogMetricsCategory(int dialogId)475 public int getDialogMetricsCategory(int dialogId) { 476 return 0; 477 } 478 removeDialog(int dialogId)479 protected void removeDialog(int dialogId) { 480 // mDialogFragment may not be visible yet in parent fragment's onResume(). 481 // To be able to dismiss dialog at that time, don't check 482 // mDialogFragment.isVisible(). 483 if (mDialogFragment != null && mDialogFragment.getDialogId() == dialogId) { 484 mDialogFragment.dismissAllowingStateLoss(); 485 } 486 mDialogFragment = null; 487 } 488 489 /** 490 * Sets the OnCancelListener of the dialog shown. This method can only be 491 * called after showDialog(int) and before removeDialog(int). The method 492 * does nothing otherwise. 493 */ setOnCancelListener(DialogInterface.OnCancelListener listener)494 protected void setOnCancelListener(DialogInterface.OnCancelListener listener) { 495 if (mDialogFragment != null) { 496 mDialogFragment.mOnCancelListener = listener; 497 } 498 } 499 500 /** 501 * Sets the OnDismissListener of the dialog shown. This method can only be 502 * called after showDialog(int) and before removeDialog(int). The method 503 * does nothing otherwise. 504 */ setOnDismissListener(DialogInterface.OnDismissListener listener)505 protected void setOnDismissListener(DialogInterface.OnDismissListener listener) { 506 if (mDialogFragment != null) { 507 mDialogFragment.mOnDismissListener = listener; 508 } 509 } 510 onDialogShowing()511 public void onDialogShowing() { 512 // override in subclass to attach a dismiss listener, for instance 513 } 514 515 @Override onDisplayPreferenceDialog(Preference preference)516 public void onDisplayPreferenceDialog(Preference preference) { 517 if (preference.getKey() == null) { 518 // Auto-key preferences that don't have a key, so the dialog can find them. 519 preference.setKey(UUID.randomUUID().toString()); 520 } 521 DialogFragment f = null; 522 if (preference instanceof RestrictedListPreference) { 523 f = RestrictedListPreference.RestrictedListPreferenceDialogFragment 524 .newInstance(preference.getKey()); 525 } else if (preference instanceof CustomListPreference) { 526 f = CustomListPreference.CustomListPreferenceDialogFragment 527 .newInstance(preference.getKey()); 528 } else if (preference instanceof CustomDialogPreferenceCompat) { 529 f = CustomDialogPreferenceCompat.CustomPreferenceDialogFragment 530 .newInstance(preference.getKey()); 531 } else if (preference instanceof CustomEditTextPreferenceCompat) { 532 f = CustomEditTextPreferenceCompat.CustomPreferenceDialogFragment 533 .newInstance(preference.getKey()); 534 } else { 535 super.onDisplayPreferenceDialog(preference); 536 return; 537 } 538 f.setTargetFragment(this, 0); 539 f.show(getFragmentManager(), "dialog_preference"); 540 onDialogShowing(); 541 } 542 543 public static class SettingsDialogFragment extends InstrumentedDialogFragment { 544 private static final String KEY_DIALOG_ID = "key_dialog_id"; 545 private static final String KEY_PARENT_FRAGMENT_ID = "key_parent_fragment_id"; 546 547 private Fragment mParentFragment; 548 549 private DialogInterface.OnCancelListener mOnCancelListener; 550 private DialogInterface.OnDismissListener mOnDismissListener; 551 newInstance(DialogCreatable fragment, int dialogId)552 public static SettingsDialogFragment newInstance(DialogCreatable fragment, int dialogId) { 553 if (!(fragment instanceof Fragment)) { 554 throw new IllegalArgumentException("fragment argument must be an instance of " 555 + Fragment.class.getName()); 556 } 557 558 final SettingsDialogFragment settingsDialogFragment = new SettingsDialogFragment(); 559 settingsDialogFragment.setParentFragment(fragment); 560 settingsDialogFragment.setDialogId(dialogId); 561 562 return settingsDialogFragment; 563 } 564 565 @Override getMetricsCategory()566 public int getMetricsCategory() { 567 if (mParentFragment == null) { 568 return Instrumentable.METRICS_CATEGORY_UNKNOWN; 569 } 570 final int metricsCategory = 571 ((DialogCreatable) mParentFragment).getDialogMetricsCategory(mDialogId); 572 if (metricsCategory <= 0) { 573 throw new IllegalStateException("Dialog must provide a metrics category"); 574 } 575 return metricsCategory; 576 } 577 578 @Override onSaveInstanceState(Bundle outState)579 public void onSaveInstanceState(Bundle outState) { 580 super.onSaveInstanceState(outState); 581 if (mParentFragment != null) { 582 outState.putInt(KEY_DIALOG_ID, mDialogId); 583 outState.putInt(KEY_PARENT_FRAGMENT_ID, mParentFragment.getId()); 584 } 585 } 586 587 @Override onStart()588 public void onStart() { 589 super.onStart(); 590 591 if (mParentFragment != null && mParentFragment instanceof SettingsPreferenceFragment) { 592 ((SettingsPreferenceFragment) mParentFragment).onDialogShowing(); 593 } 594 } 595 596 @Override onCreateDialog(Bundle savedInstanceState)597 public Dialog onCreateDialog(Bundle savedInstanceState) { 598 if (savedInstanceState != null) { 599 mDialogId = savedInstanceState.getInt(KEY_DIALOG_ID, 0); 600 mParentFragment = getParentFragment(); 601 int mParentFragmentId = savedInstanceState.getInt(KEY_PARENT_FRAGMENT_ID, -1); 602 if (mParentFragment == null) { 603 mParentFragment = getFragmentManager().findFragmentById(mParentFragmentId); 604 } 605 if (!(mParentFragment instanceof DialogCreatable)) { 606 throw new IllegalArgumentException( 607 (mParentFragment != null 608 ? mParentFragment.getClass().getName() 609 : mParentFragmentId) 610 + " must implement " 611 + DialogCreatable.class.getName()); 612 } 613 // This dialog fragment could be created from non-SettingsPreferenceFragment 614 if (mParentFragment instanceof SettingsPreferenceFragment) { 615 // restore mDialogFragment in mParentFragment 616 ((SettingsPreferenceFragment) mParentFragment).mDialogFragment = this; 617 } 618 } 619 return ((DialogCreatable) mParentFragment).onCreateDialog(mDialogId); 620 } 621 622 @Override onCancel(DialogInterface dialog)623 public void onCancel(DialogInterface dialog) { 624 super.onCancel(dialog); 625 if (mOnCancelListener != null) { 626 mOnCancelListener.onCancel(dialog); 627 } 628 } 629 630 @Override onDismiss(DialogInterface dialog)631 public void onDismiss(DialogInterface dialog) { 632 super.onDismiss(dialog); 633 if (mOnDismissListener != null) { 634 mOnDismissListener.onDismiss(dialog); 635 } 636 } 637 getDialogId()638 public int getDialogId() { 639 return mDialogId; 640 } 641 642 @Override onDetach()643 public void onDetach() { 644 super.onDetach(); 645 646 // This dialog fragment could be created from non-SettingsPreferenceFragment 647 if (mParentFragment instanceof SettingsPreferenceFragment) { 648 // in case the dialog is not explicitly removed by removeDialog() 649 if (((SettingsPreferenceFragment) mParentFragment).mDialogFragment == this) { 650 ((SettingsPreferenceFragment) mParentFragment).mDialogFragment = null; 651 } 652 } 653 } 654 setParentFragment(DialogCreatable fragment)655 private void setParentFragment(DialogCreatable fragment) { 656 mParentFragment = (Fragment) fragment; 657 } 658 setDialogId(int dialogId)659 private void setDialogId(int dialogId) { 660 mDialogId = dialogId; 661 } 662 } 663 hasNextButton()664 protected boolean hasNextButton() { 665 return ((ButtonBarHandler) getActivity()).hasNextButton(); 666 } 667 getNextButton()668 protected Button getNextButton() { 669 return ((ButtonBarHandler) getActivity()).getNextButton(); 670 } 671 finish()672 public void finish() { 673 Activity activity = getActivity(); 674 if (activity == null) return; 675 if (getFragmentManager().getBackStackEntryCount() > 0) { 676 getFragmentManager().popBackStack(); 677 } else { 678 activity.finish(); 679 } 680 } 681 getIntent()682 protected Intent getIntent() { 683 if (getActivity() == null) { 684 return null; 685 } 686 return getActivity().getIntent(); 687 } 688 setResult(int result, Intent intent)689 protected void setResult(int result, Intent intent) { 690 if (getActivity() == null) { 691 return; 692 } 693 getActivity().setResult(result, intent); 694 } 695 setResult(int result)696 protected void setResult(int result) { 697 if (getActivity() == null) { 698 return; 699 } 700 getActivity().setResult(result); 701 } 702 isFinishingOrDestroyed()703 protected boolean isFinishingOrDestroyed() { 704 final Activity activity = getActivity(); 705 return activity == null || activity.isFinishing() || activity.isDestroyed(); 706 } 707 } 708