android.R.id.content 作为 Fragment 的容器

Posted

技术标签:

【中文标题】android.R.id.content 作为 Fragment 的容器【英文标题】:android.R.id.content as container for Fragment 【发布时间】:2014-09-02 22:26:06 【问题描述】:

我的情况是包含 Fragment B 的 Activity A。我总是这样实现它。

活动 A 的布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_
    android:layout_ />

片段 B 的布局:

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

    <Button
        android:id="@+id/button"
        android:layout_
        android:layout_
        android:text="@string/button_title"
        android:layout_centerInParent="true"
        android:background="@drawable/green_button"
        android:textColor="@android:color/white"/>

</RelativeLayout>

这很好用,但是如果我们打开 Android 设备监视器并查看 View Hierarchy:

所以,我不喜欢在我的层次结构中有两个相同的无用 FrameLayouts,我可以剪切我的 R.id.container。我是这样做的:

我的活动 A 中的 onCreate(Bundle args) 实现:

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

    getFragmentManager().beginTransaction()
        .add(android.R.id.content, FragmentB.newInstance()).commit();

我只是没有为我的 Activity 设置内容,而是将我的 Fragment B 附加到系统容器 android.R.id.content。这对我很有用。我删除了一个无用的包含。

我的问题是做这个“hack”是个好习惯。它会在任何情况下使我的应用程序崩溃吗?在此实施后我会遇到什么问题?可能有人在这个问题上有有用的经验吗?

感谢大家的好回答。

【问题讨论】:

same 不,android.R. 【参考方案1】:

这并没有什么问题。就像你说的:你不需要额外的 R.id.content 布局,所以......只是不要用 setContentView 添加它。 ActionBar 的官方文档中甚至有提及:http://developer.android.com/guide/topics/ui/actionbar.html#Tabs

或者,如果选项卡内容将填充活动布局,则 您的活动根本不需要布局(您甚至不需要 调用 setContentView())。相反,您可以将每个片段放在 默认根视图,您可以使用 android.R.id.content ID

如果你只为 14+ 开发(因为原生 ActionBar)一切都应该没问题,但如果你使用支持库,请阅读以下几点。

我。如果您使用低于 19 的支持库版本:

重要的是:您开发的最低 API 级别是多少? 如果您的应用支持 API android.R.id.content 是您的应用程序应显示其内容的屏幕部分。 在原生 API 14+ 这只是 ActionBar 下方的部分,因为这部分应该显示活动内容。 在 AppCompat 中,没有对 ActionBar 的原生支持。 android.R.id.content 是整个应用屏幕的容器。这意味着 - 包括 ActionBar,因为 ActionBar 在那里被模拟并作为标准视图层次结构添加。要解决此问题,您必须检查您是否使用低于 14 的 API 并使用不同的 id:R.id.action_bar_activity_content

您可以创建辅助方法来获取正确的 id:

public static int getContentViewId() 
    return Build.VERSION.SDK_INT>=Build.VERSION_CODES.ICE_CREAM_SANDWICH ? android.R.id.content : R.id.action_bar_activity_content;

因此,如果您正在为 14 岁以上的用户开发,这是一个非常好的解决方案。如果您使用自定义 ActionBar 实现(如 AppCompat),则必须这样做。


二。如果您使用支持库修订版 19(或更高版本):

似乎此行为已在支持库修订版 19 中得到修复: https://code.google.com/p/android/issues/detail?id=58108#c21

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4.2_r1/android/support/v7/app/ActionBarActivityDelegateBase.java/#228

您可以看到他们用标准的 android.R.id.content 替换了旧的 R.id.action_bar_activity_content(以及旧的 android.R.id.content带 NO_ID)以获得更好的兼容性!因此,如果您使用 Support Lib r19 或更高版本(或仅使用本机框架),您可以只使用

【讨论】:

没问题。很高兴我能提供帮助:)我还稍微重新组织了我的答案+在顶部添加了 ActionBar 文档的链接(和引用)(确切地提到了这个特殊案例) 这很奇怪。我在支持库 v20 上使用了 android.R.id.content,但它不起作用。唯一有效的是使用布局文件并在其上使用 setContentView。 这似乎在 appcompat >= v22 中再次被破坏(它在 v21 上对我有用,但升级到 v22 或 v23 会中断,并放入我自己的内容 FrameLayout 修复它)

以上是关于android.R.id.content 作为 Fragment 的容器的主要内容,如果未能解决你的问题,请参考以下文章

findViewById(android.R.id.content) 可以为 Snackbars 返回 null 吗?

如何从 Activity RootView 中删除视图

如何使用ById或ByTag在android中获取当前片段

循环遍历 GroupView 的所有子项?

监听虚拟键盘弹出的高度

片段变得可见时的监听器