Custom EditTextPreference and setOnPreferenceChangeListener not called - android

My listener is not getting called for some reason? This is what I have:
In Preference file I have a custom EditTextPreference:
<com.xxx.yyy.preference.PreferenceEditTextDialog
android:layout="#layout/preference_edit"
android:title="#string/title"
android:summary="#string/summary"
android:defaultValue=""
android:dialogTitle="#string/dialogTitle"
android:key="mypref"/>
I extend my class:
public class PreferenceEditTextDialog extends EditTextPreference {
Launching my Activity:
startActivity(new Intent(this, PrefsActivity.class));
Definition:
public class PrefsActivity extends PreferenceActivity implements
OnPreferenceClickListener, OnSharedPreferenceChangeListener {
In here I register my setOnPreferenceChangeListener (which is not called).
However changing my Preference file from:
<com.xxx.yyy.preference.PreferenceEditTextDialog
to default:
<EditTextPreference
it all works. Could someone help me to find the problem, somehow the listener is not propagated properly using my custom Preference.
Thanks!
#Sam Here my listener definition:
myfield = (EditTextPreference) getPreferenceScreen().findPreference(KEY_PREFERENCE);
myfield.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
Boolean valid = true;
if(!validate(newValue.toString())) {
valid = false;
}
return valid;
}
});

Found a solution, in my custom EditTextPreference I added a call to callChangeListener(value):
#Override
public void onBindDialogView(View view) {
edittext = (EditText) view.findViewById(R.id.edittext);
edittext.setText(PreferenceManager.
getDefaultSharedPreferences(view.getContext()).
getString(getKey(), ""));
ok_button = (Button) view.findViewById(R.id.ok_button);
ok_button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
String value = edittext.getText().toString();
if(callChangeListener(value)) {
Editor editor = getEditor();
editor.putString(getKey(), value);
editor.commit();
getDialog().dismiss();
}
}
});

Related

AndroidX: Set Enter key to validate EditTextPreference dialog box

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

Check if switch from SettingsActivity is on

How can I check in my MainActivity if the on/off switch is on in the SettingsActivity. I want to check if the switch is on and if it is, I want to do something. How do I do this so that this preference is saved and will be the same when you restart the app?
Here is a part of my SettingsActivity with a switch
static int audio;
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class GeneralPreferenceFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_general);
setHasOptionsMenu(true);
bindPreferenceSummaryToValue(findPreference("example_text"));
bindPreferenceSummaryToValue(findPreference("example_list"));
Preference switchPref = (Preference) findPreference("audio_switch");
switchPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object o) {
boolean isOn = (boolean) o;
if (isOn) {
audio = 1;
}else{
audio = 0;
}
return true;
}
});
}
You are saving correctly the preference value, even you are returning true from your onPreferenceChangeListener to store the new value.
Preference switchPref = (Preference) findPreference("audio_switch");
switchPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object o) {
boolean isOn = (boolean) o;
if (isOn) {
audio = 1;
}else{
audio = 0;
}
//* Set true to update the state of the Preference with the new value!
return true;
}
});
}
The value is saved correctly when you close the application, if you want to check the value you can read it from the preference:
//Check the current value in preference.
SharedPreferences switchPrefStatus = PreferenceManager.getDefaultSharedPreferences(getActivity());
boolean switchPrefValue = switchPrefStatus.getBoolean("audio_switch", false);
Toast.makeText(getActivity(), "Current value: " + switchPrefValue, Toast.LENGTH_SHORT).show();
Here is a complete example of PreferenceFragment with PreferenceFragment:
I usually do the following:
To save your setting
(Put this in a save() method you call when you click a button or something in your settings activity)
SharedPreferences options =
getSharedPreferences("optionsPreference",
contextOfSettings.MODE_PRIVATE);
options.edit().putString("key", "value").apply();
In order to do this you need to add this in your settings activity
As a global variable in settings
public static Context contextOfSettings;
And this method in your onCreate of settings
#Override
protected void onCreate {
contextOfSettings = getApplicationContext();
}
And import it in your main activity by typing context of settings somewhere and then import it by pressing alt+enter
Like this:
import com.SettingsActivity.contextOfSettings;
Then you can get your saved value (which will still be saved even if you close your app) with this in your on create of your MainActivity
SharedPreferences options = getSharedPreferences("optionsPreference", contextOfSettings.MODE_PRIVATE);
String savedValue = options.getString("key", "defaultValue");
This String can have the values true and false which you can set with checkBox.isChecked() in combination with an if-statement

