1/* 2 * Copyright (C) 2015 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.support.v14.preference; 18 19import android.app.AlertDialog; 20import android.app.Dialog; 21import android.app.DialogFragment; 22import android.app.Fragment; 23import android.content.Context; 24import android.content.DialogInterface; 25import android.os.Bundle; 26import android.support.annotation.NonNull; 27import android.support.v7.preference.DialogPreference; 28import android.text.TextUtils; 29import android.view.LayoutInflater; 30import android.view.View; 31import android.view.Window; 32import android.view.WindowManager; 33import android.widget.TextView; 34 35public abstract class PreferenceDialogFragment extends DialogFragment implements 36 DialogInterface.OnClickListener { 37 38 protected static final String ARG_KEY = "key"; 39 40 private DialogPreference mPreference; 41 42 /** Which button was clicked. */ 43 private int mWhichButtonClicked; 44 45 @Override 46 public void onCreate(Bundle savedInstanceState) { 47 super.onCreate(savedInstanceState); 48 49 final Fragment rawFragment = getTargetFragment(); 50 if (!(rawFragment instanceof DialogPreference.TargetFragment)) { 51 throw new IllegalStateException("Target fragment must implement TargetFragment" + 52 " interface"); 53 } 54 55 final DialogPreference.TargetFragment fragment = 56 (DialogPreference.TargetFragment) rawFragment; 57 58 final String key = getArguments().getString(ARG_KEY); 59 mPreference = (DialogPreference) fragment.findPreference(key); 60 } 61 62 @Override 63 public @NonNull 64 Dialog onCreateDialog(Bundle savedInstanceState) { 65 final Context context = getActivity(); 66 mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE; 67 68 final AlertDialog.Builder builder = new AlertDialog.Builder(context) 69 .setTitle(mPreference.getDialogTitle()) 70 .setIcon(mPreference.getDialogIcon()) 71 .setPositiveButton(mPreference.getPositiveButtonText(), this) 72 .setNegativeButton(mPreference.getNegativeButtonText(), this); 73 74 View contentView = onCreateDialogView(context); 75 if (contentView != null) { 76 onBindDialogView(contentView); 77 builder.setView(contentView); 78 } else { 79 builder.setMessage(mPreference.getDialogMessage()); 80 } 81 82 onPrepareDialogBuilder(builder); 83 84 // Create the dialog 85 final Dialog dialog = builder.create(); 86 if (needInputMethod()) { 87 requestInputMethod(dialog); 88 } 89 90 91 return builder.create(); 92 } 93 94 /** 95 * Get the preference that requested this dialog. Available after {@link #onCreate(Bundle)} has 96 * been called. 97 * 98 * @return The {@link DialogPreference} associated with this 99 * dialog. 100 */ 101 public DialogPreference getPreference() { 102 return mPreference; 103 } 104 105 /** 106 * Prepares the dialog builder to be shown when the preference is clicked. 107 * Use this to set custom properties on the dialog. 108 * <p> 109 * Do not {@link AlertDialog.Builder#create()} or 110 * {@link AlertDialog.Builder#show()}. 111 */ 112 protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {} 113 114 /** 115 * Returns whether the preference needs to display a soft input method when the dialog 116 * is displayed. Default is false. Subclasses should override this method if they need 117 * the soft input method brought up automatically. 118 * @hide 119 */ 120 protected boolean needInputMethod() { 121 return false; 122 } 123 124 /** 125 * Sets the required flags on the dialog window to enable input method window to show up. 126 */ 127 private void requestInputMethod(Dialog dialog) { 128 Window window = dialog.getWindow(); 129 window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); 130 } 131 132 /** 133 * Creates the content view for the dialog (if a custom content view is 134 * required). By default, it inflates the dialog layout resource if it is 135 * set. 136 * 137 * @return The content View for the dialog. 138 * @see DialogPreference#setLayoutResource(int) 139 */ 140 protected View onCreateDialogView(Context context) { 141 final int resId = mPreference.getDialogLayoutResource(); 142 if (resId == 0) { 143 return null; 144 } 145 146 LayoutInflater inflater = LayoutInflater.from(context); 147 return inflater.inflate(resId, null); 148 } 149 150 /** 151 * Binds views in the content View of the dialog to data. 152 * <p> 153 * Make sure to call through to the superclass implementation. 154 * 155 * @param view The content View of the dialog, if it is custom. 156 */ 157 protected void onBindDialogView(View view) { 158 View dialogMessageView = view.findViewById(android.R.id.message); 159 160 if (dialogMessageView != null) { 161 final CharSequence message = mPreference.getDialogMessage(); 162 int newVisibility = View.GONE; 163 164 if (!TextUtils.isEmpty(message)) { 165 if (dialogMessageView instanceof TextView) { 166 ((TextView) dialogMessageView).setText(message); 167 } 168 169 newVisibility = View.VISIBLE; 170 } 171 172 if (dialogMessageView.getVisibility() != newVisibility) { 173 dialogMessageView.setVisibility(newVisibility); 174 } 175 } 176 } 177 178 @Override 179 public void onClick(DialogInterface dialog, int which) { 180 mWhichButtonClicked = which; 181 } 182 183 @Override 184 public void onDismiss(DialogInterface dialog) { 185 super.onDismiss(dialog); 186 onDialogClosed(mWhichButtonClicked == DialogInterface.BUTTON_POSITIVE); 187 } 188 189 public abstract void onDialogClosed(boolean positiveResult); 190} 191