AndroidX: Set Enter key to validate EditTextPreference dialog box

1.1k Views Asked by At

I'm trying to make a preference screen with AndroidX, but I'm encountering a small problem...

When I validate my entry with the "OK" button on the virtual keyboard, the preference is not validated. (keyboard is hidden, that's all...)

With AndroidX, we can no longer override showDialog() in EditTextPreference... and I couldn't find another way to access the dialog box to dismiss it.

In conclusion, what I wish: the DONE action of the button on the virtual keyboard validates the AlertDialog.

enter image description here

Here's my sample code:

XML file

<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
    <EditTextPreference
        app:key="pref_1"
        app:title="Test"
        app:useSimpleSummaryProvider="true" /> 
</PreferenceScreen> 

Preference activity

public class MySettingsActivity extends AppCompatActivity implements
        PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {

    [...]

    public static class HeaderFragment extends PreferenceFragmentCompat {
        @Override
        public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
            setPreferencesFromResource(R.xml.header_preferences, rootKey);

            EditTextPreference pref1 = getPreferenceManager().findPreference("pref_1");
            pref1.setOnBindEditTextListener(new EditTextPreference.OnBindEditTextListener() {
                @Override
                public void onBindEditText(@NonNull EditText editText) {
                    editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
                    editText.setImeOptions(EditorInfo.IME_ACTION_DONE);
                }
            });
        }
    }
}
2

There are 2 best solutions below

6
On BEST ANSWER

If you want to validate that update value of text you need to use this listener

pref1.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {

            @Override
            public boolean onPreferenceChange(Preference preference, Object newValue) {
                // put validation here..

                Log.d("Prefrence====>",newValue+"<===  validate you can validate this value");

                return true; //if you pass false here the updated value will not save
            }
        });

here is the example to use the true false return

public static class HeaderFragment extends PreferenceFragmentCompat {
    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        setPreferencesFromResource(R.xml.headerpref, rootKey);

        EditTextPreference pref1 = getPreferenceManager().findPreference("pref_1");

        pref1.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {

            @Override
            public boolean onPreferenceChange(Preference preference, Object newValue) {
                // put validation here..

                Log.d("Prefrence====>",newValue+"<===  validate you can validate this value");
                if(newValue.toString().length()>0){
                    return  true;
                }else return false;
            }
        });

        pref1.setOnBindEditTextListener(new EditTextPreference.OnBindEditTextListener() {
            @Override
            public void onBindEditText(@NonNull EditText editText) {
                editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
                editText.setImeOptions(EditorInfo.IME_ACTION_DONE);
                editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
                    @Override
                    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                        //Your dialog will dissmiss on ok click
                        if(actionId==EditorInfo.IME_ACTION_DONE)dismissDialog();
                        return false;
                    }
                });

            }
        });


    }
void dismissDialog(){
        for(Fragment fragments : HeaderFragment.this.getActivity().getSupportFragmentManager().getFragments()){
            if(fragments instanceof EditTextPreferenceDialogFragmentCompat){
                EditTextPreferenceDialogFragmentCompat dialog = ((EditTextPreferenceDialogFragmentCompat) fragments);
                dialog.onDialogClosed(true);
                dialog.dismiss();
                return;
            }
        }
    }
}

Since you want to dismiss Dialog manually you can do it like this way , cause there are no direct method available to get the dialog and dismiss it.

I updated the dialog dismiss listener as your need to save the data passing true in onDialogClosed method will help to save your data

void dismissDialog(){

        for(Fragment fragments : HeaderFragment.this.getActivity().getSupportFragmentManager().getFragments()){
            if(fragments instanceof EditTextPreferenceDialogFragmentCompat){
                EditTextPreferenceDialogFragmentCompat dialog = ((EditTextPreferenceDialogFragmentCompat) fragments);
                dialog.onDialogClosed(true);
                dialog.dismiss();
                return;
            }
        }
    }
1
On

I found another way. I don't think it's the best, but if it can help anyone...

PreferenceFragmentCompat customized

public class PreferenceFragmentCompatCustom extends PreferenceFragmentCompat {
    private static final String DIALOG_FRAGMENT_TAG =
            "androidx.preference.PreferenceFragment.DIALOG";
    private DialogFragment mDialogFragment;

    @Override
    public void onDisplayPreferenceDialog(Preference preference) {
        if (getActivity() instanceof MySettingsActivity) {
            final DialogFragment f;
            if (preference instanceof EditTextPreference) {
                f = EditTextPreferenceDialogFragmentCompat.newInstance(preference.getKey());
            } else if (preference instanceof ListPreference) {
                f = ListPreferenceDialogFragmentCompat.newInstance(preference.getKey());
            } else {
                throw new IllegalArgumentException("Tried to display dialog for unknown " +
                        "preference type. Did you forget to override onDisplayPreferenceDialog()?");
            }
            f.setTargetFragment(this, 0);

            // Expose the dialog
            mDialogFragment = f;

            f.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);

        }else{
            super.onDisplayPreferenceDialog(preference);
        }
    }

    public DialogFragment getDialog(){ return mDialogFragment;}

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {}
}

Preference activity

public class MySettingsActivity extends AppCompatActivity implements
        PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {

    [...]

    public static class HeaderFragment extends PreferenceFragmentCompatCustom {
        @Override
        public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
            setPreferencesFromResource(R.xml.header_preferences, rootKey);

            EditTextPreference pref1 = getPreferenceManager().findPreference("pref_1");
            pref1.setOnBindEditTextListener(new EditTextPreference.OnBindEditTextListener() {
                @Override
                public void onBindEditText(@NonNull EditText editText) {
                    editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
                    editText.setImeOptions(EditorInfo.IME_ACTION_DONE);

                    editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
                        @Override
                        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                            if (actionId == EditorInfo.IME_ACTION_DONE) {
                                // If callOnClick, do not save value here
                                //etpTest.setText(v.getText().toString());
                                // If dismiss, the preference is not set !
                                //getDialog().dismiss();

                                ((AlertDialog) getDialog().getDialog())
                                               .getButton(DialogInterface.BUTTON_POSITIVE)
                                               .callOnClick();
                                return true;
                            }
                            return false;
                        }
                    });
                }
            });
        }
    }
}