5

It may sound foolish, but I actually can't find anything on it. Is it ok to add multiple views to the root view of activity in Android?

So for example I could go like this:

setContentView(R.layout.main);
setContentView(gLView);
setContentView(otherView);

Or simply retrieve it as a view

FrameLayout layout = (FrameLayout)this.getWindow().getDecorView().findViewById(android.R.id.content);
layout.addView(view1);
layout.addView(view2);
layout.addView(view3);
layout.addView(view4);

It all seems to work on devices I test, but is it guaranteed to work on all of them? Or should I artificially create single FrameLayout to add to root view and add everything to this FrameLayout?

More experiments: 1) if I don't use setContentView and print:

Log.d("Test", this.getWindow().getDecorView().findViewById(android.R.id.content).getClass().getName());

I get: android.widget.FrameLayout

2) If I set content view to for example GLSurfaceView and print the same Log.d It also prints android.widget.FrameLayout

3) And if I dont' use setContentView at all, and simply do

FrameLayout layout = (FrameLayout)this.getWindow().getDecorView().findViewById(android.R.id.content);
layout.addView(myView);

It attaches the view

So I assume that android.R.id.content returns not what you set by setContentView but the parent of what you set, or the actual root view in activity (which turns out is FrameLayout?)

And I am able to add multiple children to it this way, but question is: Am I allowed to do that?

Artūrs Sosins
  • 579
  • 5
  • 21
  • 3
    have setContentview more than once for the same activity is not a good idea. you can have a container in the layout and views to it. – Raghunandan Jan 21 '14 at 16:05
  • 1
    without testing id assume that setContentView will replace previous views, while retrieving the FrameLayout and adding views to it, will keep em all. – Daniel Bo Jan 21 '14 at 16:08
  • true, it seems that setContentView replaces, but retrieving root view as layout allows to add multiple views. But question is, is it safe to do that? – Artūrs Sosins Jan 21 '14 at 16:13

3 Answers3

3

Yes, it's perfectly fine to add multiple content Views at the root level. The content Views are simply added to a FrameLayout container, and it is best practice to simply use it for your layout if a FrameLayout is all you require for it, instead of adding an additional container layer.

If you are adding a new content View, then you should use the addContentView() method instead of setContentView(), which would cause the existing content to be replaced instead.

Also, it is possible to add multiple Views to the content container in XML layouts as well by using the <merge> tag, which would just replace the base FrameLayout.

corsair992
  • 3,050
  • 22
  • 33
  • `addContentView`, brilliant, that is the confirmation, that there could be multiple views. Some how I missed that. Thank you ;) – Artūrs Sosins Jan 21 '14 at 20:18
  • Answer my question https://stackoverflow.com/questions/76529993/add-view-to-android-rootview-application-without-permission – Taimoor Khan Jun 22 '23 at 11:28
1

Calling setContentView several times will simply replace whatever view you set before. So what you want to do is create a root view that contains the multiple views you want to add and set the root view to your Activity with setContentView. Your second example with the FrameLayout is a good approach.

AxiomaticNexus
  • 6,190
  • 3
  • 41
  • 61
  • I agree with you in principle. However, note that the documentation suggests that although you can add multiple children to [`FrameLayout`](http://developer.android.com/reference/android/widget/FrameLayout.html) in general `FrameLayout` should be used to hold a single child `View`. – Justin Muller Jan 21 '14 at 16:46
  • @JustinMuller You don't have to use `FrameLayout`. `LinearLayout` is usually the default root view people go with. I personally always go with `RelativeLayout`. It all depends on what you're trying to accomplish really. – AxiomaticNexus Jan 21 '14 at 17:00
  • But isn't `this.getWindow().getDecorView().findViewById(android.R.id.content);` would get you back the same root view, you set children to using `setContentView`? or am I misunderstanding something? – Artūrs Sosins Jan 21 '14 at 17:05
  • @ArtūrsSosins `setContentView` does not set a child, `setContentView` sets the root view that you will get back if you call `this.getWindow().getDecorView().findViewById(android.R.id.content);` – AxiomaticNexus Jan 21 '14 at 18:00
  • @Yasmani Llanes not exactly true, check my additions to the question – Artūrs Sosins Jan 21 '14 at 18:19
0

Your approach is valid at some extent. but its nice practice to call the setcontentView() once in activity.

this is because it will be very easy to maintain the Activity life cycle and reduce the app crash due to layout leak.

I personally call the setcontentView() once. I define all the layout in single XML file. Afterwords I call setVisibility(View.VISIBLE) and setVisibility(View.INVISIBLE) or setVisibility(View.GONE) to show or hide any particular layout containing my certain views.

Edit

Also its very easy to adjust the layout in XML because you can use simple drag and drop and If you are using relativeLayout then it will be very easy to place any view any where. but in Java code its some how difficult to place the views on your desired position

Hope this helps :)

Qadir Hussain
  • 8,721
  • 13
  • 89
  • 124
  • 1
    Oh I know the good practices but my purpose is a little different which is hard to explain and setting multiple views directly to root view without additional layout in xml or programmatically would save tons of time for me and hundreds of other developers – Artūrs Sosins Jan 21 '14 at 18:56
  • Good to know this :p I was just sharing my experience – Qadir Hussain Jan 21 '14 at 18:58