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

Ily*_*dov 15 android android-layout android-fragments fragmenttransaction

我的情况是活动A,其中包含片段B.我总是像这样实现它.

活动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" />
Run Code Online (Sandbox Code Playgroud)

片段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>
Run Code Online (Sandbox Code Playgroud)

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

所以,我不喜欢在我的层次结构中有两个相同无用的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();
}
Run Code Online (Sandbox Code Playgroud)

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

我的问题是做这个"黑客"的好习惯.在任何情况下它都会崩溃我的应用程序吗?这个实现后我可以遇到什么问题?可能有人在这个问题上有实际经验吗?

感谢所有人的好答案.

Mac*_*ęga 21

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

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

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

I.如果您使用低于19的支持库修订版:

重要的是:您开发的最低API级别是多少?

如果您的应用支持API <14并且您使用AppCompat,则必须了解不同的行为. 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;
}
Run Code Online (Sandbox Code Playgroud)

因此,如果您正在开发14+,这是非常好的解决方案.如果您使用自定义ActionBar实现(如AppCompat),则必须执行此操作.


II.如果您使用支持库修订版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(以及带有NO_ID的旧android.R.id.content)替换旧的R.id.action_bar_activity_content以获得更好的兼容性!因此,如果您使用Support Lib r19或更高版本(或仅仅是本机框架),您可以只使用<14和14+变体中的android.R.id.content :)

  • 这很奇怪.我在支持库v20上使用了android.R.id.content,但它没有用.唯一有用的是使用布局文件并在其上使用setContentView. (2认同)
  • 似乎这已经在appcompat> = v22中再次被打破(它在v21上为我工作,但升级到v22或v23中断,并放入我自己的内容FrameLayout修复它) (2认同)