Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

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

like image 556
Ilya Demidov Avatar asked Jul 12 '14 10:07

Ilya Demidov


People also ask

What is <fragmentcontainerview> in Android?

FragmentContainerView is a custom View that extends FrameLayout, but unlike other ViewGroups, it only accepts Fragment Views. It also supports the <fragment> attributes, but offers more Fragment transactions flexibility.

How do I access the fragmentmanager in Android?

Every FragmentActivity and subclasses thereof, such as AppCompatActivity, have access to the FragmentManager through the getSupportFragmentManager () method. Accessing in a Fragment Fragments are also capable of hosting one or more child fragments.

What happens to fragments after they are created in Android?

When you commit the fragment transaction, the instance of the fragment you created is the instance used. However, during a configuration change, your activity and all of its fragments are destroyed and then recreated with the most applicable Android resources . The FragmentManager handles all of this for you.

What is the use of fragmenttransaction in Android?

Instead, a FragmentTransaction is used to instantiate a fragment and add it to the activity's layout. While your activity is running, you can make fragment transactions such as adding, removing, or replacing a fragment. In your FragmentActivity, you can get an instance of the FragmentManager, which can be used to create a FragmentTransaction.


1 Answers

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:)

like image 131
Maciej Ciemięga Avatar answered Oct 03 '22 05:10

Maciej Ciemięga