216

Let's say I have a LinearLayout, and I want to add a View to it, in my program from the Java code. What method is used for this? I'm not asking how it's done in XML, which I do know, but rather, how can I do something along the lines of this sample code?

(One View).add(Another View)

Like one can do in Swing.

xarlymg89
  • 2,552
  • 2
  • 27
  • 41
Moki
  • 5,121
  • 4
  • 21
  • 9

7 Answers7

293

Calling addView is the correct answer, but you need to do a little more than that to get it to work.

If you create a View via a constructor (e.g., Button myButton = new Button();), you'll need to call setLayoutParams on the newly constructed view, passing in an instance of the parent view's LayoutParams inner class, before you add your newly constructed child to the parent view.

For example, you might have the following code in your onCreate() function assuming your LinearLayout has id R.id.main:

LinearLayout myLayout = findViewById(R.id.main);

Button myButton = new Button(this);
myButton.setLayoutParams(new LinearLayout.LayoutParams(
                                     LinearLayout.LayoutParams.MATCH_PARENT,
                                     LinearLayout.LayoutParams.MATCH_PARENT));

myLayout.addView(myButton);

Making sure to set the LayoutParams is important. Every view needs at least a layout_width and a layout_height parameter. Also getting the right inner class is important. I struggled with getting Views added to a TableRow to display properly until I figured out that I wasn't passing an instance of TableRow.LayoutParams to the child view's setLayoutParams.

Sergii
  • 1,521
  • 3
  • 24
  • 37
Brian Cooley
  • 11,622
  • 4
  • 40
  • 39
  • 7
    How would you create the view programmatically but by using an XML layout file you specifically wrote for this new view? – Ken Jan 18 '11 at 12:31
  • 12
    @SK9 You would use a LayoutInflater, which you can get from a Context, usually the current Activity. Something like: LayoutInflater myInflater = getLayoutInflater; View myView = myInflater.inflate(R.layout.myLayout, parent, false); – Brian Cooley Jan 30 '11 at 11:05
  • 1
    Actually getLayoutInflater() comes from the Window class (not Context), and it is a convenience method in Activity. – Brian Cooley Jan 30 '11 at 11:17
  • 2
    As a coding practice, on findViewById, cast to ViewGroup or always the most generic form of an object so that if it changes from a LinearLayout to a RelativeLayout, you have no refactoring. – Joel Teply Apr 03 '15 at 16:59
  • 2
    These are some details :D – Vivek Solanki Sep 01 '17 at 00:41
  • this is perfect answer :) – coolcool1994 Aug 04 '20 at 21:51
  • If you're not seeing your custom control, double check the layout you are adding to has space for your custom view! I erroneously tried adding my custom view to the bottom of a layout whose last child was set to `android:layout_height="match_parent"`. My custom view was being added, but not visibly rendered due to this simple error. – rmirabelle Feb 10 '21 at 04:50
63

The best way I found is to use the inflate static method of View.

View inflatedView = View.inflate(context, yourViewXML, yourLinearLayout);

where yourViewXML is something like R.layout.myView

please notice that you need a ViewGroup in order to add a view (which is any layout you can think of)

so as an example lets say you have a fragment which it view already been inflated and you know that the root view is a layout, and you want to add a view to it:

    View view = getView(); // returns base view of the fragment
    if (view == null)
        return;
    if (!(view instanceof ViewGroup))
        return;

    ViewGroup viewGroup = (ViewGroup) view;
    View popup = View.inflate(viewGroup.getContext(), R.layout.someView, viewGroup);

EDIT:

Kotlin code for the example above (view is the getView() of a fragment)

(view as? ViewGroup)?.let {
        View.inflate(context, R.layout.add_credit_card, it)
}
ndori
  • 1,934
  • 1
  • 18
  • 23
  • You could also write a static method, something like `addView(View v){ // your code after get view }` that would take a view found using `findViewById(int resourceID)` or inflated like your `inflatedView`... just to expand on your fragment example. – zgc7009 Oct 09 '16 at 23:35
  • After messing with inflating the layout and trying to do `myLinearLayout.add(view)` this was the only thing that worked. Thanks for this! – Eric B. Mar 07 '21 at 01:10
29

To add the view programmatically, you can do:

LinearLayout rlmain = new LinearLayout(this);      
LinearLayout.LayoutParams llp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.FILL_PARENT);          
LinearLayout   ll1 = new LinearLayout (this);
                        
ImageView iv = new ImageView(this);
iv.setImageResource(R.drawable.logo);              
LinearLayout .LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
            
iv.setLayoutParams(lp);
ll1.addView(iv);
rlmain.addView(ll1);              
setContentView(rlmain, llp);

You can also add any number of views.

Zoe
  • 27,060
  • 21
  • 118
  • 148
AndroidOptimist
  • 1,419
  • 3
  • 23
  • 38
23

LinearLayout is a subclass of ViewGroup, which has a method called addView. The addView method should be what you are after.

Klarth
  • 2,035
  • 14
  • 26
9

The idea of programmatically setting constraints can be tiresome. This solution below will work for any layout whether constraint, linear, etc. Best way would be to set a placeholder i.e. a FrameLayout with proper constraints (or proper placing in other layout such as linear) at position where you would expect the programmatically created view to have.

All you need to do is inflate the view programmatically and it as a child to the FrameLayout by using addChild() method. Then during runtime your view would be inflated and placed in right position. Per Android recommendation, you should add only one childView to FrameLayout [link].

Here is what your code would look like, supposing you wish to create TextView programmatically at a particular position:

Step 1:

In your layout which would contain the view to be inflated, place a FrameLayout at the correct position and give it an id, say, "container".

Step 2 Create a layout with root element as the view you want to inflate during runtime, call the layout file as "textview.xml" :

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent">

</TextView>

BTW, set the layout-params of your frameLayout to wrap_content always else the frame layout will become as big as the parent i.e. the activity i.e the phone screen.

android:layout_width="wrap_content"
android:layout_height="wrap_content"

If not set, because a child view of the frame, by default, goes to left-top of the frame layout, hence your view will simply fly to left top of the screen.

Step 3

In your onCreate method, do this :

FrameLayout frameLayout = findViewById(R.id.container);
                TextView textView = (TextView) View.inflate(this, R.layout.textview, null);
                frameLayout.addView(textView);

(Note that setting last parameter of findViewById to null and adding view by calling addView() on container view (frameLayout) is same as simply attaching the inflated view by passing true in 3rd parameter of findViewById(). For more, see this.)

kush
  • 486
  • 4
  • 6
4

One more way to add view from Activity

ViewGroup rootLayout = findViewById(android.R.id.content);
rootLayout.addView(view);
yoAlex5
  • 29,217
  • 8
  • 193
  • 205
-1

You guys should also make sure that when you override onLayout you HAVE to call super.onLayout with all of the properties, or the view will not be inflated!

Oz Shabat
  • 1,434
  • 17
  • 16