Explorar el Código

Added MaterialDialogPreference. Resolves #549. Also fixed callback leaks.

Aidan Follestad hace 10 años
padre
commit
83210add5b

+ 168 - 0
library/src/main/java/com/afollestad/materialdialogs/prefs/MaterialDialogPreference.java

@@ -0,0 +1,168 @@
+package com.afollestad.materialdialogs.prefs;
+
+import android.annotation.TargetApi;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.preference.DialogPreference;
+import android.preference.ListPreference;
+import android.preference.PreferenceManager;
+import android.support.annotation.NonNull;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.afollestad.materialdialogs.MaterialDialog;
+
+import java.lang.reflect.Method;
+
+/**
+ * @author Aidan Follestad (afollestad)
+ */
+public class MaterialDialogPreference extends DialogPreference {
+
+    private Context context;
+    private MaterialDialog mDialog;
+
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+    public MaterialDialogPreference(Context context) {
+        super(context);
+        init(context);
+    }
+
+    public MaterialDialogPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(context);
+    }
+
+    private void init(Context context) {
+        this.context = context;
+    }
+
+    @Override
+    public Dialog getDialog() {
+        return mDialog;
+    }
+
+    @Override
+    protected void showDialog(Bundle state) {
+        MaterialDialog.Builder builder = new MaterialDialog.Builder(context)
+                .title(getDialogTitle())
+                .content(getDialogMessage())
+                .icon(getDialogIcon())
+                .positiveText(getPositiveButtonText())
+                .negativeText(getNegativeButtonText())
+                .autoDismiss(true); // immediately close the dialog after selection
+
+        final View contentView = onCreateDialogView();
+        if (contentView != null) {
+            onBindDialogView(contentView);
+            builder.customView(contentView, false);
+        } else {
+            builder.content(getDialogMessage());
+        }
+
+        try {
+            PreferenceManager pm = getPreferenceManager();
+            Method method = pm.getClass().getDeclaredMethod(
+                    "registerOnActivityDestroyListener",
+                    PreferenceManager.OnActivityDestroyListener.class);
+            method.setAccessible(true);
+            method.invoke(pm, this);
+        } catch (Exception ignored) {
+        }
+
+        mDialog = builder.build();
+        if (state != null)
+            mDialog.onRestoreInstanceState(state);
+        mDialog.show();
+    }
+
+    @Override
+    public void onDismiss(DialogInterface dialog) {
+        super.onDismiss(dialog);
+        try {
+            PreferenceManager pm = getPreferenceManager();
+            Method method = pm.getClass().getDeclaredMethod(
+                    "unregisterOnActivityDestroyListener",
+                    PreferenceManager.OnActivityDestroyListener.class);
+            method.setAccessible(true);
+            method.invoke(pm, this);
+        } catch (Exception ignored) {
+        }
+    }
+
+    @Override
+    public void onActivityDestroy() {
+        super.onActivityDestroy();
+        if (mDialog != null && mDialog.isShowing())
+            mDialog.dismiss();
+    }
+
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        final Parcelable superState = super.onSaveInstanceState();
+        Dialog dialog = getDialog();
+        if (dialog == null || !dialog.isShowing()) {
+            return superState;
+        }
+
+        final SavedState myState = new SavedState(superState);
+        myState.isDialogShowing = true;
+        myState.dialogBundle = dialog.onSaveInstanceState();
+        return myState;
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable state) {
+        if (state == null || !state.getClass().equals(SavedState.class)) {
+            // Didn't save state for us in onSaveInstanceState
+            super.onRestoreInstanceState(state);
+            return;
+        }
+
+        SavedState myState = (SavedState) state;
+        super.onRestoreInstanceState(myState.getSuperState());
+        if (myState.isDialogShowing) {
+            showDialog(myState.dialogBundle);
+        }
+    }
+
+    // From DialogPreference
+    private static class SavedState extends BaseSavedState {
+        boolean isDialogShowing;
+        Bundle dialogBundle;
+
+        public SavedState(Parcel source) {
+            super(source);
+            isDialogShowing = source.readInt() == 1;
+            dialogBundle = source.readBundle();
+        }
+
+        @Override
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
+            super.writeToParcel(dest, flags);
+            dest.writeInt(isDialogShowing ? 1 : 0);
+            dest.writeBundle(dialogBundle);
+        }
+
+        public SavedState(Parcelable superState) {
+            super(superState);
+        }
+
+        public static final Creator<SavedState> CREATOR =
+                new Creator<SavedState>() {
+                    public SavedState createFromParcel(Parcel in) {
+                        return new SavedState(in);
+                    }
+
+                    public SavedState[] newArray(int size) {
+                        return new SavedState[size];
+                    }
+                };
+    }
+}

