2011-06-24 16 views
21

Mam aktywność preferencji, która ma language jako ListPreference, która wyświetla listę dostępnych języków. Mogę wypełnić listę po wywołaniu metody onCreate, ale chcę ją wypełnić, gdy użytkownik ją kliknie.Jak dynamicznie wypełniać ListPreference po uruchomieniu onPreferenceClick?

this is the java code:

public class SettingsActivity extends PreferenceActivity implements OnPreferenceClickListener { 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     try { 
      addPreferencesFromResource(R.xml.settings); 
     } catch (Exception e) { 

     } 

    } 

    @Override 
    public boolean onPreferenceClick(Preference preference) { 

     if((preference instanceof ListPreference) && (preference.getKey().equals("language"))){ 
      ListPreference lp = (ListPreference)preference; 
      CharSequence[] entries = { "English", "French" }; 
      CharSequence[] entryValues = {"1" , "2"}; 
      lp.setEntries(entries); 
      lp.setDefaultValue("1"); 
      lp.setEntryValues(entryValues); 
      return true; 
     } 
     return false; 

    } 
} 

i to jest settings.xml (preferencji):

<?xml version="1.0" encoding="utf-8"?> 
<PreferenceScreen 
    xmlns:android="http://schemas.android.com/apk/res/android"> 
    <PreferenceCategory android:title="General Settings"> 
     <CheckBoxPreference android:key="enabled" android:title="Application Status" android:summary="Enable or disable the application" /> 
     <ListPreference 
     android:key="language" 
     android:title="Language" 
     android:dialogTitle="Application language" 
     android:summary="Select the Application language" 
     /> 
    </PreferenceCategory> 
</PreferenceScreen> 

Szukałem ale nie znaleziono wyników! Wyjątek występuje za każdym razem, gdy kliknę tę listę.

Odpowiedz

36

Otrzymujesz wyjątek, ponieważ obiekt ListPreference nie jest w pełni zainicjowany - albo trzeba ustawić entries i entryValues atrybutów w formacie XML lub zrobić to programowo w onCreate().

Jeśli chcesz, aby móc dynamicznie zmieniać pozycje na liście po zainicjowaniu początkowego obiektu ListPreference, musisz dołączyć OnPreferenceClickListener bezpośrednio do obiektu ListPreference. Użyj klucza podanego w pliku XML, aby uzyskać uchwyt do preferencji.

Ponieważ kod, aby wypełnić entries i entryValues tablice będą musiały działać zarówno w onCreate() i onPreferenceClick, ma sens, aby wyodrębnić go do oddzielnej metody - setListPreferenceData() w celu uniknięcia powielania działań.

public class SettingsActivity extends PreferenceActivity { 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     try { 
      addPreferencesFromResource(R.xml.settings); 
     } catch (Exception e) { 

     } 

     final ListPreference listPreference = (ListPreference) findPreference("language"); 

     // THIS IS REQUIRED IF YOU DON'T HAVE 'entries' and 'entryValues' in your XML 
     setListPreferenceData(listPreference); 

     listPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() { 
      @Override 
      public boolean onPreferenceClick(Preference preference) { 

       setListPreferenceData(listPreference); 
       return false; 
      } 
     }); 
    } 

    protected static void setListPreferenceData(ListPreference lp) { 
      CharSequence[] entries = { "English", "French" }; 
      CharSequence[] entryValues = {"1" , "2"}; 
      lp.setEntries(entries); 
      lp.setDefaultValue("1"); 
      lp.setEntryValues(entryValues); 
    } 
} 
+2

Ta odpowiedź działa, ale jest trochę błędna, jeśli zezwalasz na uruchomienie setListPreferenceData tylko onClick (a nie onCReate). To jest , ponieważ jeśli metoda setListPreferenceData zajmuje więcej niż ułamek sekundy , to przed ustawieniem danych wyświetlana jest domyślna lista, a użytkownik jest zmuszony anulować, a następnie ponownie otworzyć preferencję. Czy istnieje sposób aktualizacji listyPreferencji, która jest już wyświetlana po zakończeniu ustawiania setListPreferenceData? – Malabarba

+3

Jeśli potrzebujesz niestandardowego zachowania, najlepszym rozwiązaniem byłoby rozszerzenie 'ListPreference' lub' Preference'. Rozwiązaniem czysto "społecznym" byłoby ustawienie domyślnej wartości pozycji listy na coś w rodzaju ccpizza

+1

Tak, musiałem sam rozszerzyć listę. Ale nie było tak źle. onCreate była jedyną metodą, która wymagała przeciążenia. – Malabarba

