Get current ListPreference label from MainActivity - android

As explained here:
Get Key, not value, of the ListPreference selection - Possible?
and many other places, it is quite easy to access ListPreferences labels from PreferenceActivity.
What I need to do is to read the label corresponding to the current selected from the main activity.
But I can't find a way.
For example, in my main activity I have
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
I would like to use something like:
ListPreference listPreference = (ListPreference) settings.findPreference("list_of_countries");
And then handle it to get current value and label.
Update 01
I tried to handle another way to retrieve the summary (the name of a country in my example) value which I need to say the customer what he selected. I can't give him the code!
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
String stringSummary = preference.getSummary().toString();
String stringKey = preference.getKey().toString();
if (stringKey.equals("list_of_countries")){
MyActivity.countryName = stringSummary;
}
Nothing to do... the OnPreferenceChangeListener is called.... BEFORE the preference change, i.e., when one item is clicked, so what I succeed to retrieve is just the past summary.
I found no way.

Related

Referencing another preference in onPreferenceChange(preference, value)

I have two preferences that are related (units and distance)
When units changes I want to convert the distance accordingly. For example if distance is 1610 meters and units changes to miles I want to convert it to 1 mile.
For this I use the code provided by Android studio SettingsActivity code.
But how do I find the distance preference when the units preference changes?
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
...
// I need to address also the distance preference value here
// It is not the preference given in the arguments (units)
// The distance preference is in another preferences fragment
...
}
};
If you can't put it in the listener you can just override the onSharedPreferencesChanged() method and access like this:
SharedPreferences prefs = getSharedPreferences(String str, Context.MODE_PRIVATE)
SharedPreferences.Editor prefEditor = prefs.edit()
editor.putInt("distance", 1610)
editor.apply()
Otherwise use an application context from a singleton.
Update in response to comment:
My apologies for misunderstanding your question. In that case something like:
SharedPreferences prefs = getDefaultSharedPreferences(appContext);
int distance = prefs.getInt("distance", defaultValue);
preference.setSummary(/* whatever value you wish to pass*/);

How do I access a value from my Preference?

My app contains shared preferences, so in my "Settings-Menu" I can select an item from a list.
In another java file I want to access the value of the selected item.
I failed passing the integer-value through an intent, because the integer is declared in private static, private boolean, and Android Studio tells me, it cannot be refferenced from a static content.
So how can I receive my value from this integer? Thanks in advance :).
Edit: firstival, thanks a lot for that many answers! But as I'm not that much into java I wasn't able to follow your instructions, so I'm going to depict my problem closer.
I'm using androids template "Settings-Activity". In my strings.xml I've got
<string name="Values">Values</string>
<string-array name="pref_example_list_titles">
<item>A</item>
<item>B</item>
<item>C</item>
</string-array>
<string-array name="pref_example_list_values">
<item>01</item>
<item>02</item>
<item>03</item>
</string-array>
In my SettingsActivity.java
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
if (preference instanceof ListPreference) {
ListPreference listPreference = (ListPreference) preference;
int index = listPreference.findIndexOfValue(stringValue);
preference.setSummary(
index >= 0
? listPreference.getEntries()[index]
: null);
{...}
In another java file, a fragment "FirstFragment.java I finally want to assign the value from pref_example_list_values to a new integer, called "Vallue2".
So could you please explain me, how I do this, bc I couldn't follow your explainations. Thanks a lot!
As per documentation:
A SharedPreferences object points to a file containing key-value pairs and provides simple methods to read and write them.
This means that a single file holds the value, and the preffered way to read and write to it are as following:
SharedPreferences preference = yourContext.getSharedPreferences(yourFileName), Context.MODE_PRIVATE
);
preference.edit().putString(AN_IDENTIFIER, "aValue").apply();
Then to retrieve the value:
SharedPreferences preference = yourContext.getSharedPreferences(yourFileName), Context.MODE_PRIVATE
);
preference.getString(AN_IDENTIFIER,"a default value to use");

Validating a phone number in Android PreferenceScreen

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.

Refresh EditText of a Preference depending on the change of another Preference

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);
}

Number Preferences in Preference Activity in Android

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
}

Categories

Resources