+ 21 - 12
library/src/main/java/com/afollestad/materialdialogs/prefs/MaterialEditTextPreference.java

@@ -2,6 +2,7 @@ package com.afollestad.materialdialogs.prefs;
 
 import android.app.Dialog;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
@@ -67,17 +68,13 @@ public class MaterialEditTextPreference extends EditTextPreference {
     protected void onBindDialogView(@NonNull View view) {
         EditText editText = mEditText;
         editText.setText(getText());
-
         // Initialize cursor to end of text
-        if (editText.getText().length() > 0) {
+        if (editText.getText().length() > 0)
             editText.setSelection(editText.length());
-        }
-
         ViewParent oldParent = editText.getParent();
         if (oldParent != view) {
-            if (oldParent != null) {
+            if (oldParent != null)
                 ((ViewGroup) oldParent).removeView(editText);
-            }
             onAddEditTextToDialogView(view, editText);
         }
     }
@@ -86,9 +83,8 @@ public class MaterialEditTextPreference extends EditTextPreference {
     protected void onDialogClosed(boolean positiveResult) {
         if (positiveResult) {
             String value = mEditText.getText().toString();
-            if (callChangeListener(value)) {
+            if (callChangeListener(value))
                 setText(value);
-            }
         }
     }
 
@@ -126,15 +122,14 @@ public class MaterialEditTextPreference extends EditTextPreference {
         }
         mBuilder.customView(layout, false);
 
-        PreferenceManager pm = getPreferenceManager();
         try {
+            PreferenceManager pm = getPreferenceManager();
             Method method = pm.getClass().getDeclaredMethod(
                     "registerOnActivityDestroyListener",
                     PreferenceManager.OnActivityDestroyListener.class);
             method.setAccessible(true);
             method.invoke(pm, this);
-        } catch (Exception e) {
-            e.printStackTrace();
+        } catch (Exception ignored) {
         }
 
         mDialog = mBuilder.build();
@@ -145,6 +140,20 @@ public class MaterialEditTextPreference extends EditTextPreference {
         mDialog.show();
     }
 
+    @Override
+    public void onDismiss(DialogInterface dialog) {
+        super.onDismiss(dialog);
+        try {
+            PreferenceManager pm = getPreferenceManager();
+            Method method = pm.getClass().getDeclaredMethod(
+                    "unregisterOnActivityDestroyListener",
+                    PreferenceManager.OnActivityDestroyListener.class);
+            method.setAccessible(true);
+            method.invoke(pm, this);
+        } catch (Exception ignored) {
+        }
+    }
+
     /**
      * Callback listener for the MaterialDialog. Positive button checks with
      * OnPreferenceChangeListener before committing user entered text
@@ -214,7 +223,7 @@ public class MaterialEditTextPreference extends EditTextPreference {
         }
 
         @Override
-        public void writeToParcel(Parcel dest, int flags) {
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
             super.writeToParcel(dest, flags);
             dest.writeInt(isDialogShowing ? 1 : 0);
             dest.writeBundle(dialogBundle);

+ 18 - 4
library/src/main/java/com/afollestad/materialdialogs/prefs/MaterialListPreference.java

@@ -9,6 +9,7 @@ import android.os.Parcel;
 import android.os.Parcelable;
 import android.preference.ListPreference;
 import android.preference.PreferenceManager;
+import android.support.annotation.NonNull;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.View;
@@ -89,15 +90,14 @@ public class MaterialListPreference extends ListPreference {
             builder.content(getDialogMessage());
         }
 
-        PreferenceManager pm = getPreferenceManager();
         try {
+            PreferenceManager pm = getPreferenceManager();
             Method method = pm.getClass().getDeclaredMethod(
                     "registerOnActivityDestroyListener",
                     PreferenceManager.OnActivityDestroyListener.class);
             method.setAccessible(true);
             method.invoke(pm, this);
-        } catch (Exception e) {
-            e.printStackTrace();
+        } catch (Exception ignored) {
         }
 
         mDialog = builder.build();
@@ -106,6 +106,20 @@ public class MaterialListPreference extends ListPreference {
         mDialog.show();
     }
 
+    @Override
+    public void onDismiss(DialogInterface dialog) {
+        super.onDismiss(dialog);
+        try {
+            PreferenceManager pm = getPreferenceManager();
+            Method method = pm.getClass().getDeclaredMethod(
+                    "unregisterOnActivityDestroyListener",
+                    PreferenceManager.OnActivityDestroyListener.class);
+            method.setAccessible(true);
+            method.invoke(pm, this);
+        } catch (Exception ignored) {
+        }
+    }
+
     @Override
     public void onActivityDestroy() {
         super.onActivityDestroy();
@@ -166,7 +180,7 @@ public class MaterialListPreference extends ListPreference {
         }
 
         @Override
-        public void writeToParcel(Parcel dest, int flags) {
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
             super.writeToParcel(dest, flags);
             dest.writeInt(isDialogShowing ? 1 : 0);
             dest.writeBundle(dialogBundle);

+ 18 - 4
library/src/main/java/com/afollestad/materialdialogs/prefs/MaterialMultiSelectListPreference.java

@@ -10,6 +10,7 @@ import android.os.Parcel;
 import android.os.Parcelable;
 import android.preference.MultiSelectListPreference;
 import android.preference.PreferenceManager;
+import android.support.annotation.NonNull;
 import android.util.AttributeSet;
 import android.view.View;
 
@@ -98,15 +99,14 @@ public class MaterialMultiSelectListPreference extends MultiSelectListPreference
             builder.content(getDialogMessage());
         }
 
-        PreferenceManager pm = getPreferenceManager();
         try {
+            PreferenceManager pm = getPreferenceManager();
             Method method = pm.getClass().getDeclaredMethod(
                     "registerOnActivityDestroyListener",
                     PreferenceManager.OnActivityDestroyListener.class);
             method.setAccessible(true);
             method.invoke(pm, this);
-        } catch (Exception e) {
-            e.printStackTrace();
+        } catch (Exception ignored) {
         }
 
         mDialog = builder.build();
@@ -115,6 +115,20 @@ public class MaterialMultiSelectListPreference extends MultiSelectListPreference
         mDialog.show();
     }
 
+    @Override
+    public void onDismiss(DialogInterface dialog) {
+        super.onDismiss(dialog);
+        try {
+            PreferenceManager pm = getPreferenceManager();
+            Method method = pm.getClass().getDeclaredMethod(
+                    "unregisterOnActivityDestroyListener",
+                    PreferenceManager.OnActivityDestroyListener.class);
+            method.setAccessible(true);
+            method.invoke(pm, this);
+        } catch (Exception ignored) {
+        }
+    }
+
     @Override
     public void onActivityDestroy() {
         super.onActivityDestroy();
@@ -163,7 +177,7 @@ public class MaterialMultiSelectListPreference extends MultiSelectListPreference
         }
 
         @Override
-        public void writeToParcel(Parcel dest, int flags) {
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
             super.writeToParcel(dest, flags);
             dest.writeInt(isDialogShowing ? 1 : 0);
             dest.writeBundle(dialogBundle);

+ 5 - 1
sample/src/main/res/values/strings.xml

@@ -130,7 +130,7 @@
     <string name="list_pref_desc">This is an example of a list preference that automatically uses Material Dialogs to show the list dialog.</string>
     <string name="multilist_pref_title">Multi Select List Preference</string>
     <string name="multilist_pref_desc">This is an example of a multi select list preference that automatically uses Material Dialogs to show the list dialog.</string>
-    <string name="edittext_pref_title">Material EditText Preference</string>
+    <string name="edittext_pref_title">EditText Preference</string>
     <string name="edittext_pref_desc">This is an example of an EditText preference that automatically uses Material Dialogs to show the input dialog.</string>
     <string name="edittext_pref_dialogtitle">Enter a Name</string>
     <string name="edittext_pref_optionalvalue">Default value</string>
@@ -155,5 +155,9 @@
     <string name="set_backup">Set backup account</string>
     <string name="add_account">Add account</string>
     <string name="submit">Submit</string>
+    <string name="preference_dialog_message">This is an example of a dialog message.</string>
+    <string name="preference_dialog_title">Dialog Title</string>
+    <string name="material_dialog_pref_title">Dialog Preference</string>
+    <string name="material_dialog_pref_summary">This is an example of a basic dialog preference that automatically uses Material Dialogs to show the dialog.</string>
 
 </resources>

+ 25 - 15
sample/src/main/res/xml-v11/preferences.xml

@@ -1,33 +1,43 @@
 <?xml version="1.0" encoding="utf-8"?>
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
 
+    <com.afollestad.materialdialogs.prefs.MaterialDialogPreference
+        android:dialogIcon="@drawable/ic_launcher"
+        android:dialogMessage="@string/preference_dialog_message"
+        android:dialogTitle="@string/preference_dialog_title"
+        android:key="unused_key00"
+        android:negativeButtonText="@android:string/cancel"
+        android:positiveButtonText="@android:string/ok"
+        android:summary="@string/material_dialog_pref_summary"
+        android:title="@string/material_dialog_pref_title" />
+
     <com.afollestad.materialdialogs.prefs.MaterialListPreference
-        android:key="unused_key01"
         android:entries="@array/preference_values"
         android:entryValues="@array/preference_values"
-        android:title="@string/list_pref_title"
-        android:summary="@string/list_pref_desc"
+        android:key="unused_key01"
+        android:layout="@layout/preference_custom"
         android:persistent="true"
-        android:layout="@layout/preference_custom" />
+        android:summary="@string/list_pref_desc"
+        android:title="@string/list_pref_title" />
 
     <com.afollestad.materialdialogs.prefs.MaterialMultiSelectListPreference
-        android:key="unused_key02"
         android:entries="@array/preference_values"
         android:entryValues="@array/preference_values"
-        android:title="@string/multilist_pref_title"
-        android:summary="@string/multilist_pref_desc"
+        android:key="unused_key02"
+        android:layout="@layout/preference_custom"
         android:persistent="true"
-        android:layout="@layout/preference_custom" />
+        android:summary="@string/multilist_pref_desc"
+        android:title="@string/multilist_pref_title" />
 
     <com.afollestad.materialdialogs.prefs.MaterialEditTextPreference
-        android:key="unused_key03"
-        android:title="@string/edittext_pref_title"
-        android:summary="@string/edittext_pref_desc"
-        android:inputType="textPersonName"
-        android:dialogTitle="@string/edittext_pref_dialogtitle"
+        android:defaultValue="@string/edittext_pref_optionalvalue"
         android:dialogMessage="@string/optional_dialog_message"
+        android:dialogTitle="@string/edittext_pref_dialogtitle"
+        android:inputType="textPersonName"
+        android:key="unused_key03"
+        android:layout="@layout/preference_custom"
         android:persistent="true"
-        android:defaultValue="@string/edittext_pref_optionalvalue"
-        android:layout="@layout/preference_custom" />
+        android:summary="@string/edittext_pref_desc"
+        android:title="@string/edittext_pref_title" />
 
 </PreferenceScreen>

+ 21 - 11
sample/src/main/res/xml/preferences.xml

@@ -1,24 +1,34 @@
 <?xml version="1.0" encoding="utf-8"?>
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
 
+    <com.afollestad.materialdialogs.prefs.MaterialDialogPreference
+        android:dialogIcon="@drawable/ic_launcher"
+        android:dialogMessage="@string/preference_dialog_message"
+        android:dialogTitle="@string/preference_dialog_title"
+        android:key="unused_key00"
+        android:negativeButtonText="@android:string/cancel"
+        android:positiveButtonText="@android:string/ok"
+        android:summary="@string/material_dialog_pref_summary"
+        android:title="@string/material_dialog_pref_title" />
+
     <com.afollestad.materialdialogs.prefs.MaterialListPreference
-        android:key="unused_key01"
         android:entries="@array/preference_values"
         android:entryValues="@array/preference_values"
-        android:title="@string/list_pref_title"
-        android:summary="@string/list_pref_desc"
+        android:key="unused_key01"
+        android:layout="@layout/preference_custom"
         android:persistent="true"
-        android:layout="@layout/preference_custom" />
+        android:summary="@string/list_pref_desc"
+        android:title="@string/list_pref_title" />
 
     <com.afollestad.materialdialogs.prefs.MaterialEditTextPreference
-        android:key="unused_key03"
-        android:title="@string/edittext_pref_title"
-        android:summary="@string/edittext_pref_desc"
-        android:inputType="textPersonName"
-        android:dialogTitle="@string/edittext_pref_dialogtitle"
+        android:defaultValue="@string/edittext_pref_optionalvalue"
         android:dialogMessage="@string/optional_dialog_message"
+        android:dialogTitle="@string/edittext_pref_dialogtitle"
+        android:inputType="textPersonName"
+        android:key="unused_key03"
+        android:layout="@layout/preference_custom"
         android:persistent="true"
-        android:defaultValue="@string/edittext_pref_optionalvalue"
-        android:layout="@layout/preference_custom" />
+        android:summary="@string/edittext_pref_desc"
+        android:title="@string/edittext_pref_title" />
 
 </PreferenceScreen>