73

hereと記載されているように、私はPreferenceFragmentをサブクラス化してActivity内に表示しています。このドキュメントでは、PreferenceActivityをサブクラス化した場合にのみ、優先度変更hereをリッスンする方法について説明します。私はそれをやっていないので、どのように嗜好の変化を聞くのですか?PreferenceFragment内の環境設定変更をリッスンするにはどうすればよいですか?

私のPreferenceFragmentにOnSharedPreferenceChangeListenerを実装しようとしましたが、動作していないようです(onSharedPreferenceChangedは呼び出されないようです)。

これは、これまでの私のコードです:

SettingsActivity.java

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

     // Display the fragment as the main content. 
     getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit(); 
    } 
} 

SettingsFragment.java

public class SettingsFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener 
{ 
    public static final String KEY_PREF_EXERCISES = "pref_number_of_exercises"; 

    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 

     // Load the preferences from an XML resource 
     addPreferencesFromResource(R.xml.preferences); 
    } 

    @Override 
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) 
    { 
     //IT NEVER GETS IN HERE! 
     if (key.equals(KEY_PREF_EXERCISES)) 
     { 
      // Set summary to be the user-description for the selected value 
      Preference exercisesPref = findPreference(key); 
      exercisesPref.setSummary(sharedPreferences.getString(key, "")); 
     } 
    } 
} 

あるpreferences.xml

<?xml version="1.0" encoding="utf-8"?> 
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" > 

    <EditTextPreference 
     android:defaultValue="15" 
     android:enabled="true" 
     android:key="pref_number_of_exercises" 
     android:numeric="integer" 
     android:title="Number of exercises" /> 

</PreferenceScreen> 

また、PreferenceFragmentは環境設定の変更を待機する適切な場所でも、アクティビティ内で行う必要がありますか?

+1

あなたの最後の質問は、デザインフレームワークによって異なります。 MVCまたはMVPアプローチを使用するには、Androidで行うのは難しいですが、私はすべてのアクションを、そのフラグメントをホストしているアクティビティ(コントローラ)で行い、フラグメントはUIのみにします(ビュー/プレゼンター) –

答えて

131

PreferenceFragmentListenerを登録/登録解除するだけでいいと思います。

@Override 
public void onResume() { 
    super.onResume(); 
    getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); 

} 

@Override 
public void onPause() { 
    getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); 
    super.onPause(); 
} 

リスナーを使用する必要がない場合があります。環境設定の変更は自動的にSharedPreferencesにコミットされます。

import android.app.Activity; 
import android.content.SharedPreferences; 
import android.content.SharedPreferences.OnSharedPreferenceChangeListener; 
import android.os.Bundle; 
import android.preference.ListPreference; 
import android.preference.PreferenceFragment; 

public class UserPreferencesV11 extends Activity { 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    // Display the fragment as the main content. 
    getFragmentManager().beginTransaction().replace(android.R.id.content, 
      new PrefsFragment()).commit(); 
} 

public static class PrefsFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     // Load the preferences from an XML resource 
     addPreferencesFromResource(R.xml.preferences); 

     // set texts correctly 
     onSharedPreferenceChanged(null, ""); 

    } 

    @Override 
    public void onResume() { 
     super.onResume(); 
     // Set up a listener whenever a key changes 
     getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); 
    } 

    @Override 
    public void onPause() { 
     super.onPause(); 
     // Set up a listener whenever a key changes 
     getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); 
    } 

    @Override 
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { 
     // just update all 
     ListPreference lp = (ListPreference) findPreference(PREF_YOUR_KEY); 
     lp.setSummary("dummy"); // required or will not update 
     lp.setSummary(getString(R.string.pref_yourKey) + ": %s"); 

    } 
} 
} 
+0

Ah、私見る。それは動作します。しかし、 'getPreferenceManager'(やったように)や' getPreferenceScreen'を使ってSharedPreferencesを取得する必要がありますか?違いは何ですか? –

+0

正直言って私は本当の違いは何か、おそらく他の誰かがそれに重きを置くかもしれない、それは別の質問のための良い話題かもしれません。 – antew

+2

さて、[ここ](http://stackoverflow.com/q/13618335/963396)はその質問に対する答えです。機能上の違いはまったくないようですが、一般的に 'getPreferenceManager'が優先されます。 –

21

antewのソリューションは、ここにあなたが以降のAndroid V11のための完全な好みの活動を見ることができます適しています。しかし、あなたがすぐに変更を引き起こしたPreferenceインスタンスを持っているので、私はこの代替案が気に入っています。あなたは全体像を見るよう

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    Preference pref = findPreference(getString(R.string.key_of_pref));   
    pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { 
     @Override 
     public boolean onPreferenceChange(Preference preference, Object newValue) { 
      // do whatever you want with new value 

      // true to update the state of the Preference with the new value 
      // in case you want to disallow the change return false 
      return true; 
     } 
    }); 
} 
12

