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.
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.
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.
It seems that this behavior was fixed in Support Library revision 19: https://code.google.com/p/android/issues/detail?id=58108#c21
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:)