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