他のすべての答えが正しい:

+0

'onSharedPreferenceChanged()'では 'findPreference(key)'で簡単にPreferenceインスタンスにアクセスできますが、正しいです。おそらく 'SharedPreferences'方法は、登録/登録解除のために好まれますか? –

2

これはPreferenceFragment.onCreate()

OnSharedPreferenceChangeListener listener = 
    new SharedPreferences.OnSharedPreferenceChangeListener() 
    { 
     public void onSharedPreferenceChanged(SharedPreferences prefs, String key) 
     { 
     showDialog(); 
     } 
    }; 
0

から私のために別の完全な例を働きました。

public class SettingsActivity extends AppCompatPreferenceActivity { 


    /** 
    * A preference value change listener that updates the preference's summary 
    * to reflect its new value. 
    */ 
    private static Preference.OnPreferenceChangeListener 
      sBindPreferenceSummaryToValueListener = 
      new Preference.OnPreferenceChangeListener() { 

       @Override 
       public boolean onPreferenceChange(Preference preference, Object value) { 
        String stringValue = value.toString(); 

        if (preference instanceof ListPreference) { 
         // For list preferences, look up the correct display value in 
         // the preference's 'entries' list. 
         ListPreference listPreference = (ListPreference) preference; 
         int index = listPreference.findIndexOfValue(stringValue); 

         // Set the summary to reflect the new value. 
         preference.setSummary(
           index >= 0 
             ? listPreference.getEntries()[index] 
             : null); 

        } else if (preference instanceof RingtonePreference) { 
         // For ringtone preferences, look up the correct display value 
         // using RingtoneManager. 
         if (TextUtils.isEmpty(stringValue)) { 
          // Empty values correspond to 'silent' (no ringtone). 
          preference.setSummary(R.string.pref_ringtone_silent); 
         } else { 
          Ringtone ringtone = RingtoneManager.getRingtone(
            preference.getContext(), Uri.parse(stringValue)); 
          if (ringtone == null) { 
           // Clear the summary if there was a lookup error. 
           preference.setSummary(null); 
          } else { 
           // Set the summary to reflect the new ringtone display 
           // name. 
           String name = ringtone.getTitle(preference.getContext()); 
           preference.setSummary(name); 
          } 
         } 

        } else { 
         // For all other preferences, set the summary to the value's 
         // simple string representation. 
         preference.setSummary(stringValue); 
        } 
        return true; 
       } 
      }; 

