public abstract class

PreferenceDialogFragment

extends android.app.DialogFragment

 java.lang.Object

↳android.app.DialogFragment

↳androidx.preference.PreferenceDialogFragment

Subclasses:

EditTextPreferenceDialogFragment, MultiSelectListPreferenceDialogFragment, ListPreferenceDialogFragment

Gradle dependencies

compile group: 'androidx.preference', name: 'preference', version: '1.2.1'

  • groupId: androidx.preference
  • artifactId: preference
  • version: 1.2.1

Artifact androidx.preference:preference:1.2.1 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.preference:preference com.android.support:preference-v7

Androidx class mapping:

androidx.preference.PreferenceDialogFragment android.support.v14.preference.PreferenceDialogFragment

Overview

Abstract base class which presents a dialog associated with a DialogPreference. Since the preference object may not be available during fragment re-creation, the necessary information for displaying the dialog is read once during the initial call to PreferenceDialogFragment.onCreate(Bundle) and saved/restored in the saved instance state. Custom subclasses should also follow this pattern.

Summary

Fields
protected static final java.lang.StringARG_KEY

Constructors
publicPreferenceDialogFragment()

Methods
public DialogPreferencegetPreference()

Get the preference that requested this dialog.

protected booleanneedInputMethod()

Returns whether the preference needs to display a soft input method when the dialog is displayed.

protected voidonBindDialogView(View view)

Binds views in the content view of the dialog to data.

public voidonClick(DialogInterface dialog, int which)

public voidonCreate(Bundle savedInstanceState)

public DialogonCreateDialog(Bundle savedInstanceState)

protected ViewonCreateDialogView(Context context)

Creates the content view for the dialog (if a custom content view is required).

public abstract voidonDialogClosed(boolean positiveResult)

public voidonDismiss(DialogInterface dialog)

protected voidonPrepareDialogBuilder(AlertDialog.Builder builder)

Prepares the dialog builder to be shown when the preference is clicked.

public voidonSaveInstanceState(Bundle outState)

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Fields

protected static final java.lang.String ARG_KEY

Deprecated: Use PreferenceDialogFragmentCompat instead

Constructors

public PreferenceDialogFragment()

Deprecated: Use PreferenceDialogFragmentCompat instead

Methods

public void onCreate(Bundle savedInstanceState)

public void onSaveInstanceState(Bundle outState)

public Dialog onCreateDialog(Bundle savedInstanceState)

public DialogPreference getPreference()

Deprecated: Use PreferenceDialogFragmentCompat instead

Get the preference that requested this dialog. Available after PreferenceDialogFragment.onCreate(Bundle) has been called on the PreferenceFragment which launched this dialog.

Returns:

The DialogPreference associated with this dialog

protected void onPrepareDialogBuilder(AlertDialog.Builder builder)

Deprecated: Use PreferenceDialogFragmentCompat instead

Prepares the dialog builder to be shown when the preference is clicked. Use this to set custom properties on the dialog.

Do not or .

protected boolean needInputMethod()

Returns whether the preference needs to display a soft input method when the dialog is displayed. Default is false. Subclasses should override this method if they need the soft input method brought up automatically.

Note: If your application targets P or above, ensure your subclass manually requests focus (ideally in PreferenceDialogFragment.onBindDialogView(View)) for the input field in order to correctly attach the input method to the field.

protected View onCreateDialogView(Context context)

Deprecated: Use PreferenceDialogFragmentCompat instead

Creates the content view for the dialog (if a custom content view is required). By default, it inflates the dialog layout resource if it is set.

Returns:

The content view for the dialog

See also: Preference.setLayoutResource(int)

protected void onBindDialogView(View view)

Deprecated: Use PreferenceDialogFragmentCompat instead

Binds views in the content view of the dialog to data.

Make sure to call through to the superclass implementation.

Parameters:

view: The content view of the dialog, if it is custom

public void onClick(DialogInterface dialog, int which)

Deprecated: Use PreferenceDialogFragmentCompat instead

public void onDismiss(DialogInterface dialog)

public abstract void onDialogClosed(boolean positiveResult)

Deprecated: Use PreferenceDialogFragmentCompat instead

Source

/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.preference;

import static androidx.annotation.RestrictTo.Scope.LIBRARY;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.TextView;

import androidx.annotation.DoNotInline;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;

/**
 * Abstract base class which presents a dialog associated with a {@link DialogPreference}. Since
 * the preference object may not be available during fragment re-creation, the necessary
 * information for displaying the dialog is read once during the initial call to
 * {@link #onCreate(Bundle)} and saved/restored in the saved instance state. Custom subclasses
 * should also follow this pattern.
 *
 * @deprecated Use {@link PreferenceDialogFragmentCompat} instead
 */
