Question

I want to validate an EditTextPreference value to be inside a specific int range (lets say 1 to 22). The only part that I could validate was the inputType (number only) with the following xml declaration in the prefs.xml file.

android:inputType="number"

The second thing that I did is to write the following code in the ListSettings activity.

public class ListSettings extends PreferenceActivity implements OnSharedPreferenceChangeListener{

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.prefs);
    SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
    sp.registerOnSharedPreferenceChangeListener(this);
}
 public void onSharedPreferenceChanged(SharedPreferences sp, String key) {
        String value = sp.getString(key, null);
        int intZoomValue = Integer.parseInt(value);
        if (intZoomValue < 1 || intZoomValue > 22) {
            Intent intent = new Intent().setClass(this, dialog.class);
            // I want to call the dialog activity here...
        }

  }

and the dialog.class is the following:

public class dialog extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  AlertDialog.Builder builder = new AlertDialog.Builder(this);
  builder.setMessage("Please enter a value between 1-22!");
  builder.setCancelable(true);

  AlertDialog alert = builder.create();
  alert.show();
  }
}

What I want to achieve is to call the dialog.class (the alert dialog box) whenever the user enters a value not in the range 1-22.

I can't really understand how to validate with the proper way.

Was it helpful?

Solution

It might be more user-friendly to just clamp the value to the permitted range if an invalid value is entered, and notify the user with a Toast that you have done so.

If your range is small, such as 1-22, then you may even consider using a Spinner instead of an EditText so that the user can't enter an invalid value in the first place.

OTHER TIPS

This is what I did:

    EditTextPreference pref = (EditTextPreference) findPreference(this.getString(R.string.my_setting_key));
    pref.getEditText().setFilters(new InputFilter[]{
            new InputFilter (){

                @Override
                public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {   
                    try {
                        int input = Integer.parseInt(dest.toString() + source.toString());
                        if (input<MAX_VALUE && input >0)
                            return null;
                    } catch (NumberFormatException nfe) { }     
                    return "";
                }
            }
    });

So the trick is that you can get and EditText from your EditTextPreference by using:

    pref.getEditText()

then you can set a filter. The filter should return null when everything is ok and an empty string when the char the user entered would make the text invalid.

See also here

You could use setPositivteButton and validate the input once the user hits Okay, if not okay, repop the dialog.

The InputFilter solution does not work, especially with selectAllOnFocus. If you cannot use the suggested picker/spinner alternative, for example, when you want to enforce a minimum but not a maximum, you can disable the OK button when the value is invalid like this:

public static void setNumberRange(final EditTextPreference preference, 
                                  final Number min, final Number max) {
    setNumberRange(preference, min, max, false);
}

public static void setNumberRange(final EditTextPreference preference,
                                  final Number min, final Number max, 
                                  final boolean allowEmpty) {

    preference.getEditText().addTextChangedListener(new TextWatcher() {

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
        }

        @Override
        public void afterTextChanged(final Editable s) {

            Dialog dialog = preference.getDialog();
            if (dialog instanceof AlertDialog) {
                Button button = ((AlertDialog) dialog).getButton(DialogInterface.BUTTON_POSITIVE);
                if (allowEmpty && s.length() == 0) {
                    button.setEnabled(true);
                    return;
                }
                try {
                    if (min instanceof Integer || max instanceof Integer) {
                        int input = Integer.parseInt(s.toString());
                        button.setEnabled((min == null || input >= min.intValue()) && (max == null || input <= max.intValue()));
                    } else if (min instanceof Float || max instanceof Float) {
                        float input = Float.parseFloat(s.toString());
                        button.setEnabled((min == null || input >= min.floatValue()) && (max == null || input <= max.floatValue()));
                    } else if (min instanceof Double || max instanceof Double) {
                        double input = Double.parseDouble(s.toString());
                        button.setEnabled((min == null || input >= min.doubleValue()) && (max == null || input <= max.doubleValue()));
                    }
                } catch (Exception e) {
                    button.setEnabled(false);
                }
            }
        }
    });
}

This allows you to specify minimum and/or maximum values as Integer, Float or Double (pass null for unbounded). Optionally you can allow/disallow empty values. (Values invalid initially are accepted.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top