Android - Dynamically Add Views into View

AndroidDynamicViewAndroid Layout

Android Problem Overview


I have a layout for a view -

<LinearLayout
  	xmlns:android="http://schemas.android.com/apk/res/android"
  	android:layout_width="fill_parent"
  	android:layout_height="fill_parent"
  	android:padding="0px"
  	android:orientation="vertical">
  
  	<TextView
  		android:layout_width="fill_parent"
  		android:layout_height="wrap_content"
  		android:id="@+id/items_header"
  		style="@style/Home.ListHeader" />
  		
  	<TextView 
  		android:layout_width="fill_parent"
  		android:layout_height="wrap_content"
  		android:id="@+id/items_none"
  		android:visibility="gone"
  		style="@style/TextBlock"
  		android:paddingLeft="6px" />
  	
  	<ListView 
  		android:layout_width="fill_parent"
  		android:layout_height="wrap_content"
		android:id="@+id/items_list" />
		
  
</LinearLayout>

What I want to do, is in my main activity with a layout like this

<LinearLayout
  	xmlns:android="http://schemas.android.com/apk/res/android"
  	android:layout_width="fill_parent"
  	android:layout_height="fill_parent"
  	android:padding="0px"
  	android:id="@+id/item_wrapper">
</LinearLayout>

I want to loop through my data model and inject multiple views consisting of the first layout into the main layout. I know I can do this by building the controls completely within the code, but I was wondering if there was a way to dynamically build the views so that I can continue using a layout instead of putting everything in code.

Android Solutions


Solution 1 - Android

Use the LayoutInflater to create a view based on your layout template, and then inject it into the view where you need it.

LayoutInflater vi = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = vi.inflate(R.layout.your_layout, null);

// fill in any details dynamically here
TextView textView = (TextView) v.findViewById(R.id.a_text_view);
textView.setText("your text");

// insert into main view
ViewGroup insertPoint = (ViewGroup) findViewById(R.id.insert_point);
insertPoint.addView(v, 0, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));

You may have to adjust the index where you want to insert the view.

Additionally, set the LayoutParams according to how you would like it to fit in the parent view. e.g. with FILL_PARENT, or MATCH_PARENT, etc.

Solution 2 - Android

See the LayoutInflater class.

LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ViewGroup parent = (ViewGroup)findViewById(R.id.where_you_want_to_insert);
inflater.inflate(R.layout.the_child_view, parent);

Solution 3 - Android

It looks like what you really want a ListView with a custom adapter to inflate the specified layout. Using an ArrayAdapter and the method notifyDataSetChanged() you have full control of the Views generation and rendering.

Take a look at these tutorials

Solution 4 - Android

To make @Mark Fisher's answer more clear, the inserted view being inflated should be a xml file under layout folder but without a layout (ViewGroup) like LinearLayout etc. inside. My example:

res/layout/my_view.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/i_am_id"
    android:text="my name"
    android:textSize="17sp"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1"/>

Then, the insertion point should be a layout like LinearLayout:

res/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/aaa"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/insert_point"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </LinearLayout>

</RelativeLayout>

Then the code should be

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_shopping_cart);

    LayoutInflater inflater = getLayoutInflater();
    View view = inflater.inflate(R.layout.my_view, null);
    ViewGroup main = (ViewGroup) findViewById(R.id.insert_point);
    main.addView(view, 0);
}

The reason I post this very similar answer is that when I tried to implement Mark's solution, I got stuck on what xml file should I use for insert_point and the child view. I used layout in the child view firstly and it was totally not working, which took me several hours to figure out. So hope my exploration can save others' time.

Solution 5 - Android

// Parent layout
LinearLayout parentLayout = (LinearLayout)findViewById(R.id.layout);

// Layout inflater
LayoutInflater layoutInflater = getLayoutInflater();
View view;

for (int i = 1; i < 101; i++){
	// Add the text layout to the parent layout
	view = layoutInflater.inflate(R.layout.text_layout, parentLayout, false);

	// In order to get the view we have to use the new view with text_layout in it
	TextView textView = (TextView)view.findViewById(R.id.text);
	textView.setText("Row " + i);

	// Add the text view to the parent layout
	parentLayout.addView(textView);
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJoshView Question on Stackoverflow
Solution 1 - AndroidMark FisherView Answer on Stackoverflow
Solution 2 - AndroidGabriel NegutView Answer on Stackoverflow
Solution 3 - AndroidAleadamView Answer on Stackoverflow
Solution 4 - AndroidYork YangView Answer on Stackoverflow
Solution 5 - AndroidTienanhvnView Answer on Stackoverflow