@Deprecated
public abstract class PreferenceDialogFragment extends android.app.DialogFragment implements
        DialogInterface.OnClickListener {

    /**
     * @deprecated Use {@link PreferenceDialogFragmentCompat} instead
     */
    @Deprecated
    protected static final String ARG_KEY = "key";

    private static final String SAVE_STATE_TITLE = "PreferenceDialogFragment.title";
    private static final String SAVE_STATE_POSITIVE_TEXT = "PreferenceDialogFragment.positiveText";
    private static final String SAVE_STATE_NEGATIVE_TEXT = "PreferenceDialogFragment.negativeText";
    private static final String SAVE_STATE_MESSAGE = "PreferenceDialogFragment.message";
    private static final String SAVE_STATE_LAYOUT = "PreferenceDialogFragment.layout";
    private static final String SAVE_STATE_ICON = "PreferenceDialogFragment.icon";

    private DialogPreference mPreference;

    private CharSequence mDialogTitle;
    private CharSequence mPositiveButtonText;
    private CharSequence mNegativeButtonText;
    private CharSequence mDialogMessage;
    private @LayoutRes int mDialogLayoutRes;

    private BitmapDrawable mDialogIcon;

    /** Which button was clicked. */
    private int mWhichButtonClicked;

    /**
     * @deprecated Use {@link PreferenceDialogFragmentCompat} instead
     */
    @SuppressWarnings("deprecation")
    @Deprecated
    public PreferenceDialogFragment() {}

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        final android.app.Fragment rawFragment = getTargetFragment();
        if (!(rawFragment instanceof DialogPreference.TargetFragment)) {
            throw new IllegalStateException("Target fragment must implement TargetFragment"
                    + " interface");
        }

        final DialogPreference.TargetFragment fragment =
                (DialogPreference.TargetFragment) rawFragment;

        final String key = getArguments().getString(ARG_KEY);
        if (savedInstanceState == null) {
            mPreference = (DialogPreference) fragment.findPreference(key);
            mDialogTitle = mPreference.getDialogTitle();
            mPositiveButtonText = mPreference.getPositiveButtonText();
            mNegativeButtonText = mPreference.getNegativeButtonText();
            mDialogMessage = mPreference.getDialogMessage();
            mDialogLayoutRes = mPreference.getDialogLayoutResource();

            final Drawable icon = mPreference.getDialogIcon();
            if (icon == null || icon instanceof BitmapDrawable) {
                mDialogIcon = (BitmapDrawable) icon;
            } else {
                final Bitmap bitmap = Bitmap.createBitmap(icon.getIntrinsicWidth(),
                        icon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
                final Canvas canvas = new Canvas(bitmap);
                icon.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
                icon.draw(canvas);
                mDialogIcon = new BitmapDrawable(getResources(), bitmap);
            }
        } else {
            mDialogTitle = savedInstanceState.getCharSequence(SAVE_STATE_TITLE);
            mPositiveButtonText = savedInstanceState.getCharSequence(SAVE_STATE_POSITIVE_TEXT);
            mNegativeButtonText = savedInstanceState.getCharSequence(SAVE_STATE_NEGATIVE_TEXT);
            mDialogMessage = savedInstanceState.getCharSequence(SAVE_STATE_MESSAGE);
            mDialogLayoutRes = savedInstanceState.getInt(SAVE_STATE_LAYOUT, 0);
            final Bitmap bitmap = savedInstanceState.getParcelable(SAVE_STATE_ICON);
            if (bitmap != null) {
                mDialogIcon = new BitmapDrawable(getResources(), bitmap);
            }
        }
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);

        outState.putCharSequence(SAVE_STATE_TITLE, mDialogTitle);
        outState.putCharSequence(SAVE_STATE_POSITIVE_TEXT, mPositiveButtonText);
        outState.putCharSequence(SAVE_STATE_NEGATIVE_TEXT, mNegativeButtonText);
        outState.putCharSequence(SAVE_STATE_MESSAGE, mDialogMessage);
        outState.putInt(SAVE_STATE_LAYOUT, mDialogLayoutRes);
        if (mDialogIcon != null) {
            outState.putParcelable(SAVE_STATE_ICON, mDialogIcon.getBitmap());
        }
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        final Context context = getActivity();
        mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE;

        final AlertDialog.Builder builder = new AlertDialog.Builder(context)
                .setTitle(mDialogTitle)
                .setIcon(mDialogIcon)
                .setPositiveButton(mPositiveButtonText, this)
                .setNegativeButton(mNegativeButtonText, this);

        View contentView = onCreateDialogView(context);
        if (contentView != null) {
            onBindDialogView(contentView);
            builder.setView(contentView);
        } else {
            builder.setMessage(mDialogMessage);
        }

        onPrepareDialogBuilder(builder);

        // Create the dialog
        final Dialog dialog = builder.create();
        if (needInputMethod()) {
            requestInputMethod(dialog);
        }

        return dialog;
    }

    /**
     * Get the preference that requested this dialog. Available after {@link #onCreate(Bundle)} has
     * been called on the {@link PreferenceFragment} which launched this dialog.
     *
     * @return The {@link DialogPreference} associated with this dialog
     *
     * @deprecated Use {@link PreferenceDialogFragmentCompat} instead
     */
    @Deprecated
    public DialogPreference getPreference() {
        if (mPreference == null) {
            final String key = getArguments().getString(ARG_KEY);
            final DialogPreference.TargetFragment fragment =
                    (DialogPreference.TargetFragment) getTargetFragment();
            mPreference = (DialogPreference) fragment.findPreference(key);
        }
        return mPreference;
    }

    /**
     * Prepares the dialog builder to be shown when the preference is clicked.
     * Use this to set custom properties on the dialog.
     *
     * <p>Do not {@link AlertDialog.Builder#create()} or {@link AlertDialog.Builder#show()}.
     *
     * @deprecated Use {@link PreferenceDialogFragmentCompat} instead
     */
    @Deprecated
    protected void onPrepareDialogBuilder(@NonNull AlertDialog.Builder builder) {}

    /**
     * Returns whether the preference needs to display a soft input method when the dialog is
     * displayed. Default is false. Subclasses should override this method if they need the soft
     * input method brought up automatically.
     *
     * <p>Note: If your application targets P or above, ensure your subclass manually requests
     * focus (ideally in {@link #onBindDialogView(View)}) for the input field in order to
     * correctly attach the input method to the field.
     *
     * @hide
     */
    @RestrictTo(LIBRARY)
    protected boolean needInputMethod() {
        return false;
    }

    /**
     * Sets the required flags on the dialog window to enable input method window to show up.
     * <p>
     * Note that starting from Android R, the new WindowInsets API supports showing soft-input
     * on-demand, so there is no longer a need to rely on the
     * {@link WindowManager.LayoutParams#SOFT_INPUT_STATE_ALWAYS_VISIBLE} flag to show the
     * soft-input when there is no focused editor.</p>
     */
    private void requestInputMethod(@NonNull Dialog dialog) {
        Window window = dialog.getWindow();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            Api30Impl.showIme(window);
        } else {
            window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
        }
    }

    /**
     * Creates the content view for the dialog (if a custom content view is required).
     * By default, it inflates the dialog layout resource if it is set.
     *
     * @return The content view for the dialog
     * @see DialogPreference#setLayoutResource(int)
     *
     * @deprecated Use {@link PreferenceDialogFragmentCompat} instead
     */
    @Deprecated
    @Nullable
    protected View onCreateDialogView(@NonNull Context context) {
        final int resId = mDialogLayoutRes;
        if (resId == 0) {
            return null;
        }

        LayoutInflater inflater = LayoutInflater.from(context);
        return inflater.inflate(resId, null);
    }

    /**
     * Binds views in the content view of the dialog to data.
     *
     * <p>Make sure to call through to the superclass implementation.
     *
     * @param view The content view of the dialog, if it is custom
     *
     * @deprecated Use {@link PreferenceDialogFragmentCompat} instead
     */
    @Deprecated
    protected void onBindDialogView(@NonNull View view) {
        View dialogMessageView = view.findViewById(android.R.id.message);

        if (dialogMessageView != null) {
            final CharSequence message = mDialogMessage;
            int newVisibility = View.GONE;

            if (!TextUtils.isEmpty(message)) {
                if (dialogMessageView instanceof TextView) {
                    ((TextView) dialogMessageView).setText(message);
                }

                newVisibility = View.VISIBLE;
            }

            if (dialogMessageView.getVisibility() != newVisibility) {
                dialogMessageView.setVisibility(newVisibility);
            }
        }
    }

    /**
     * @deprecated Use {@link PreferenceDialogFragmentCompat} instead
     */
    @Deprecated
    @Override
    public void onClick(@NonNull DialogInterface dialog, int which) {
        mWhichButtonClicked = which;
    }

    @Override
    public void onDismiss(@NonNull DialogInterface dialog) {
        super.onDismiss(dialog);
        onDialogClosed(mWhichButtonClicked == DialogInterface.BUTTON_POSITIVE);
    }

    /**
     * @deprecated Use {@link PreferenceDialogFragmentCompat} instead
     */
    @Deprecated
    public abstract void onDialogClosed(boolean positiveResult);

    /**
     * Nested class to avoid verification errors for methods introduced in R.
     */
    @RequiresApi(Build.VERSION_CODES.R)
    private static class Api30Impl {
        // Prevent instantiation.
        private Api30Impl() {}

        /**
         * Shows the IME on demand for the given {@link Window}.
         */
        @DoNotInline
        static void showIme(@NonNull Window dialogWindow) {
            dialogWindow.getDecorView().getWindowInsetsController().show(WindowInsets.Type.ime());
        }
    }
}