Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a PreferenceActivity launch a Dialog to set a custom preference

I have a working Preferences setup launched from a menu option. In the preferences I have setup a Custom Preference that must launch a dialog with 3 TextViews to set confirm and change a password. Now I do not know how to launch the dialog from the PreferenceActivity's onPreferenceClick. If I sound like a newby - I am, sorry!

Here is my xml layout for the dialog popup:

<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:id="@+id/root"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <TextView
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:id="@+id/TextView_Pwd1"
        android:text="@string/settings_oldpassword"
        android:textStyle="bold" />

    <EditText
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:id="@+id/EditText_OldPwd" />

    <TextView
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:id="@+id/TextView_Pwd1"
        android:text="@string/settings_password"
        android:textStyle="bold" />

    <EditText
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:id="@+id/EditText_Pwd1"
        android:inputType="textPassword" />

    <TextView
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:id="@+id/TextView_Pwd2"
        android:text="@string/settings_password2"
        android:textStyle="bold" />

    <EditText
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:id="@+id/EditText_Pwd2"
        android:inputType="textPassword" />

    <TextView
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:id="@+id/TextView_PwdProblem"
        android:textStyle="bold"
        android:gravity="center" />

    <TextView
        android:id="@+id/TextView_PwdProblem"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="@string/settings_pwd_not_equal" />

    <CheckBox
        android:id="@+id/checkShowPwdText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/settings_showpwd_text" />

Here is my DialogChangePassword class for the dialog popup:

package biz.linsys.package;

import android.app.Dialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.DialogPreference;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

public class DialogChangePassword extends DialogPreference {

    private String strPass1;
    private String strPass2;

    public DialogChangePassword(Context context, AttributeSet attrs) {
        super(context, attrs);
        setDialogLayoutResource(R.layout.dialog_pwdchange);
    }

    @Override
     protected void onBindDialogView(View view) {

        Dialog pwdDialog            = getDialog();
        final EditText password1    = (EditText) pwdDialog.findViewById(R.id.EditText_Pwd1);
        final EditText password2    = (EditText) pwdDialog.findViewById(R.id.EditText_Pwd2);
        final TextView error        = (TextView) pwdDialog.findViewById(R.id.TextView_PwdProblem);      

        password2.addTextChangedListener(new TextWatcher() {

            @Override
            public void afterTextChanged(Editable s) {

                strPass1 = password1.getText().toString();
                strPass2 = password2.getText().toString();

                if (strPass1.equals(strPass2)) {

                    error.setText(R.string.settings_pwd_equal);
                } else {

                    error.setText(R.string.settings_pwd_not_equal);
                }
            }  public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
               public void onTextChanged(CharSequence s, int start, int before, int count) {}
        });

        super.onBindDialogView(view);

    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {

        if(!positiveResult) return;

        SharedPreferences.Editor editor = getEditor();

        if (strPass1.equals(strPass2)) {

            editor.putString("password", strPass1);
            editor.commit();
        }

        super.onDialogClosed(positiveResult);

    }
}

This the PreferenceActivity class containing Custom Preference onPreferenceClick. This is where I need to call the dialog box to change the user password setting.

package biz.linsys.package;

import android.content.Context;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;

public class Preferences extends PreferenceActivity {

    public static Context dialogContext;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);

        // Get the custom preference
        Preference customPref = (Preference) findPreference("customPref");

        customPref.setOnPreferenceClickListener(new OnPreferenceClickListener() {

            public boolean onPreferenceClick(Preference preference) {

                // [ NEED TO CALL DIALOG FROM HERE ]

                return false;
           }
        });
    }
}
like image 993
Lukuluba Avatar asked Apr 04 '12 23:04

Lukuluba


1 Answers

This is something that is missing in the documentation, and I've found lots of similar questions regarding it, mostly with no definite answers. I've faced the same problem today, and somehow I've found the solution, so I'll summarize my quest here, just in hope someone will find this useful. BTW your question is the most detailed and accurate among others.

The general point is that you don't need to create the dialog manually, you just 1) create a subclass of the DialogPreference that will handle the logic of a complex preference and 2) create a node of the proper type in your preferences.xml so the dialog will be spawned automatically.

The problem of the Android SDK is that you cannot add that proper node using the visual XML editor, you need to go and edit the file manually.

The problem of the documentation is that it misses this very bit of information.

So here is the step-by-step solution:

1) Create a subclass of DialogPreference that will handle your special preference. For details on what is needed in your subclass, I'd recommend this answer.

2) Create a Preference node in your preferences.xml.

3) Edit the preferences.xml and replace the Preference with full name of your DialogPreference subclass including the package path, e. g. com.sample.MyPreferenceDialog. You may also add some attributes to the node to customize the dialog (title, icon, etc.), see this answer or the documentation for DialogPreference for details.

That's all. You don't need to add OnPreferenceClickListener to the preferences, the dialog will show up automatically.

Note: I am not 100% sure that this is the intended way of using things, but it seems to be working.

like image 186
Alexander Dunaev Avatar answered Oct 20 '22 19:10

Alexander Dunaev