What I want to do is I am working on a game of life program. I want to take the time delay and make it a preference, but I want to make it available for people to type in a specific time. The number can be in miliseconds or seconds.
However I'm a little stuck on how to proceed, I haven't been able to find a simple preference that already handles this, but there might be one. Is there an easy way to make this preference and confirm that the entered data is an integer or afloat?
Use an EditTextPreference and set the input type to TYPE_CLASS_NUMBER. This will force the user to enter numbers and not letters.
EditTextPreference pref = (EditTextPreference)findPreference("preference_name");
pref.getEditText().setInputType(InputType.TYPE_CLASS_NUMBER);
You can also enforce it with the xml attribute android:numeric. The possible relevant values for this attribute are decimal and integer.
You can also do this directly in your preferences.xml. Something like this would work:
<EditTextPreference
android:defaultValue="100"
android:dialogTitle="#string/pref_query_limit"
android:inputType="number"
android:key="pref_query_limit"
android:summary="#string/pref_query_limit_summ"
android:title="#string/pref_query_limit" />
If you are using a PreferenceActivity which you probably are, there is not one available.
You will need to do something like this:
/**
* Checks that a preference is a valid numerical value
*/
Preference.OnPreferenceChangeListener numberCheckListener = new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
//Check that the string is an integer.
return numberCheck(newValue);
}
};
private boolean numberCheck(Object newValue) {
if( !newValue.toString().equals("") && newValue.toString().matches("\\d*") ) {
return true;
}
else {
Toast.makeText(ActivityUserPreferences.this, newValue+" "+getResources().getString(R.string.is_an_invalid_number), Toast.LENGTH_SHORT).show();
return false;
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//get XML preferences
addPreferencesFromResource(R.xml.user_preferences);
//get a handle on preferences that require validation
delayPreference = getPreferenceScreen().findPreference("pref_delay");
//Validate numbers only
delayPreference.setOnPreferenceChangeListener(numberCheckListener);
}
In Android Jetpack Preference things changed, to access EditText you have to access like this
val preference = findPreference<EditTextPreference>(getString(R.string.pref_numdefault_key))
preference?.setOnBindEditTextListener {
it.inputType = InputType.TYPE_CLASS_NUMBER
}
Related
This question already has answers here:
How do you validate the format and values of EditTextPreference entered in Android 2.1?
(3 answers)
Closed 8 years ago.
I have a preference screen that, when a setting is enabled, has several strings that must be a particular length (# of characters). Also all of the strings are required. Ideally when the user has enabled this setting they should not be able to apply the changes until all strings are filed in with the appropriate length. Note that I'm not talking about a max length, but an exact character count.
How can I enforce those rules on the user? Is there a way to do this through the built-in preference controls or do I have to build a custom fragment?
The Preference class has the onPreferenceChange listener.
public abstract boolean onPreferenceChange (Preference preference, Object newValue);
By returning false from this listener, the new value will not be accepted:
public boolean onPreferenceChange(Preference pref, Object newValue) {
if (pref == myStringPreferenceToValidate) {
final String newValueStr = (String) newValue;
if (newValueStr.length() != XX) {
// don't save it, not the correct length
return false;
}
return true;
}
}
Check out the full documentation here: http://developer.android.com/reference/android/preference/Preference.OnPreferenceChangeListener.html
I'm writing custom EditTextPreference.
Using this code inside my CustomEditTextPreference:
#Override
protected void onDialogClosed(boolean shouldSave) {
if (shouldSave) {
String sValue = getText();
value = Float.parseFloat(sValue);
peristValue();
}
}
sValue is null. How do I acquire the value from edit then?
You should probably use
getEditText().getText().toString();
Since getText() by itself gets the current SharedPreference value, which may or may not exist.
I have a PreferenceScreen in which the user is capable, if system can't autodetect it, to enter the device's phone number. I'm still learning this part of Android but I managed to understand a bit of PreferenceScreens by examples provided by Android SDK itself and a few tutorials.
What I want is that the user can save the phone number only if null or valid, where by "valid" I mean running a generic validation logic (ie. an anonymous method that returns true or false, that can be reused in any possible situation*) or better, just to simplify things, ^(\+39)?3[0-9]{9}$
For now I have the following XML snip
<EditTextPreference
android:inputType="phone"
android:key="#string/preference_phoneNo"
android:selectAllOnFocus="true"
android:singleLine="true"
android:summary="#string/pref_phoneNumber_description"
android:title="#string/pref_phoneNumber" />
and following code by courtesy of Eclipse New Activity wizard:
private void setupSimplePreferencesScreen() {
if (!isSimplePreferences(this)) {
return;
}
addPreferencesFromResource(R.xml.pref_general);
bindPreferenceSummaryToValue(findPreference(getString(R.string.preference_phoneNo)));
}
addPreferenceFromResource is supposed to load the XML node and add the preference to the screen, while binPreferenceSummaryToValue is supposed to make description text change when preference is updated. Just for sake of completeness for those who don't like code courtesy of the IDE, the second method is provided by Eclipse who also provides a private class in the code file that is
/**
* A preference value change listener that updates the preference's summary
* to reflect its new value.
*/
In the general case, what should I do to perform validation logic before the preference gets saved when I click OK on the preference editor? Where is the validation logic to be put in a PreferenceScreen?
*Aren't we all here to learn?
Android has a built in helper method for this.
String phoneNumber = ...;
boolean valid = PhoneNumberUtils.isGlobalPhoneNumber(phoneNumber);
For a generic, re-usable method, here's the implementation of that method in PhoneNumberUtils, courtesy of AOSP (Apache licensed)
private static final Pattern GLOBAL_PHONE_NUMBER_PATTERN =
Pattern.compile("[\\+]?[0-9.-]+");
...
public static boolean isGlobalPhoneNumber(String phoneNumber) {
if (TextUtils.isEmpty(phoneNumber)) {
return false;
}
Matcher match = GLOBAL_PHONE_NUMBER_PATTERN.matcher(phoneNumber);
return match.matches();
}
Validation should occur within a Preference.OnPreferenceChangeListener , in the onPreferenceChange method. Simply return false if you don't want the value to be saved.
Example snippet:
private static Preference.OnPreferenceChangeListener myListener =
new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
if (preference instanceof PhoneNumberPreference) {
return isGlobalPhoneNumber(value);
}
}
...
As a note, since you're starting off with the Settings activity generated by the Eclipse wizard, this listener has already been built for you. You just need to edit it to include validation of the phone number (assuming that's what's being edited), and to return false if the number is invalid, so it won't be saved to preferences.
I have an Android preferences screen where some of the preferences are interdependent.
In other words, if one of the preferences is set to a certain value(s) then another two of the others are available.
If not, then they are not because they are meaningless.
Specifically, I have an option with 3 possible values: Prompt, Yes and No.
When the value is set to No I want to lock the other 2 options.
How do I do this in Android 2.1?
Basically just call setEnabled() on the preferences you want to enable/disable in the OnPreferenceChangeListener for the 3-way preference. e.g.:
otherPrefOne = (ListPreference)findPreference("OTHER_PREF_1");
otherPrefTwo = (ListPreference)findPreference("OTHER_PREF_2");
ThreeWayPref = (ListPreference)findPreference("3WAY_PREF");
ThreeWayPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (((String)newValue).equals("No")) {
otherPrefOne.setEnabled(false);
otherPrefTwo.setEnabled(false);
} else {
otherPrefOne.setEnabled(true);
otherPrefTwo.setEnabled(true);
}
return true;
}
});
I want to change the values displayed in each Preference in my PreferenceActivity based on the change in another preference.
I have an app that stores metric (float) values in Preferences. I also have a Preference called metric where the user can switch between usage of metric or imperial units.
I only store metric values, but when the user switches to imperial the app displays the imperial values.
Everything works fine if the user only switches the metric preference and leaves the PreferenceActivity. When he goes back the values are displayed the correct way. If he goes to look at userHeight for example the display still shows the metric value though.
In my PreferenceActivity I want to refresh the displayed values when the metric Preference changes (I am making sure that when these values should be stored they will be converted back correctly):
this.metric.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final Boolean metric = Boolean.parseBoolean(newValue.toString());
changeSummaries(metric);
refreshDisplay(metric);
return true;
}
});
What do I have to implement in the refreshDisplay(...) method? It would also help to know at what point of the lifecycle of the PreferenceActivity are the changed values committed?
I found it. At least for my specific problem I found a simple solution.
I had already extended EditTextPreference to be able to store something other than String
Before opening the dialog the onBindDialogView method is called at that point the other changed Preference is committed (I thought at first it might not be - a quick test proved me wrong). Simply overriding onBindDialogView allows me to change the displayed value to the one I want to display:
#Override
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
getEditText().setText(getPersistedString(""));
}
#Override
protected String getPersistedString(String defaultReturnValue) {
final Float storedValue = getPersistedFloat(-1);
Float returnValue;
if (MyPreferences.isMetric(getContext())) {
returnValue = storedValue;
} else {
returnValue = this.unit.convertToImperial(storedValue);
}
return String.valueOf(returnValue);
}