Android can't figure out why perference screen won't show preference textbox

I'm trying to display preference screen and with a text box and doesn't show but in another screen it has no problem? It shows a negative 1 or null.
StatsActivity
public class StatsActivity extends Activity {
static final String TAG = "StatsActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.stats_settings_layout);
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
StringBuilder builder = new StringBuilder();
builder.append("\n" + sharedPrefs.getString("time_usage_key", "-1"));
TextView settingsTextViewStats = (TextView) findViewById(R.id.stats_settings_text_view);
settingsTextViewStats.setText(builder.toString());
}
}
StatsPrefsActivity
public class StatsPrefsActivity extends PreferenceActivity implements
OnSharedPreferenceChangeListener{
static final String TAG = "StatsPrefsActivity";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences_stats);
PreferenceManager.setDefaultValues(this,R.xml.preferences_stats, false);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
//menu.add(Menu.NONE, 0, 0, "Show current settings");
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 0:
startActivity(new Intent(this, StatsActivity.class));
return true;
}
return false;
}
#Override
public void onStart(){
super.onStart();
SharedPreferences prefs=PreferenceManager.getDefaultSharedPreferences(StatsPrefsActivity.this);
}
#Override
protected void onResume() {
super.onResume();
// Set up a listener whenever a key changes
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
#Override
protected void onPause() {
super.onPause();
// Unregister the listener whenever a key changes
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
SharedPreferences s = getSharedPreferences("MY_PREFS", 0);
// Create a editor to edit the preferences:
SharedPreferences.Editor editor = s.edit();
}
}
preference_stats.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="Settings"
android:key="first_category">
<EditTextPreference
android:id="#+id/text_pref_box"
android:key="time_usage_key"
android:title="7 Day Usage"
android:summary="A total of usage of 7 days." />
</PreferenceCategory>
</PreferenceScreen>
if you want an inital value then set one. right now you have "-1" set as the default value. so if the preference has never been used before your going to get "-1" as the default. Try changing that to a blank string "" or something if you want better presentation.

OnPreferenceChangeListener

I have a EditText in a preference menu that allows me to edit a URL address. The problem is when I get the preference value in the mainActivity is not getting updated right away after I click OK in the Preference Menu. Not sure how to fix this problem. I tried a bunch of ideas and finally decided to ask.
public class PreferencesActivityTest extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.radio_preferences);
PreferenceManager.setDefaultValues(PreferencesActivityTest.this,
R.xml.radio_preferences, false);
EditTextPreference editPref =(EditTextPreference)findPreference("MyText");
editPref.setOnPreferenceChangeListener(
new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference,
Object newValue) {
if (newValue.toString().length() > 0) {
return true;
}
// If now create a message to the user
Toast.makeText(PreferencesActivityTest.this,
"Invalid Input", Toast.LENGTH_SHORT).show();
return false;
}
});
}
}
PS: This code updates the newValue to what I enter in the EditTextPreference, doesn't carry the new value to the MainActivity until I modify it again...
UPDATE:
In OnResume() I can see that the value is updated with the one that I modified in the PreferenceActivityTest from EditTextPreference. What I'm trying to do is to pass this newValue into the SetDataSource("").
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_radio);
initializeMediaPlayer();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_edit:
editURL();
// make a Dialog or show an Activity
return true;
}
}
private void initializeMediaPlayer() {
PreferenceManager.setDefaultValues(this, R.xml.radio_preferences, false);
SharedPreferences pref =PreferenceManager.getDefaultSharedPreferences(this);
String radioPath = pref.getString("MyText", "default value");
// Toast.makeText(this, radioPath, Toast.LENGTH_SHORT).show();
try {
radioPlayer.reset();
// radioPlayer.setDataSource("http://31.xx.xxx");
// Toast.makeText(this, radioPath, Toast.LENGTH_SHORT).show();
radioPlayer.setDataSource(radioPath);
} catch {
}
}
public void editURL() {
stopPlaying();
startActivity(new Intent(getBaseContext(), PreferencesActivityTest.class));
}
I am doing something fundamentally wrong but I need help. Thank you in advance !
how are you calling the preference activity? If you are calling it directly, you probably need to change the call to startActivityForResult so you refresh your data once you return from the Activity

Is it possible to combine an EditTextPreference with a CheckBoxPreference?

