What is the use of LayoutInflater
in Android?
This question is related to
android
layout-inflater
android-inflate
LayoutInflator
do?When I first started Android programming, I was really confused by LayoutInflater
and findViewById
. Sometimes we used one and sometimes the other.
LayoutInflater
is used to create a new View
(or Layout
) object from one of your xml layouts.findViewById
just gives you a reference to a view than has already been created. You might think that you haven't created any views yet, but whenever you call setContentView
in onCreate
, the activity's layout along with its subviews gets inflated (created) behind the scenes.So if the view already exists, then use findViewById
. If not, then create it with a LayoutInflater
.
Here is a mini project I made that shows both LayoutInflater
and findViewById
in action. With no special code, the layout looks like this.
The blue square is a custom layout inserted into the main layout with include
(see here for more). It was inflated automatically because it is part of the content view. As you can see, there is nothing special about the code.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Now let's inflate (create) another copy of our custom layout and add it in.
LayoutInflater inflater = getLayoutInflater();
View myLayout = inflater.inflate(R.layout.my_layout, mainLayout, false);
To inflate the new view layout, all I did was tell the inflater the name of my xml file (my_layout
), the parent layout that I want to add it to (mainLayout
), and that I don't actually want to add it yet (false
). (I could also set the parent to null
, but then the layout parameters of my custom layout's root view would be ignored.)
Here it is again in context.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// inflate the main layout for the activity
setContentView(R.layout.activity_main);
// get a reference to the already created main layout
LinearLayout mainLayout = (LinearLayout) findViewById(R.id.activity_main_layout);
// inflate (create) another copy of our custom layout
LayoutInflater inflater = getLayoutInflater();
View myLayout = inflater.inflate(R.layout.my_layout, mainLayout, false);
// make changes to our custom layout and its subviews
myLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.colorAccent));
TextView textView = (TextView) myLayout.findViewById(R.id.textView);
textView.setText("New Layout");
// add our custom layout to the main layout
mainLayout.addView(myLayout);
}
}
Notice how findViewById
is used only after a layout has already been inflated.
Here is the xml for the example above.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main_layout"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<!-- Here is the inserted layout -->
<include layout="@layout/my_layout"/>
</LinearLayout>
my_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="@color/colorPrimary">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:padding="5dp"
android:textColor="@android:color/white"
android:text="My Layout"/>
</RelativeLayout>
RecyclerView
. (See these RecyclerView
examples for a list or a grid.) You have to inflate a new layout for every single visible item in the list or grid.What inflater does
It takes a xml layout as input (say) and converts it to View object.
Why needed
Let us think a scenario where we need to create a custom listview. Now each row should be custom. But how can we do it. Its not possible to assign a xml layout to a row of listview. So, we create a View object. Thus we can access the elements in it (textview,imageview etc) and also assign the object as row of listview
So, whenever we need to assign view type object somewhere and we have our custom xml design we just convert it to object by inflater and use it.
The LayoutInflater class is used to instantiate the contents of layout XML files into their corresponding View objects.
In other words, it takes an XML file as input and builds the View objects from it.
LayoutInflater is a fundamental component in Android. You must use it all the time to turn xml files into view hierarchies.
This class is used to instantiate layout XML file into its corresponding View
objects. It is never be used directly -- use getLayoutInflater()
or getSystemService(String)
to retrieve a standard LayoutInflater
instance that is already hooked up to the current context and correctly configured for the device you are running on. For example:
LayoutInflater inflater = (LayoutInflater)context.getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
Reference: http://developer.android.com/reference/android/view/LayoutInflater.html
here is an example for geting a refrence for the root View of a layout , inflating it and using it with setContentView(View view)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater li=getLayoutInflater();
View rootView=li.inflate(R.layout.activity_main,null);
setContentView(rootView);
}
LayoutInflater.inflate() provides a means to convert a res/layout/*.xml file defining a view into an actual View object usable in your application source code.
basic two steps: get the inflater and then inflate the resource
How do you get the inflater?
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
How do you get the view assuming the xml file is "list_item.xml"?
View view = inflater.inflate(R.layout.list_item, parent, false);
LayoutInflater is a class used to instantiate layout XML file into its corresponding view objects which can be used in Java programs.
In simple terms, there are two ways to create UI in android. One is a static way and another is dynamic or programmatically.
Suppose we have a simple layout main.xml having one textview
and one edittext
as follows.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/layout1"
>
<TextView
android:id="@+id/namelabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Enter your name"
android:textAppearance="?android:attr/textAppearanceLarge" >
</TextView>
<EditText
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginTop="14dp"
android:ems="10">
</EditText>
</LinearLayout>
We can display this layout in static way by
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
A dynamic way of creating a view means the view is not mentioned in our main.xml but we want to show with this in run time. For example, we have another XML in layout folder as footer.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/TextView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="Add your record"
android:textSize="24sp" >
</TextView>
We want to show this textbox in run time within our main UI. So here we will inflate text.xml. See how:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
TextView t = (TextView)inflater.inflate(R.layout.footer,null);
lLayout = (LinearLayout)findViewById(R.id.layout1);
lLayout.addView(t);
Here I have used getSystemService (String) to retrieve a LayoutInflater instance. I can use getLayoutInflator() too to inflate instead of using getSystemService (String) like below:
LayoutInflator inflater = getLayoutInflater();
TextView t = (TextView) inflater.inflate(R.layout.footer, null);
lLayout.addView(t);
Inflater actually some sort of convert to data, views, instances, to visible UI representation.. ..thus it make use of data feed into from maybe adapters, etc. programmatically. then integrating it with an xml you defined, that tells it how the data should be represented in UI
my customize list hope it illustrate concept
public class second extends ListActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
// TextView textview=(TextView)findViewById(R.id.textView1);
// textview.setText(getIntent().getExtras().getString("value"));
setListAdapter(new MyAdapter(this,R.layout.list_item,R.id.textView1, getResources().getStringArray(R.array.counteries)));
}
private class MyAdapter extends ArrayAdapter<String>{
public MyAdapter(Context context, int resource, int textViewResourceId,
String[] objects) {
super(context, resource, textViewResourceId, objects);
// TODO Auto-generated constructor stub
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater=(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row=inflater.inflate(R.layout.list_item,parent,false);
String[]items=getResources().getStringArray(R.array.counteries);
ImageView iv=(ImageView) row.findViewById(R.id.imageView1);
TextView tv=(TextView) row.findViewById(R.id.textView1);
tv.setText(items[position]);
if(items[position].equals("unitedstates")){
iv.setImageResource(R.drawable.usa);
}else if(items[position].equals("Russia")){
iv.setImageResource(R.drawable.russia);
}else if(items[position].equals("Japan")){
iv.setImageResource(R.drawable.japan);
}
// TODO Auto-generated method stub
return row;
}
}
}
Layout inflater is a class that reads the xml appearance description and convert them into java based View objects.
Here is another example similar to the previous one, but extended to further demonstrate inflate parameters and dynamic behavior it can provide.
Suppose your ListView row layout can have variable number of TextViews. So first you inflate the base item View (just like the previous example), and then loop dynamically adding TextViews at run-time. Using android:layout_weight additionally aligns everything perfectly.
Here are the Layouts resources:
list_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/field1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"/>
<TextView
android:id="@+id/field2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
/>
</LinearLayout>
schedule_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
Override getView method in extension of BaseAdapter class
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = activity.getLayoutInflater();
View lst_item_view = inflater.inflate(R.layout.list_layout, null);
TextView t1 = (TextView) lst_item_view.findViewById(R.id.field1);
TextView t2 = (TextView) lst_item_view.findViewById(R.id.field2);
t1.setText("some value");
t2.setText("another value");
// dinamically add TextViews for each item in ArrayList list_schedule
for(int i = 0; i < list_schedule.size(); i++){
View schedule_view = inflater.inflate(R.layout.schedule_layout, (ViewGroup) lst_item_view, false);
((TextView)schedule_view).setText(list_schedule.get(i));
((ViewGroup) lst_item_view).addView(schedule_view);
}
return lst_item_view;
}
Note different inflate method calls:
inflater.inflate(R.layout.list_layout, null); // no parent
inflater.inflate(R.layout.schedule_layout, (ViewGroup) lst_item_view, false); // with parent preserving LayoutParams
LayoutInflater creates View objects based on layouts defined in XML. There are several different ways to use LayoutInflater, including creating custom Views, inflating Fragment views into Activity views, creating Dialogs, or simply inflating a layout file View into an Activity.
There are a lot of misconceptions about how the inflation process works. I think this comes from poor of the documentation for the inflate() method. If you want to learn about the inflate() method in detail, I wrote a blog post about it here:
https://www.bignerdranch.com/blog/understanding-androids-layoutinflater-inflate/
Inflating means reading the XML file that describes a layout (or GUI element) and to create the actual objects that correspond to it, and thus make the object visible within an Android app.
final Dialog mDateTimeDialog = new Dialog(MainActivity.this);
// Inflate the root layout
final RelativeLayout mDateTimeDialogView = (RelativeLayout) getLayoutInflater().inflate(R.layout.date_time_dialog, null);
// Grab widget instance
final DateTimePicker mDateTimePicker = (DateTimePicker) mDateTimeDialogView.findViewById(R.id.DateTimePicker);
This file could saved as date_time_dialog.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/DateTimeDialog" android:layout_width="100px"
android:layout_height="wrap_content">
<com.dt.datetimepicker.DateTimePicker
android:id="@+id/DateTimePicker" android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<LinearLayout android:id="@+id/ControlButtons"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:layout_below="@+id/DateTimePicker"
android:padding="5dip">
<Button android:id="@+id/SetDateTime" android:layout_width="0dip"
android:text="@android:string/ok" android:layout_weight="1"
android:layout_height="wrap_content"
/>
<Button android:id="@+id/ResetDateTime" android:layout_width="0dip"
android:text="Reset" android:layout_weight="1"
android:layout_height="wrap_content"
/>
<Button android:id="@+id/CancelDialog" android:layout_width="0dip"
android:text="@android:string/cancel" android:layout_weight="1"
android:layout_height="wrap_content"
/>
</LinearLayout>
This file could saved as date_time_picker.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="wrap_content" `enter code here`
android:padding="5dip" android:id="@+id/DateTimePicker">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:baselineAligned="true"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/month_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="1dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:gravity="center"
android:orientation="vertical">
<Button
android:id="@+id/month_plus"
android:layout_width="45dp"
android:layout_height="45dp"
android:background="@drawable/image_button_up_final"/>
<EditText
android:id="@+id/month_display"
android:layout_width="45dp"
android:layout_height="35dp"
android:background="@drawable/picker_middle"
android:focusable="false"
android:gravity="center"
android:singleLine="true"
android:textColor="#000000">
</EditText>
<Button
android:id="@+id/month_minus"
android:layout_width="45dp"
android:layout_height="45dp"
android:background="@drawable/image_button_down_final"/>
</LinearLayout>
<LinearLayout
android:id="@+id/date_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="0.5dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:gravity="center"
android:orientation="vertical">
<Button
android:id="@+id/date_plus"
android:layout_width="45dp"
android:layout_height="45dp"
android:background="@drawable/image_button_up_final"/>
<EditText
android:id="@+id/date_display"
android:layout_width="45dp"
android:layout_height="35dp"
android:background="@drawable/picker_middle"
android:gravity="center"
android:focusable="false"
android:inputType="number"
android:textColor="#000000"
android:singleLine="true"/>
<Button
android:id="@+id/date_minus"
android:layout_width="45dp"
android:layout_height="45dp"
android:background="@drawable/image_button_down_final"/>
</LinearLayout>
<LinearLayout
android:id="@+id/year_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="0.5dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:gravity="center"
android:orientation="vertical">
<Button
android:id="@+id/year_plus"
android:layout_width="45dp"
android:layout_height="45dp"
android:background="@drawable/image_button_up_final"/>
<EditText
android:id="@+id/year_display"
android:layout_width="45dp"
android:layout_height="35dp"
android:background="@drawable/picker_middle"
android:gravity="center"
android:focusable="false"
android:inputType="number"
android:textColor="#000000"
android:singleLine="true"/>
<Button
android:id="@+id/year_minus"
android:layout_width="45dp"
android:layout_height="45dp"
android:background="@drawable/image_button_down_final"/>
</LinearLayout>
<LinearLayout
android:id="@+id/hour_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:gravity="center"
android:orientation="vertical">
<Button
android:id="@+id/hour_plus"
android:layout_width="45dp"
android:layout_height="45dp"
android:background="@drawable/image_button_up_final"/>
<EditText
android:id="@+id/hour_display"
android:layout_width="45dp"
android:layout_height="35dp"
android:background="@drawable/picker_middle"
android:gravity="center"
android:focusable="false"
android:inputType="number"
android:textColor="#000000"
android:singleLine="true">
</EditText>
<Button
android:id="@+id/hour_minus"
android:layout_width="45dp"
android:layout_height="45dp"
android:background="@drawable/image_button_down_final"/>
</LinearLayout>
<LinearLayout
android:id="@+id/min_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="0.35dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:gravity="center"
android:orientation="vertical">
<Button
android:id="@+id/min_plus"
android:layout_width="45dp"
android:layout_height="45dp"
android:background="@drawable/image_button_up_final"/>
<EditText
android:id="@+id/min_display"
android:layout_width="45dp"
android:layout_height="35dp"
android:background="@drawable/picker_middle"
android:gravity="center"
android:focusable="false"
android:inputType="number"
android:textColor="#000000"
android:singleLine="true"/>
<Button
android:id="@+id/min_minus"
android:layout_width="45dp"
android:layout_height="45dp"
android:background="@drawable/image_button_down_final"/>
</LinearLayout>
<LinearLayout
android:id="@+id/meridiem_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="0.35dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:gravity="center"
android:orientation="vertical">
<ToggleButton
android:id="@+id/toggle_display"
style="@style/SpecialToggleButton"
android:layout_width="40dp"
android:layout_height="32dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="45dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:padding="5dp"
android:gravity="center"
android:textOn="@string/meridiem_AM"
android:textOff="@string/meridiem_PM"
android:checked="true"/>
<!-- android:checked="true" -->
</LinearLayout>
</LinearLayout>
</RelativeLayout>
The MainActivity
class saved as MainActivity.java:
public class MainActivity extends Activity {
EditText editText;
Button button_click;
public static Activity me = null;
String meridiem;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText)findViewById(R.id.edittext1);
button_click = (Button)findViewById(R.id.button1);
button_click.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view){
final Dialog mDateTimeDialog = new Dialog(MainActivity.this);
final RelativeLayout mDateTimeDialogView = (RelativeLayout) getLayoutInflater().inflate(R.layout.date_time_dialog, null);
final DateTimePicker mDateTimePicker = (DateTimePicker) mDateTimeDialogView.findViewById(R.id.DateTimePicker);
// mDateTimePicker.setDateChangedListener();
((Button) mDateTimeDialogView.findViewById(R.id.SetDateTime)).setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mDateTimePicker.clearFocus();
int hour = mDateTimePicker.getHour();
String result_string = mDateTimePicker.getMonth() +" "+ String.valueOf(mDateTimePicker.getDay()) + ", " + String.valueOf(mDateTimePicker.getYear())
+ " " +(mDateTimePicker.getHour()<=9? String.valueOf("0"+mDateTimePicker.getHour()) : String.valueOf(mDateTimePicker.getHour())) + ":" + (mDateTimePicker.getMinute()<=9?String.valueOf("0"+mDateTimePicker.getMinute()):String.valueOf(mDateTimePicker.getMinute()))+" "+mDateTimePicker.getMeridiem();
editText.setText(result_string);
mDateTimeDialog.dismiss();
}
});
// Cancel the dialog when the "Cancel" button is clicked
((Button) mDateTimeDialogView.findViewById(R.id.CancelDialog)).setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
mDateTimeDialog.cancel();
}
});
// Reset Date and Time pickers when the "Reset" button is clicked
((Button) mDateTimeDialogView.findViewById(R.id.ResetDateTime)).setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
mDateTimePicker.reset();
}
});
// Setup TimePicker
// No title on the dialog window
mDateTimeDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
// Set the dialog content view
mDateTimeDialog.setContentView(mDateTimeDialogView);
// Display the dialog
mDateTimeDialog.show();
}
});
}
}
Source: Stackoverflow.com