user1318160
user1318160

Reputation: 73

EditTextPreference value only refreshed after clicking ListPreference second time

I've been struggling with this issue for a while now so I decided to ask here what I' m doing wrong.

First of all: - I have a PreferenceFragment with a ListPreference on top and an EditTextPreference below - The ListPreference is filled with Objects, the values are stored in a file and read from there (this works flawlessly) - The EditTextPreference should display the value of the in the ListPreference chosen object. And that's the problem: after choosing the value nothing changes so I have to click the ListPreference once more and the value is set correctly. Is this a problem with my Listener?

Here's the code:

public class SettingsTestFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {

    private final String[] pref_key_array = {"pref_key_lp", "pref_key_et""}; // array that contains all the preference keys of changeable values
    private final int numberOfEntries = pref_key_array.length;
    private Preference[] pref_entries;
    String[] entries = {"Value 1", "Value 2", "Value 3"};
    String[] entryValues = {"0", "1", "2"};
    private int position;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.settings);
        final SharedPreferences myPreference = PreferenceManager.getDefaultSharedPreferences(getActivity());

        final EditTextPreference et = (EditTextPreference) findPreference("pref_key_et");
        final ListPreference lp = (ListPreference) findPreference("pref_key_lp");
        prepareListPref(lp);
        pref_entries = new Preference[numberOfEntries];
        for(int i = 0; i < numberOfEntries; i++) {
            pref_entries[i] = getPreferenceScreen().findPreference(pref_key_array[i]);
        }


        lp.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
            @Override
            public boolean onPreferenceClick(Preference preference) {
                position = Integer.valueOf(myPreference.getString("pref_key_lp", "0"));
                et.setText(entries[position]);
                return true;
            }
        });


        Preference.OnPreferenceChangeListener changeListener = new Preference.OnPreferenceChangeListener() {
            public boolean onPreferenceChange(Preference preference, Object newValue) {
                position = Integer.valueOf(myPreference.getString("pref_key_lp", "0"));
                preference.setSummary(entries[position]);
                return true;
            }
        };
         lp.setOnPreferenceChangeListener(changeListener);
    }

    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
       updateSummary(key, pref_key_array, numberOfEntries, pref_entries);
    }


    @Override
    public void onResume() {
        super.onResume();
        // Set up listener when a key changes
        for(int i = 0; i < numberOfEntries; i++) {
            updateSummary(pref_key_array[i], pref_key_array, numberOfEntries, pref_entries);
        }
        getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onPause() {
        super.onPause();
        // Unregister listener every time a key changes
        getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
    }

    public void prepareListPref(ListPreference lp) {
        lp.setEntries(entries);
        lp.setEntryValues(entryValues);
        lp.setDefaultValue("0");
    }

    public void updateSummary(String key, String[] pref_key_array, int numberOfEntries, Preference[] pref_entries) {
        for(int i = 0; i < numberOfEntries; i++) {
            if(key.equals(pref_key_array[i])) {
                if(pref_entries[i] instanceof EditTextPreference) {
                    final EditTextPreference currentPreference = (EditTextPreference) pref_entries[i];
                    pref_entries[i].setSummary(currentPreference.getText());
                } else if(pref_entries[i] instanceof ListPreference) {
                    final ListPreference currentPreference = (ListPreference) pref_entries[i];
                    pref_entries[i].setSummary(currentPreference.getEntry());
                }
                break;
            }
        }
    }
}

Summarizing the code for reading from the file and writing the value to the Settings works but only after clicking the ListPreference a second time. Do you have any ideas why?

Thanks

Upvotes: 2

Views: 663

Answers (1)

android developer
android developer

Reputation: 115972

ok, I'm not sure what you are trying to do and what is the problem, so I've made a sample, showing the next thing:

  1. a listPreference that its default value&entry will set the title&summary of an EditTextPreference .
  2. when choosing an item on the ListPreference, it will also update tge title&summary of the EditTextPreference according to the value&entry of the item being selected.
  3. Not sure what to do with the EditTextPreference. This is your choice.

I still think you should consider making a custom Preference class, as you wrote that you intend to use a lot of couples of ListPreference&EditTextPreference.