I have a PreferenceActivity with, among other things, a category including call forward options. What I want is a preference that:
Enables/Disables if the user presses a checkbox on the right.
Opens up the EditTextPreference dialog if the user presses the text(or anything else in the preference)
It's probably not of any use but here is a snippet of this particular preferencecategory :
<PreferenceCategory
android:title="#string/category_callforward">
<EditTextPreference
android:key="call_forward_always"
android:title="#string/call_forward_always"
android:summary="#string/call_forward_forwardto" />
</PreferenceCategory>
EDIT
I'd like to implement it in this method if possible:
// Locates the correct data from saved preferences and sets input type to numerics only
private void setCallForwardType()
{
ep1 = (EditTextPreference) findPreference("call_forward_always");
EditText et = (EditText) ep1.getEditText();
et.setKeyListener(DigitsKeyListener.getInstance());
}
EDIT2
If anyone is still wondering - this is what I want as a Preference:
EDIT3
I've searched around for a couple hours now and have come up with a single word: 'PreferenceGroupAdapter'. I have not, however, been able to find examples or tutorials showing me how to use it. Suggestions ? Is this even the correct path to go?
EDIT4
If this really isn't possibly I would very much like a suggestion to an alternative(user-friendly) solution that I can implement instead of the combined Edit- and Checkbox preference.
You can do this. First, create a class for preferences which should be extended from PreferenceActivity. Use like this:
// editbox ise your EditTextPreference, so set it.
checkbox = (CheckBoxPreference) findPreference("checkbox_preference");
checkbox.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
if(newValue.toString().equals("false")) {
PrefActivity.this.editbox.setEnabled(false);
} else if(newValue.toString().equals("true")) {
PrefActivity.this.editbox.setEnabled(true);
}
return true;
}
});
I hope it helps.
A bit late but I think I've managed to create something similar with a dialog that creates a layout with an edit text and a checkbox, it should be possible to do the same in a normal layout:
public class CheckEditTextPreference extends DialogPreference {
private static final String KEY_PROPERTY_DISABLED = "key_property_disabled";
private EditText editText;
private CheckBox checkBox;
private String text;
private boolean isDisabled;
private SharedPreferences mySharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext());
public CheckEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected View onCreateDialogView() {
return buildUi();
}
/**
* Build a dialog using an EditText and a CheckBox
*/
private View buildUi() {
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(25, 0, 0, 0);
LinearLayout linearLayout = new LinearLayout(getContext());
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout.setLayoutParams(layoutParams);
checkBox = new CheckBox(getContext());
editText = new EditText(getContext());
editText.setLayoutParams(layoutParams);
checkBox.setLayoutParams(layoutParams);
checkBox.setText("Disabled");
FrameLayout dialogView = new FrameLayout(getContext());
linearLayout.addView(editText);
linearLayout.addView(checkBox);
dialogView.addView(linearLayout);
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
editText.setEnabled(!isChecked);
}
});
return dialogView;
}
#Override
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
checkBox.setChecked(isDisabled());
editText.setText(getText());
}
#Override
protected void onDialogClosed(boolean positiveResult) {
if (positiveResult) {
String text = editText.getText().toString();
boolean isChecked = checkBox.isChecked();
if (callChangeListener(text)) {
setText(text);
}
if (callChangeListener(isChecked)) {
isDisabled(isChecked);
}
}
}
#Override
protected Object onGetDefaultValue(TypedArray a, int index) {
return a.getString(index);
}
#Override
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
setText(restorePersistedValue ? getPersistedString("") : defaultValue.toString());
isDisabled(mySharedPreferences.getBoolean(KEY_PROPERTY_DISABLED, true));
}
public void setText(String value) {
this.text = value;
persistString(this.text);
}
public String getText() {
return this.text;
}
private void isDisabled(boolean value) {
this.isDisabled = value;
mySharedPreferences.edit().putBoolean(KEY_PROPERTY_DISABLED, this.isDisabled).apply();
}
public boolean isDisabled() {
return this.isDisabled;
}
}
And put this into your preferences screen:
<your.package.name.CheckEditTextPreference
android:key="chkEtPref"
android:title="Title"/>
Define a key in res/values/strings.xml for your CheckBoxPreference.
Give your CheckBoxPreference the XML attribute android:key="#string/THE_KEY_YOU_DEFINED" so that it will automatically save state in SharedPreferences.
Give your EditTextPreference the XML attribute android:dependency="#string/THE_KEY_YOU_DEFINED.
The EditTextPreference should then enable / disable depending on the state of the CheckBoxPreference.

Categories

Resources