android.R.id.content as container for Fragment

My situation is Activity A which contains Fragment B. I always implement it like this.

Layout for Activity A:

  • How to display my location on Google Maps for Android API v2
  • How to Build a RSS reader for Android?
  • How do I draw an arrowhead (in Android)?
  • java.lang.RuntimeException: Only one Looper may be created per thread
  • Icon in Tab is not showing up
  • How can I set the color of android rating bar's stroke? (Not the color of the stars but the BORDER)
  • <?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" />
    

    Layout for Fragment 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>
    

    This works great, but if we open Android Device monitor and look at View Hierarchy:

    So, I do not like that in my hierarchy there are two same useless FrameLayouts and I can cut my R.id.container. I do it like this:

    onCreate(Bundle args) implementation in my Activity A:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        getFragmentManager().beginTransaction()
            .add(android.R.id.content, FragmentB.newInstance()).commit();
    }
    

    I just do not set content for my Activity and attach my Fragment B to system container android.R.id.content. This works great for me. I removed one useless include.

    My question is it good practice to do this “hack”. Could it crashs my application in any cases and what problems could I have after this implementation? May be somebody has useful experience in this question?

    Thanks to all for good answers.

  • Android Studio Espresso Testing Error: Empty Test Suite
  • How do android screen coordinates work?
  • Using TabLayout inside a Fragment; tab text invisible
  • how to design right to left linear layout
  • Android, how to not destroy the activity when I rotate the device?
  • How to programmatically change contrast of a bitmap in android?
  • One Solution collect form web for “android.R.id.content as container for Fragment”

    there is nothing wrong with it. Like you said: you dont need your extra R.id.content layout so… just don’t add it with setContentView. There is even mention about it in official documentation of ActionBar: http://developer.android.com/guide/topics/ui/actionbar.html#Tabs

    Alternatively, if the tab content will fill the activity layout, then
    your activity doesn’t need a layout at all (you don’t even need to
    call setContentView()). Instead, you can place each fragment in the
    default root view, which you can refer to with the
    android.R.id.content ID

    If you develop only for 14+ (because of native ActionBar) everything should be fine with it, but if you use support lib please read the points below.

    I. If you use Support Library revision lower than 19:

    Important thing is: What is your min API level that you develop for?

    If your app supporting API < 14 and you use AppCompat you must be aware the different behavior.
    android.R.id.content is the part of screen where your application should display it’s content.
    On native API 14+ This is just part below ActionBar, because this part is supposed to display activity content.

    In AppCompat, where there is no native support for ActionBar. android.R.id.content is the container of entire app screen. This means – including ActionBar, because ActionBar is emulated there and added as a standard view hierarchy. To solve this issue you have to check whether you are on API lower than 14 and use different id: R.id.action_bar_activity_content

    You can create helper method to get correct 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;
    }
    

    So if you are developing for 14+ this is perfectly fine solution. If you use custom ActionBar implementation (like AppCompat) you have to do this trick.


    II. If you use Support Library revision 19 (or greater):

    It seems that this behavior was fixed in Support Library revision 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

    You can see that they replacing the old R.id.action_bar_activity_content with standard android.R.id.content (and the old android.R.id.content with NO_ID) for better compatibility! So if you use Support Lib r19 or greater (or just a native framework) you can just just android.R.id.content in both <14 and 14+ variants:)

    Android Babe is a Google Android Fan, All about Android Phones, Android Wear, Android Dev and Android Games Apps and so on.