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.
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.
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.
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.
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.
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
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:)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With