I am following this tutorial. In that the PreferenceActivity is used to create Settings. However it was mentioned that I can use Fragments if I like, so I went ahead and used PreferenceFrament in a normal activity. But when I ran the app, it crashed giving the following log -
07-25 10:41:02.048 7515-7515/com.example.sunshine E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.sunshine/com.example.sunshine.SettingsActivity}: java.lang.RuntimeException: Content has view with id attribute 'android.R.id.list' that is not a ListView class
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2063)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2088)
at android.app.ActivityThread.access$600(ActivityThread.java:134)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1199)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4744)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: Content has view with id attribute 'android.R.id.list' that is not a ListView class
at android.preference.PreferenceFragment.ensureList(PreferenceFragment.java:350)
at android.preference.PreferenceFragment.getListView(PreferenceFragment.java:336)
at android.preference.PreferenceFragment.bindPreferences(PreferenceFragment.java:330)
at android.preference.PreferenceFragment.onActivityCreated(PreferenceFragment.java:171)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:852)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1039)
at android.app.BackStackRecord.run(BackStackRecord.java:635)
at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1411)
at android.app.Activity.performStart(Activity.java:5017)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2036)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2088)
at android.app.ActivityThread.access$600(ActivityThread.java:134)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1199)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4744)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
When I searched on SO, I came to know the crash is somewhat related to ListFragment. But I am sure I did not use it in my app. PreferenceFragment might have called it though. I cannot pinpoint the problem here. Can you help me to solve it?
Here's the preference xml I am using -
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<EditTextPreference
android:title="@string/pref_location_label"
android:key="@string/pref_location_key"
android:defaultValue="@string/pref_location_default"
android:inputType="text"
android:singleLine="true"
/>
</PreferenceScreen>
And here's the SettingsActivity, along with Fragment -
public class SettingsActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new SettingsFragment())
.commit();
}
}
public static class SettingsFragment extends PreferenceFragment implements Preference.OnPreferenceChangeListener {
public SettingsFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Add 'general' preferences, defined in the XML file
addPreferencesFromResource(R.xml.pref_general);
// For all preferences, attach an OnPreferenceChangeListener so the UI summary can be
// updated when the preference changes.
bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_location_key)));
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_settings, container, false);
return rootView;
}
/**
* Attaches a listener so the summary is always updated with the preference value.
* Also fires the listener once, to initialize the summary (so it shows up before the value
* is changed.)
*/
private void bindPreferenceSummaryToValue(Preference preference) {
// Set the listener to watch for value changes.
preference.setOnPreferenceChangeListener(this);
// Trigger the listener immediately with the preference's
// current value.
onPreferenceChange(preference,
PreferenceManager
.getDefaultSharedPreferences(preference.getContext())
.getString(preference.getKey(), ""));
}
@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 (since they have separate labels/values).
ListPreference listPreference = (ListPreference) preference;
int prefIndex = listPreference.findIndexOfValue(stringValue);
if (prefIndex >= 0) {
preference.setSummary(listPreference.getEntries()[prefIndex]);
}
} else {
// For other preferences, set the summary to the value's simple string representation.
preference.setSummary(stringValue);
}
return true;
}
}
}
Is there anything else I need to change to make it work for Fragments instead of Activity?
Finally found it. I just needed to put a ListView with android:id="@id/android:list"
attribute in my fragment's xml. Although I dunno why I do need it, just found it by trial and error.
Some more info in addition to the solution by noob. In case someone is wondering as to why adding WORKS, it's because in the (source code) preference fragment--> bindpreferences(), it actually tries to find a listview in the current view (using android.r.id.list) and if the resulting view is not a listview it throws the above exception. This list is mandatory for displaying the preferences.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With