2

Korzystanie PreferenceFragment & JAVA zestawem kluczy zamiast PreferenceActivity & XML jak pokazano na https://stackoverflow.com/a/13828912/1815624, która to odpowiedź jest oparta na:

Jeśli to, co chcesz, jest móc dynamicznie zmieniać elementy na liście po inicjalizacji początkowego obiektu ListPreference, wtedy należy dołączyć OnPreferenceClickListener bezpośrednio do obiektu ListPreference. Użyj klucza, który masz określony w źródle JAVA (jako CUSTOM_LIST), aby uzyskać uchwyt do tej preferencji.

Ponieważ kod, aby wypełnić entries i entryValues tablice będą musiały działać zarówno w onCreate() i onPreferenceClick, ma sens, aby wyodrębnić go do oddzielnej metody - setListPreferenceData() w celu uniknięcia powielania działań.

/** 
* This fragment shows data and sync preferences only. It is used when the 
* activity is showing a two-pane settings UI. 
*/ 
@TargetApi(Build.VERSION_CODES.HONEYCOMB) 
public static class myCustomPreferenceFragment extends PreferenceFragment { 

    final private String CUSTOM_LIST= "custom_list"; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     addPreferencesFromResource(R.xml.pref_custom_frag); 

     PreferenceCategory targetCategory = (PreferenceCategory) findPreference("CUSTOM_FRAG"); 

     final ListPreference lp = setListPreferenceData((ListPreference) findPreference(CUSTOM_LIST), getActivity()); 

     lp.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { 
      @Override 
      public boolean onPreferenceClick(Preference preference) { 

       setListPreferenceData(lp, getActivity()); 
       return false; 
      } 
     }); 
     setHasOptionsMenu(true); 
     targetCategory.addPreference(lp); 

     bindPreferenceSummaryToValue(targetCategory); 
     bindPreferenceSummaryToValue(lp); 
    } 

    protected ListPreference setListPreferenceData(ListPreference lp, Activity mActivity) { 
     CharSequence[] entries = { "One", "Two", "Three" }; 
     CharSequence[] entryValues = { "1", "2", "3" }; 
     if(lp == null) 
      lp = new ListPreference(mActivity); 
     lp.setEntries(entries); 
     lp.setDefaultValue("1"); 
     lp.setEntryValues(entryValues); 
     lp.setTitle("Number Of blahs"); 
     lp.setSummary(lp.getEntry()); 
     lp.setDialogTitle("Number of Blah objects"); 
     lp.setKey(CUSTOM_LIST); 
     return lp; 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     int id = item.getItemId(); 
     if (id == android.R.id.home) { 
      startActivity(new Intent(getActivity(), SettingsActivity.class)); 
      return true; 
     } 
     return super.onOptionsItemSelected(item); 
    } 
} 

układ XML:

<?xml version="1.0" encoding="utf-8"?> 
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> 
    <PreferenceCategory 
     android:key="CUSTOM_FRAG" 
     android:title="Some Options"> 

    </PreferenceCategory> 
</PreferenceScreen> 
0

I rozwiązać problem mój przedłużające ListPreference. To było bardzo proste.

public class DListPref extends ListPreference 
{ 
    public interface LoadingListener 
    { 
     void setData(ListPreference lp); 
    } 

    LoadingListener TheLL; 

    public void setLoadingListener(LoadingListener l) 
    { 
     TheLL = l; 
    } 

    @Override 
    protected void onPrepareDialogBuilder(AlertDialog.Builder builder) 
    { 
     if(TheLL!=null) 
     { 
      TheLL.setData(this); 
     } 
     super.onPrepareDialogBuilder(builder); 
    } 

    //Do not mind the rest of this class, as they are auto-generated boilerplate code. 
    public DListPref(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) 
    { 
     super(context, attrs, defStyleAttr, defStyleRes); 
    } 

    public DListPref(Context context, AttributeSet attrs, int defStyleAttr) 
    { 
     super(context, attrs, defStyleAttr); 
    } 

    public DListPref(Context context, AttributeSet attrs) 
    { 
     super(context, attrs); 
    } 

    public DListPref(Context context) 
    { 
     super(context); 
    } 
} 

Potem zmieniłem nazwę na moją klasę w XML.

<my.company.DListPref 
    android:defaultValue="-1" 
    android:key="damn" 
    android:title="vegetables"/> 

A potem po prostu zrobiłem to w OnCreate.

Pracował od razu. Właściwie nigdy nie spodziewałem się, że tak łatwo będzie to zrobić.

Powiązane problemy