BTW, code is based on an app that I've made (link here). I've made it so that it will be easy to handle multiple listPreferences easier.

Here's the code:

res/values/strings_activity_settings.xml

<resources>

    <string name="pref__custom_app_theme" translatable="false">pref__custom_app_theme</string>
    <string name="pref__app_theme" translatable="false">pref__app_theme</string>

    <string-array name="pref__app_theme_entries">
        <item>@string/cards_light</item>
        <item>@string/cards_dark</item>
    </string-array>

    <string name="pref__app_theme__cards_ui" translatable="false">CARDS_UI</string>
    <string name="pref__app_theme__cards_ui_dark" translatable="false">CARDS_UI_DARK</string>
    <string name="pref__app_theme_default" translatable="false">@string/pref__app_theme__cards_ui</string>


    <string-array name="pref__app_theme_values">
        <item>@string/pref__app_theme__cards_ui</item>
        <item>@string/pref__app_theme__cards_ui_dark</item>
    </string-array>
</resources>

res/values/strings.xml

<resources>
    <string name="app_name">My Application</string>

    <string name="app_theme">App Theme</string>
    <string name="cards_light">cards light</string>
    <string name="cards_dark">cards dark</string>
</resources>

res/xml/pref_general.xml

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- theme -->
    <ListPreference
        android:defaultValue="@string/pref__app_theme_default"
        android:entries="@array/pref__app_theme_entries"
        android:entryValues="@array/pref__app_theme_values"
        android:key="@string/pref__app_theme"
        android:title="@string/app_theme"/>

    <EditTextPreference android:key="@string/pref__custom_app_theme"/>
</PreferenceScreen>

SettingsActivity.java

public class SettingsActivity extends PreferenceActivity
  {
  public interface IOnListPreferenceChosenListener
    {
    public void onChosenPreference(String key,String entry,String value);
    }

  @SuppressWarnings("deprecation")
  @Override
  protected void onCreate(Bundle savedInstanceState)
    {
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.pref_general);
    final EditTextPreference editTextPreference=(EditTextPreference)findPreference(getString(R.string.pref__custom_app_theme));
    final ListPreference listPreference=prepareListPreference(this,R.string.pref__app_theme,R.array.pref__app_theme_entries,R.array.pref__app_theme_values,R.string.pref__app_theme_default,new IOnListPreferenceChosenListener()
      {
        @Override
        public void onChosenPreference(final String key,final String entry,final String value)
          {
          editTextPreference.setTitle(value);
          editTextPreference.setSummary(entry);
          }
      });
    editTextPreference.setTitle(listPreference.getValue());
    editTextPreference.setSummary(listPreference.getEntry());
    }

  public static ListPreference prepareListPreference(final PreferenceActivity activity,final int prefKeyId,//
      final int entriesId,final int valuesId,final int defaultValueId,final IOnListPreferenceChosenListener listener)
    {
    final String prefKey=activity.getString(prefKeyId);
    @SuppressWarnings("deprecation")
    final ListPreference pref=(ListPreference)activity.findPreference(prefKey);
    final String[] entries=activity.getResources().getStringArray(entriesId);
    final String[] values=activity.getResources().getStringArray(valuesId);
    final String defaultValue=activity.getResources().getString(defaultValueId);
    final String currentValue=PreferenceManager.getDefaultSharedPreferences(activity).getString(prefKey,defaultValue);
    for(int i=0;i<values.length;++i)
      {
      final String value=values[i];
      if(TextUtils.equals(currentValue,value))
        {
        pref.setSummary(entries[i]);
        pref.setValueIndex(i);
        break;
        }
      }
    pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
      {
        @Override
        public boolean onPreferenceChange(final Preference preference,final Object newValue)
          {
          final String newValueStr=newValue.toString();
          String entryChosen=null;
          for(int i=0;i<values.length;++i)
            {
            final String value=values[i];
            if(TextUtils.equals(newValueStr,value))
              {
              entryChosen=entries[i];
              break;
              }
            }
          pref.setSummary(entryChosen);
          if(listener!=null)
            listener.onChosenPreference(prefKey,entryChosen,newValueStr);
          return true;
          }
      });
    return pref;
    }
  }

Upvotes: 1

Related Questions