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

16

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

Activity A的布局:

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

片段B的布局:

<?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">

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

</RelativeLayout>

这个方法很不错,但是如果我们打开Android设备监视器并查看视图层次结构:

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

我的Activity 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”做法是否是好的实践?它会在任何情况下崩溃我的应用程序吗?在此实施后,我可能会遇到什么问题?也许有人在这个问题上有有用的经验?

感谢所有给出好答案的人。


不同,android.R. - njzk2
1个回答

22

这没有任何问题。就像你说的那样:你不需要额外的R.id.content布局,所以...只需不要在setContentView中添加它即可。甚至在ActionBar的官方文档中也提到了这一点:http://developer.android.com/guide/topics/ui/actionbar.html#Tabs

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

如果您仅为14+进行开发(因为原生ActionBar),则一切都应该没问题,但如果您使用支持库,请阅读以下几点:

I. 如果您使用低于19的Support Library版本:

重要的是:您为哪个最小API级别开发?

如果您的应用程序支持API&lt;14并且使用AppCompat,则必须知道不同的行为。 android.R.id.content是屏幕上您的应用程序应显示其内容的部分。 在原生API 14+上,这只是下面的ActionBar部分,因为此部分应显示活动内容。

在AppCompat中,没有原生ActionBar支持。 android.R.id.content是整个应用程序屏幕的容器。这意味着-包括ActionBar,因为ActionBar在那里被模拟并添加为标准视图层次结构。要解决此问题,您必须检查自己是否在API低于14的情况下使用不同的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),则必须进行此技巧。


II. 如果您使用Support Library修订版19(或更高版本):

似乎在Support Library修订版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

您可以看到,他们将旧的R.id.action_bar_activity_content替换为标准的android.R.id.content(并将旧的android.R.id.content替换为NO_ID),以提高兼容性!因此,如果您使用Support Lib r19或更高版本(或仅使用本机框架),则可以在<14和14+变体中都只使用android.R.id.content:


没问题。很高兴能帮到你 :) 我还重新组织了我的答案,并在顶部添加了ActionBar文档的链接(并引用了其中关于这个特定情况的提及)。 - Maciej Ciemięga
2
这很奇怪。我在支持库v20上使用了android.R.id.content,但它不起作用。唯一有效的方法是使用布局文件并在其上使用setContentView。 - android developer
2
似乎在appcompat >= v22中又出现了问题(在v21上对我有效,但升级到v22或v23会出现问题,将自己的内容FrameLayout放入其中可以解决问题)。 - Karsten

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接