无法让 PreferenceFragmentCompat 工作
Can't get PreferenceFragmentCompat to work
我正在尝试创建一个 Activity 扩展 AppCompatActivity 并在其中包含两个片段(一个在另一个下面 - 只需使用 LinearLayout)。我想要第一个片段从 support-v7 库扩展 PreferenceFragmentCompat class。
我遵循了 Google 关于 PreferenceFragmentCompat 的简短示例,如 https://developer.android.com/reference/android/support/v7/preference/PreferenceFragmentCompat.html 所示。
这是我当前的代码:
GroupDetailsActivity.java
public class GroupDetailsActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_group_details);
GroupDetailsPrefFragment prefFragment = GroupDetailsPrefFragment.newInstance();
GroupDetailsMembersFragment membersFragment = GroupDetailsMembersFragment.newInstance();
FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction()
.add(R.id.flPrefFragment, prefFragment, GroupDetailsPrefFragment.TAG)
.add(R.id.flMembersFragment, membersFragment, GroupDetailsMembersFragment.TAG)
.commit();
}
}
GroupDetailsPrefFragment .java - 有问题的片段
public class GroupDetailsPrefFragment extends PreferenceFragmentCompat {
public static final String TAG = "GroupDetailsPrefFragment";
@Override
public void onCreatePreferences(Bundle bundle, String s) {
setPreferencesFromResource(R.xml.group_details_preferences, s);
}
public static GroupDetailsPrefFragment newInstance() {
GroupDetailsPrefFragment fragment = new GroupDetailsPrefFragment();
return fragment;
}
}
GroupDetailsMembersFragment.java - 现在完全是空的..
public class GroupDetailsMembersFragment extends Fragment {
public static final String TAG = "GroupDetailsMembersFragment";
public static GroupDetailsMembersFragment newInstance() {
GroupDetailsMembersFragment fragment = new GroupDetailsMembersFragment();
return fragment;
}
}
activity_group_details.xml - Activity的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/flPrefFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<FrameLayout
android:id="@+id/flMembersFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
group_details_preferences.xml - 首选项XML 文件
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<Preference
android:title="@string/remove_me"
android:key="@string/pref_key_settings_remove_me"/>
<Preference
android:title="@string/delete_group"
android:key="@string/pref_key_settings_delete_group"/>
</PreferenceScreen>
尝试编译和 运行 上面的代码导致我遇到一些错误,第一个错误是关于未设置的首选项主题。我快速浏览了互联网,发现您需要将以下行添加到 Activity 的主题中:<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
为此,我需要将 support-v14 库添加到 gradle!
再次尝试 运行 代码,导致我出现另一个错误,这就是我发布此消息的原因,到目前为止我还没有找到解决此问题的任何方法。这是崩溃日志:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.cochat.android/com.cochat.android.ui.groups.details.GroupDetailsActivity}: java.lang.RuntimeException: Content has view with id attribute 'android.R.id.list_container' that is not a ViewGroup class
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2305)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2363)
at android.app.ActivityThread.access0(ActivityThread.java:161)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1265)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: Content has view with id attribute 'android.R.id.list_container' that is not a ViewGroup class
at android.support.v7.preference.PreferenceFragmentCompat.onCreateView(PreferenceFragmentCompat.java:269)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2184)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1298)
at android.support.v4.app.FragmentManagerImpl.moveFragmentsToInvisible(FragmentManager.java:2323)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2136)
at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2092)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1998)
at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:388)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:607)
at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:181)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1189)
at android.app.Activity.performStart(Activity.java:5441)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2363)
at android.app.ActivityThread.access0(ActivityThread.java:161)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1265)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
在这上面停留了一段时间,尝试在 Whosebug 或其他网站上查找不同的帖子,看到了一些解决方案,但出于某种原因 none 他们设法解决了我的问题。
编辑:
我的 gradle 文件包含以下内容:
compileSdkVersion 25
buildToolsVersion '25.0.2'
...
compile 'com.android.support:preference-v7:25.1.0'
compile 'com.android.support:preference-v14:25.1.0'
2017 年 1 月 2 日更新
我一直在查看 PreferenceFragmentCompat
的源代码,发现它正在尝试加载以下布局:R.layout.preference_list_fragment
。
在 class 的 onCreateView()
方法中,它正在膨胀布局,并试图寻找 id android.R.id.list_container
。
问题是布局中没有这样的id。
这是来自 PreferenceFragmentCompat
的代码片段:
final View view = themedInflater.inflate(mLayoutResId, container, false);
final View rawListContainer = view.findViewById(AndroidResources.ANDROID_R_LIST_CONTAINER);
if (!(rawListContainer instanceof ViewGroup)) {
throw new RuntimeException("Content has view with id attribute "
+ "'android.R.id.list_container' that is not a ViewGroup class");
}
同时
private int mLayoutResId = R.layout.preference_list_fragment;
仍在寻找解决方案,谢谢!
据此article:
Note that Google changed the needed id from R.id.list_container (in
revision 23.4.0) to android.R.id.list_container (in revision 24.0.0).
Android Studio says the new id requires API 24, but it also works on
older APIs.
布局文件 (activity_group_details.xml) 中的 ViewGroup 的 ID 应该是“@android:id/list_container”。这样才能正常工作。它看起来像这样:
<FrameLayout
android:id="@android:id/list_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<FrameLayout
android:id="@+id/flMembersFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
并且您也必须将此 ID 用于您的交易,请注意您的其他片段可以将任何 ID 用于容器,只有 pref 是 'special'
所以我找到了解决这个问题的方法,可能不是最好的,但这是我唯一设法开始工作的方法!似乎是 problem/bug 与支持库..
我已经将原来的PreferenceFragmentCompat
复制到本地class,并做了一些小改动。我已经替换了以下行
private int mLayoutResId = android.support.v7.preference.R.layout.preference_list_fragment;
和
private int mLayoutResId = R.layout.preference_fragment_compat_container;
这是我制作的布局,非常简单,只包含一个列表容器。这是布局代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/list_container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
执行上述操作后,您可以毫无问题地使用具有上述特定 gradle 设置的 PreferenceFragmentCompat
(请参阅原始 post)。
缺点是升级支持库不会升级您的 PreferenceFragmentCompat
,因为它当然是复制的。您将需要跟踪支持库,当问题得到解决时,您可以删除复制的 class 并使用原始的。
如果您有任何其他解决方案或想法,请分享!
我通过以下错误修复解决了这个问题:
https://github.com/Gericop/Android-Support-Preference-V7-Fix
简单的 3 步过程就是更新应用的 build.gradle,
删除:
compile 'com.android.support:preference-v7:25.0.1'
compile 'com.android.support:preference-v14:25.0.1'
添加
compile 'com.takisoft.fix:preference-v7:25.0.1.0'
然后更新您应用的主题以使用 PreferenceFixTheme
(您已经在使用 PreferenceFragmentCompat
太好了)。
更新:
在进一步调查中,使用 api 25.1.0,一旦我意识到对首选项样式的非常严格的限制,AppCompat 就可以正常工作。
我发现 this resource 非常有助于很好地设置所有内容:
我认为您只需要使用支持的 PreferenceScreen 和 Preferences:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<android.support.v7.preference.Preference
android:title="@string/remove_me"
android:key="@string/pref_key_settings_remove_me"/>
<android.support.v7.preference.Preference
android:title="@string/delete_group"
android:key="@string/pref_key_settings_delete_group"/>
</android.support.v7.preference.PreferenceScreen>
将此行添加到 styles.xml 文件中的 AppTheme 应该可以解决问题:
<item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
在这里查看我的回答
您需要具有该 ID 的布局资源
我正在尝试创建一个 Activity 扩展 AppCompatActivity 并在其中包含两个片段(一个在另一个下面 - 只需使用 LinearLayout)。我想要第一个片段从 support-v7 库扩展 PreferenceFragmentCompat class。
我遵循了 Google 关于 PreferenceFragmentCompat 的简短示例,如 https://developer.android.com/reference/android/support/v7/preference/PreferenceFragmentCompat.html 所示。
这是我当前的代码:
GroupDetailsActivity.java
public class GroupDetailsActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_group_details);
GroupDetailsPrefFragment prefFragment = GroupDetailsPrefFragment.newInstance();
GroupDetailsMembersFragment membersFragment = GroupDetailsMembersFragment.newInstance();
FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction()
.add(R.id.flPrefFragment, prefFragment, GroupDetailsPrefFragment.TAG)
.add(R.id.flMembersFragment, membersFragment, GroupDetailsMembersFragment.TAG)
.commit();
}
}
GroupDetailsPrefFragment .java - 有问题的片段
public class GroupDetailsPrefFragment extends PreferenceFragmentCompat {
public static final String TAG = "GroupDetailsPrefFragment";
@Override
public void onCreatePreferences(Bundle bundle, String s) {
setPreferencesFromResource(R.xml.group_details_preferences, s);
}
public static GroupDetailsPrefFragment newInstance() {
GroupDetailsPrefFragment fragment = new GroupDetailsPrefFragment();
return fragment;
}
}
GroupDetailsMembersFragment.java - 现在完全是空的..
public class GroupDetailsMembersFragment extends Fragment {
public static final String TAG = "GroupDetailsMembersFragment";
public static GroupDetailsMembersFragment newInstance() {
GroupDetailsMembersFragment fragment = new GroupDetailsMembersFragment();
return fragment;
}
}
activity_group_details.xml - Activity的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/flPrefFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<FrameLayout
android:id="@+id/flMembersFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
group_details_preferences.xml - 首选项XML 文件
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<Preference
android:title="@string/remove_me"
android:key="@string/pref_key_settings_remove_me"/>
<Preference
android:title="@string/delete_group"
android:key="@string/pref_key_settings_delete_group"/>
</PreferenceScreen>
尝试编译和 运行 上面的代码导致我遇到一些错误,第一个错误是关于未设置的首选项主题。我快速浏览了互联网,发现您需要将以下行添加到 Activity 的主题中:<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
为此,我需要将 support-v14 库添加到 gradle!
再次尝试 运行 代码,导致我出现另一个错误,这就是我发布此消息的原因,到目前为止我还没有找到解决此问题的任何方法。这是崩溃日志:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.cochat.android/com.cochat.android.ui.groups.details.GroupDetailsActivity}: java.lang.RuntimeException: Content has view with id attribute 'android.R.id.list_container' that is not a ViewGroup class
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2305)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2363)
at android.app.ActivityThread.access0(ActivityThread.java:161)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1265)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: Content has view with id attribute 'android.R.id.list_container' that is not a ViewGroup class
at android.support.v7.preference.PreferenceFragmentCompat.onCreateView(PreferenceFragmentCompat.java:269)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2184)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1298)
at android.support.v4.app.FragmentManagerImpl.moveFragmentsToInvisible(FragmentManager.java:2323)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2136)
at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2092)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1998)
at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:388)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:607)
at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:181)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1189)
at android.app.Activity.performStart(Activity.java:5441)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2363)
at android.app.ActivityThread.access0(ActivityThread.java:161)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1265)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
在这上面停留了一段时间,尝试在 Whosebug 或其他网站上查找不同的帖子,看到了一些解决方案,但出于某种原因 none 他们设法解决了我的问题。
编辑:
我的 gradle 文件包含以下内容:
compileSdkVersion 25
buildToolsVersion '25.0.2'
...
compile 'com.android.support:preference-v7:25.1.0'
compile 'com.android.support:preference-v14:25.1.0'
2017 年 1 月 2 日更新
我一直在查看 PreferenceFragmentCompat
的源代码,发现它正在尝试加载以下布局:R.layout.preference_list_fragment
。
在 class 的 onCreateView()
方法中,它正在膨胀布局,并试图寻找 id android.R.id.list_container
。
问题是布局中没有这样的id。
这是来自 PreferenceFragmentCompat
的代码片段:
final View view = themedInflater.inflate(mLayoutResId, container, false);
final View rawListContainer = view.findViewById(AndroidResources.ANDROID_R_LIST_CONTAINER);
if (!(rawListContainer instanceof ViewGroup)) {
throw new RuntimeException("Content has view with id attribute "
+ "'android.R.id.list_container' that is not a ViewGroup class");
}
同时
private int mLayoutResId = R.layout.preference_list_fragment;
仍在寻找解决方案,谢谢!
据此article:
Note that Google changed the needed id from R.id.list_container (in revision 23.4.0) to android.R.id.list_container (in revision 24.0.0). Android Studio says the new id requires API 24, but it also works on older APIs.
布局文件 (activity_group_details.xml) 中的 ViewGroup 的 ID 应该是“@android:id/list_container”。这样才能正常工作。它看起来像这样:
<FrameLayout
android:id="@android:id/list_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<FrameLayout
android:id="@+id/flMembersFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
并且您也必须将此 ID 用于您的交易,请注意您的其他片段可以将任何 ID 用于容器,只有 pref 是 'special'
所以我找到了解决这个问题的方法,可能不是最好的,但这是我唯一设法开始工作的方法!似乎是 problem/bug 与支持库..
我已经将原来的PreferenceFragmentCompat
复制到本地class,并做了一些小改动。我已经替换了以下行
private int mLayoutResId = android.support.v7.preference.R.layout.preference_list_fragment;
和
private int mLayoutResId = R.layout.preference_fragment_compat_container;
这是我制作的布局,非常简单,只包含一个列表容器。这是布局代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/list_container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
执行上述操作后,您可以毫无问题地使用具有上述特定 gradle 设置的 PreferenceFragmentCompat
(请参阅原始 post)。
缺点是升级支持库不会升级您的 PreferenceFragmentCompat
,因为它当然是复制的。您将需要跟踪支持库,当问题得到解决时,您可以删除复制的 class 并使用原始的。
如果您有任何其他解决方案或想法,请分享!
我通过以下错误修复解决了这个问题: https://github.com/Gericop/Android-Support-Preference-V7-Fix
简单的 3 步过程就是更新应用的 build.gradle,
删除:
compile 'com.android.support:preference-v7:25.0.1'
compile 'com.android.support:preference-v14:25.0.1'
添加
compile 'com.takisoft.fix:preference-v7:25.0.1.0'
然后更新您应用的主题以使用 PreferenceFixTheme
(您已经在使用 PreferenceFragmentCompat
太好了)。
更新:
在进一步调查中,使用 api 25.1.0,一旦我意识到对首选项样式的非常严格的限制,AppCompat 就可以正常工作。
我发现 this resource 非常有助于很好地设置所有内容:
我认为您只需要使用支持的 PreferenceScreen 和 Preferences:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<android.support.v7.preference.Preference
android:title="@string/remove_me"
android:key="@string/pref_key_settings_remove_me"/>
<android.support.v7.preference.Preference
android:title="@string/delete_group"
android:key="@string/pref_key_settings_delete_group"/>
</android.support.v7.preference.PreferenceScreen>
将此行添加到 styles.xml 文件中的 AppTheme 应该可以解决问题:
<item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
在这里查看我的回答
您需要具有该 ID 的布局资源