android - 如何在 Android 3.0 中为 PreferenceActivity 设置自定义布局?
我正在使用 minSdkVersion="11" 开发应用程序,这是适用于平板电脑和 Android 4.0 及更高版本的应用程序。我已经在互联网上仔细研究过这个主题,但没有发现太多。
要为以前版本的 Android SDK 实现自定义布局,我们只需使用 ListView 创建布局(例如preference.xml),其 id 等于 android.R.id.list 并使用 setContentView 方法。
choice.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>
在 Android 3.0 中,情况发生了变化,首选项是通过使用片段来实现的。这就是我的preference_headers.xml 文件的样子:
<preference-headers
xmlns:android="http://schemas.android.com/apk/res/android">
<header android:fragment="com.example.MyPreferenceActivity$GeneralSettingsFragment"
android:title="General"
android:summary="Common settings." />
<header
android:title="Example.com" >
<intent android:action="android.intent.action.VIEW"
android:data="http://www.example.com" />
</header>
</preference-headers>
MyPreferenceActivity.java:
public class MyPreferenceActivity extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.preference);
// Add a button to the header list.
if (hasHeaders()) {
Button button = new Button(this);
button.setText("Log out");
setListFooter(button);
}
}
/**
* Populate the activity with the top-level headers.
*/
@Override
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.preference_headers, target);
}
public static class GeneralSettingsFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.fragmented_preferences);
}
}
}
现在,如果我运行MyPreferenceActivity,我将在LogCat 中看到此错误:
> java.lang.IllegalArgumentException: No view found for id 0x10202be for
> fragment GeneralSettingsFragment{4077f8c0 #0 id=0x10202be}
> E/AndroidRuntime(17103): at
> android.app.FragmentManagerImpl.moveToState(FragmentManager.java:729)
> E/AndroidRuntime(17103): at
> android.app.FragmentManagerImpl.moveToState(FragmentManager.java:926)
> E/AndroidRuntime(17103): at
> android.app.FragmentManagerImpl.moveToState(FragmentManager.java:909)
> E/AndroidRuntime(17103): at
> android.app.FragmentManagerImpl.dispatchStart(FragmentManager.java:1584)
> E/AndroidRuntime(17103): at
> android.app.Activity.performStart(Activity.java:4377)
> E/AndroidRuntime(17103): at
> android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1724)
> E/AndroidRuntime(17103): ... 11 more
我知道导致此问题的原因。 FragmentManager 只是找不到插入片段 GeneralSettingsFragment 的视图。但我不知道如何解决它。
顺便说一句,如果我在 Android 4.0 上运行相同的应用程序,那么我可以看到第一个带有标题的 Preference Activity。但如果我单击“常规”,应用程序将崩溃,并且我将在 LogCat 中收到类似的错误:
java.lang.IllegalArgumentException: No view found for id 0x10202cd for fragment GeneralSettingsFragment{4134b4e0 #0 id=0x10202cd}
E/AndroidRuntime(2170): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:789)
E/AndroidRuntime(2170): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:998)
E/AndroidRuntime(2170): at android.app.BackStackRecord.run(BackStackRecord.java:622)
E/AndroidRuntime(2170): at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1330)
E/AndroidRuntime(2170): at android.app.Activity.performStart(Activity.java:4474)
E/AndroidRuntime(2170): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1928)
I am developing app with minSdkVersion="11", that is app for tablets and Android 4.0 and newer. I have scrutinized internet on this topic, but have not found much.
To implement custom layout for previous versions of Android SDK we just have to create layout (say preference.xml) with ListView and its id equals to android.R.id.list and use setContentView method.
preference.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>
In Android 3.0 things have changed and Preferences are implemented with use of fragments. That is how my preference_headers.xml file looks like:
<preference-headers
xmlns:android="http://schemas.android.com/apk/res/android">
<header android:fragment="com.example.MyPreferenceActivity$GeneralSettingsFragment"
android:title="General"
android:summary="Common settings." />
<header
android:title="Example.com" >
<intent android:action="android.intent.action.VIEW"
android:data="http://www.example.com" />
</header>
</preference-headers>
MyPreferenceActivity.java:
public class MyPreferenceActivity extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.preference);
// Add a button to the header list.
if (hasHeaders()) {
Button button = new Button(this);
button.setText("Log out");
setListFooter(button);
}
}
/**
* Populate the activity with the top-level headers.
*/
@Override
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.preference_headers, target);
}
public static class GeneralSettingsFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.fragmented_preferences);
}
}
}
Now if I run MyPreferenceActivity I will see this error in LogCat:
> java.lang.IllegalArgumentException: No view found for id 0x10202be for
> fragment GeneralSettingsFragment{4077f8c0 #0 id=0x10202be}
> E/AndroidRuntime(17103): at
> android.app.FragmentManagerImpl.moveToState(FragmentManager.java:729)
> E/AndroidRuntime(17103): at
> android.app.FragmentManagerImpl.moveToState(FragmentManager.java:926)
> E/AndroidRuntime(17103): at
> android.app.FragmentManagerImpl.moveToState(FragmentManager.java:909)
> E/AndroidRuntime(17103): at
> android.app.FragmentManagerImpl.dispatchStart(FragmentManager.java:1584)
> E/AndroidRuntime(17103): at
> android.app.Activity.performStart(Activity.java:4377)
> E/AndroidRuntime(17103): at
> android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1724)
> E/AndroidRuntime(17103): ... 11 more
I know what causes this problem. FragmentManager just cannot find a view to insert fragment GeneralSettingsFragment in. But I don't know how to solve it.
By the way, if I run the same app on Android 4.0, then I can see the first Preference Activity with headers. But if I click on General, app will crash and I will receive similar error in LogCat:
java.lang.IllegalArgumentException: No view found for id 0x10202cd for fragment GeneralSettingsFragment{4134b4e0 #0 id=0x10202cd}
E/AndroidRuntime(2170): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:789)
E/AndroidRuntime(2170): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:998)
E/AndroidRuntime(2170): at android.app.BackStackRecord.run(BackStackRecord.java:622)
E/AndroidRuntime(2170): at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1330)
E/AndroidRuntime(2170): at android.app.Activity.performStart(Activity.java:4474)
E/AndroidRuntime(2170): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1928)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我和你有同样的问题。
我尝试了很多东西,但这是我的完整代码:
https://github.com/iRail/BeTrains-for-Android/blob/master/src/tof/cv/mpp/MyPreferenceActivity.java
技巧是在 onBuildHeaders 部分添加 setContentView,但不在 onCreate 中。
我还在片段中做了一些测试,并不完全确定为什么这是有效的,但我向你保证:我在平板电脑标题部分有一个自定义布局!
https:// github.com/iRail/BeTrains-for-Android/blob/master/src/tof/cv/mpp/view/StockPreferenceFragment.java
I had the same issue than you.
I tried a lot of stuff but here is my full code:
https://github.com/iRail/BeTrains-for-Android/blob/master/src/tof/cv/mpp/MyPreferenceActivity.java
The trick is to add the setContentView in the onBuildHeaders section, but NOT in the onCreate.
I also made some tests in fragment and not perfectly sure why this is working, but I promise you: I have a custom layout on tablet header section!
https://github.com/iRail/BeTrains-for-Android/blob/master/src/tof/cv/mpp/view/StockPreferenceFragment.java
我为我的应用程序尝试了这段代码
i tried this code for my application
您不需要设置ContenView。在此示例中,布局填充是通过标题和关联的片段(换句话说是自动)完成的。
you do not need to setContenView. in this example case the layout population is done via headers and associated fragments, another words automatically.