    /** 
    * Helper method to determine if the device has an extra-large screen. For 
    * example, 10" tablets are extra-large. 
    */ 
    private static boolean isXLargeTablet(Context context) { 
     return (context.getResources().getConfiguration().screenLayout 
       & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE; 
    } 

    /** 
    * Binds a preference's summary to its value. More specifically, when the 
    * preference's value is changed, its summary (line of text below the 
    * preference title) is updated to reflect the value. The summary is also 
    * immediately updated upon calling this method. The exact display format is 
    * dependent on the type of preference. 
    * 
    * @see #sBindPreferenceSummaryToValueListener 
    */ 
    private static void bindPreferenceSummaryToValue(Preference preference) { 
     // Set the listener to watch for value changes. 
     preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener); 

     // Trigger the listener immediately with the preference's current value. 
     sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, 
       PreferenceManager 
         .getDefaultSharedPreferences(preference.getContext()) 
         .getString(preference.getKey(), "")); 
    } 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setupActionBar(); 
    } 

    /** 
    * Set up the {@link android.app.ActionBar}, if the API is available. 
    */ 
    private void setupActionBar() { 
     ActionBar actionBar = getSupportActionBar(); 
     if (actionBar != null) { 
      // Show the Up button in the action bar. 
      actionBar.setDisplayHomeAsUpEnabled(true); 
     } 
    } 

    @Override 
    public boolean onMenuItemSelected(int featureId, MenuItem item) { 
     int id = item.getItemId(); 
     if (id == android.R.id.home) { 
      if (!super.onMenuItemSelected(featureId, item)) { 
       NavUtils.navigateUpFromSameTask(this); 
      } 
      return true; 
     } 
     return super.onMenuItemSelected(featureId, item); 
    } 

    /** 
    * {@inheritDoc} 
    */ 
    @Override 
    public boolean onIsMultiPane() { 
     return isXLargeTablet(this); 
    } 

    /** 
    * {@inheritDoc} 
    */ 
    @Override 
    @TargetApi(Build.VERSION_CODES.HONEYCOMB) 
    public void onBuildHeaders(List<Header> target) { 
     loadHeadersFromResource(R.xml.pref_headers, target); 
    } 

    /** 
    * This method stops fragment injection in malicious applications. 
    * Make sure to deny any unknown fragments here. 
    */ 
    protected boolean isValidFragment(String fragmentName) { 
     return PreferenceFragment.class.getName().equals(fragmentName) 
       || GPSLocationPreferenceFragment.class.getName().equals(fragmentName) 
       || DataSyncPreferenceFragment.class.getName().equals(fragmentName) 
       || NotificationPreferenceFragment.class.getName().equals(fragmentName); 
    } 

    ////////////////// NEW PREFERENCES //////////////////////////// 

    @TargetApi(Build.VERSION_CODES.HONEYCOMB) 
    public static class GPSLocationPreferenceFragment extends PreferenceFragment { 

     Preference prefGPSServerAddr, prefGPSASDID, prefIsGPSSwitch; 

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

      // Bind the summaries of EditText/List/Dialog/Ringtone preferences 
      // to their values. When their values change, their summaries are 
      // updated to reflect the new value, per the Android Design 
      // guidelines. 

      bindPreferenceSummaryToValue(findPreference("gpsServer_Addr")); 
      bindPreferenceSummaryToValue(findPreference("gpsASD_ID")); 


      prefGPSServerAddr = findPreference("gpsServer_Addr"); 
      prefGPSServerAddr.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { 
       @Override 
       public boolean onPreferenceChange(Preference preference, Object newValue) { 

        try { 
         // do whatever you want with new value 

        } 
        catch (Exception ex) 
        { 
         Log.e("Preferences", ex.getMessage()); 
        } 

        // true to update the state of the Preference with the new value 
        // in case you want to disallow the change return false 
        return true; 
       } 
      }); 

      prefGPSASDID = findPreference("gpsASD_ID"); 
      prefGPSASDID.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { 
       @Override 
       public boolean onPreferenceChange(Preference preference, Object newValue) { 

        try { 
         // do whatever you want with new value 

        } 
        catch (Exception ex) 
        { 
         Log.e("Preferences", ex.getMessage()); 
        } 

        // true to update the state of the Preference with the new value 
        // in case you want to disallow the change return false 
        return true; 
       } 
      }); 

      prefIsGPSSwitch = findPreference("isGPS_Switch"); 
      prefIsGPSSwitch.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { 
       @Override 
       public boolean onPreferenceChange(Preference preference, Object newValue) { 

        try { 
         // do whatever you want with new value 

        } 
        catch (Exception ex) 
        { 
         Log.e("Preferences", ex.getMessage()); 
        } 

        // true to update the state of the Preference with the new value 
        // in case you want to disallow the change return false 
        return true; 
       } 
      }); 
     } 

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

    /////////////////////////////////////////////////////////////// 

    /** 
    * This fragment shows notification preferences only. It is used when the 
    * activity is showing a two-pane settings UI. 
    */ 
    @TargetApi(Build.VERSION_CODES.HONEYCOMB) 
    public static class NotificationPreferenceFragment extends PreferenceFragment { 
     @Override 
     public void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 
      addPreferencesFromResource(R.xml.pref_notification); 
      setHasOptionsMenu(true); 

      // Bind the summaries of EditText/List/Dialog/Ringtone preferences 
      // to their values. When their values change, their summaries are 
      // updated to reflect the new value, per the Android Design 
      // guidelines. 
      bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone")); 
     } 

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

    /** 
    * 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 DataSyncPreferenceFragment extends PreferenceFragment { 
     @Override 
     public void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 
      addPreferencesFromResource(R.xml.pref_data_sync); 
      setHasOptionsMenu(true); 

      // Bind the summaries of EditText/List/Dialog/Ringtone preferences 
      // to their values. When their values change, their summaries are 
      // updated to reflect the new value, per the Android Design 
      // guidelines. 
      bindPreferenceSummaryToValue(findPreference("sync_frequency")); 
     } 

     @Override 
     public boolean onOptionsItemSelected(MenuItem item) { 
      int id = item.getItemId(); 
      if (id == android.R.id.home) { 
       boolean tabletSize = getResources().getBoolean(R.bool.isTablet); 
       if (tabletSize) { 
        startActivity(new Intent(getActivity(), MainActivity.class)); 
       } else { 
        startActivity(new Intent(getActivity(), SettingsActivity.class)); 
       } 
       return true; 
      } 
      return super.onOptionsItemSelected(item); 
     } 
    } 
} 
関連する問題