10.8 LayoutInflater (Layout Service)
Category Android Basic Tutorial
Introduction:
>
This section continues with the LayoutInflater (Layout Service) in Android system services. When it comes to layouts, you might immediately think of writing an XML layout, then using setContentView()
in an Activity to load and display it on the screen. However, under the hood, this process still relies on LayoutInflater, which uses Android's built-in Pull parser to parse the layout. LayoutInflater is commonly used in Android for dynamically loading layouts or adding controls. In this section, we will explore some practical uses of LayoutInflater in development.
Official API Documentation: LayoutInflater
1. Introduction to LayoutInflater
1) What is LayoutInflater?
>
Answer: A system service for loading layouts, which instantiates View objects corresponding to Layout XML files. It cannot be used directly and must be obtained via the getLayoutInflater()
or getSystemService()
methods to get an instance of LayoutInflater bound to the current Context!
2) Usage of LayoutInflater
① Three methods to get an instance of LayoutInflater:
LayoutInflater inflater1 = LayoutInflater.from(this);
LayoutInflater inflater2 = getLayoutInflater();
LayoutInflater inflater3 = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
Note: The latter two methods actually use the first method under the hood.
② Method to load a layout:
>
public View inflate (int resource, ViewGroup root, boolean attachToRoot) The method has three parameters:
① The resource ID of the layout to be loaded.
② A parent layout to wrap around the loaded layout. If not needed, pass null
.
③ Whether to wrap the outermost layer of the loaded layout file with a root layout. If this parameter is not set, it defaults to true
if root is not null
, and has no effect if root is null
. If root is not null
and attachToRoot is true
, the loaded layout will be wrapped with a root layout; if false
, the root will have no effect. Simply put, it determines whether to add an outer container (root) to the loaded layout.
③ Setting attributes via LayoutInflater.LayoutParams:
>
For example, a RelativeLayout can add rules using the addRule
method to set positions: whether relative to the parent container, another child control, or to set margins, etc. This is determined by your needs.
2. Loading Layout with Pure Java Code
>
We are accustomed to using XML to generate the layouts we need, but in certain cases, we need to dynamically add components or layouts using Java code.
However, it is not recommended to completely use Java code to create Android page layouts. Firstly, the code can become lengthy and complex, leading to confusion and making it difficult to separate business logic. We recommend using XML for layout and modifying components within it using Java code. However, there are times when dynamic addition of components using Java is necessary.
Process of loading layout with pure Java code:
——Step 1:
① Create a container: LinearLayout ly = new LinearLayout(this);
② Create a component: Button btnOne = new Button(this);
——Step 2:
Set attributes for the container or components:
For example, for LinearLayout, you can set the orientation: ly.setOrientation(LinearLayout.VERTICAL);
For components like Button: btnOne.setText("Button 1");
Refer to the Android API for setting attributes; usually, XML attributes can be set by adding set
before the attribute name, such as setPadding(left, top, right, bottom);
——Step 3:
Add components or containers to the container. You may need to set the position or size of the components:
You will need a class called LayoutParams
, which can be seen as a package of information about the layout container, encapsulating position and size information. Here’s an example of setting size:
LinearLayout.LayoutParams lp1 = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
For setting positions, typically we consider RelativeLayout
:
You use the addRule()
method of LayoutParams
. You can add multiple addRule()
calls. For example, to set the alignment of a component within its parent container:
RelativeLayout rly = new RelativeLayout(this);
RelativeLayout.LayoutParams lp2 = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lp2.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
Button btnOne = new Button(this);
rly.addView(btnOne, lp2);
To align relative to another component:
(Note: You need to manually set an ID for the reference component)
For example: After setting btnOne
to center, place btnTwo
below btnOne
and align to the right of the parent container:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
RelativeLayout rly = new RelativeLayout(this);
Button btnOne = new Button(this);
btnOne.setText("Button 1");
Button btnTwo = new Button(this);
btnTwo.setText("Button 2");
// Set an ID for button 1
btnOne.setId(123);
// Set position for button 1, centered in the parent container
RelativeLayout.LayoutParams rlp1 = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
rlp1.addRule(RelativeLayout.CENTER_IN_PARENT);
// Set position for button 2, below button 1 and aligned to the right of the parent container
RelativeLayout.LayoutParams rlp2 = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
rlp2.addRule(RelativeLayout.BELOW, 123);
rlp2.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
// Add components to the outer container
rly.addView(btnTwo, rlp2);
rly.addView(btnOne, rlp1);
// Set the current view to load rly
setContentView(rly);
}
}
——Step 4:
Call setContentView()
to load the layout object.
Additionally, if you want to remove a View from a container, you can call container.removeView(component_to_remove);
Screenshot:
3. Dynamically Adding Controls or XML Layouts with Java Code
>
In the second point, we explained loading layouts using pure Java code, which is not commonly used. More often, we dynamically add View controls and dynamically load XML layouts.
1) Dynamically adding View with Java code
There are two ways to dynamically add components, differing in whether you need to call setContentView(R.layout.activity_main)
first. Below is an example of adding a Button using both methods:
First, write a layout file: activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/RelativeLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/txtTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="I am a layout loaded from an XML file"/>
</RelativeLayout>
First method without calling setContentView() first:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Button btnOne = new Button(this);
btnOne.setText("I am a dynamically added button");
RelativeLayout.LayoutParams lp2 = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lp2.addRule(RelativeLayout.CENTER_IN_PARENT);
LayoutInflater inflater = LayoutInflater.from(this);
RelativeLayout rly = (RelativeLayout) inflater.inflate(
R.layout.activity_main, null)
.findViewById(R.id.RelativeLayout1);
rly.addView(btnOne, lp2);
setContentView(rly);
}
}
The second method does not require setContentView() to load the layout file first:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnOne = new Button(this);
btnOne.setText("I am a dynamically added button");
RelativeLayout.LayoutParams lp2 = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lp2.addRule(RelativeLayout.CENTER_IN_PARENT);
RelativeLayout rly = (RelativeLayout) findViewById(R.id.RelativeLayout1);
rly.addView(btnOne, lp2);
}
}
Analysis Summary:
>
The code is simple. After creating the button, we create a LayoutParams object to set the Button's size, and then use the addRule() method to set the Button's position!
First Method: By using LayoutInflate's inflate() method to load the activity_main layout, we obtain the outer container, then add the button to the container with addView, and finally call setContentView().
Second Method: Since we have already loaded the layout using the setContentView() method, we can now find the outer container using findViewById, then add the button with addView, and finally call setContentView().
Additionally, the setContentView() sets the view node to the root node of the entire XML.
2) Dynamically Loading XML Layout in Java Code
Next, we'll switch to loading an XML file dynamically! Dynamically adding an XML file! First, let's write the main layout file and the dynamically loaded layout file:
activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/RelativeLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/btnLoad"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Load Layout Dynamically"/>
</RelativeLayout>
inflate.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="match_parent"
android:gravity="center"
android:orientation="vertical"
android:id="@+id/ly_inflate" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="I am a layout loaded by Java code" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="I am a small button in the layout" />
</LinearLayout>
Next, in our MainActivity.java, we dynamically load the XML layout:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Obtain the LayoutInflater object;
final LayoutInflater inflater = LayoutInflater.from(this);
// Obtain the outer container object
final RelativeLayout rly = (RelativeLayout) findViewById(R.id.RelativeLayout1);
Button btnLoad = (Button) findViewById(R.id.btnLoad);
btnLoad.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Load the layout object to be added
LinearLayout ly = (LinearLayout) inflater.inflate(
R.layout.inflate, null, false).findViewById(
R.id.ly_inflate);
// Set the size and position of the loaded layout
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lp.addRule(RelativeLayout.CENTER_IN_PARENT);
rly.addView(ly, lp);
}
});
}
}
Code Analysis:
>
① Obtain the container object:
final RelativeLayout rly = (RelativeLayout) findViewById(R.id.RelativeLayout1);
② Obtain the Inflater object, and load the XML of the layout to be added, find the outermost root node via findViewById:
final LayoutInflater inflater = LayoutInflater.from(this);
LinearLayout ly = (LinearLayout) inflater.inflate(R.layout.inflate, null, false)
.findViewById(R.id.ly_inflate);
③ Set the size and position information for this container:
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lp.addRule(RelativeLayout.CENTER_IN_PARENT);
④ Add to the outer container:
rly.addView(ly, lp);
4. Source Code of LayoutInflater's inflate() Method
>
Finally, here is the source code of LayoutInflater's inflate() method for those interested. It's essentially just Pull parsing.
public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
synchronized (mConstructorArgs) {
final AttributeSet attrs = Xml.asAttributeSet(parser);
mConstructorArgs[0] = mContext;
View result = root;
try {
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG &&
type != XmlPullParser.END_DOCUMENT) {
}
if (type != XmlPullParser.START_TAG) {
throw new InflateException(parser.getPositionDescription()
+ ": No start tag found!");
}
final String name = parser.getName();
if (TAG_MERGE.equals(name)) {
if (root == null || !attachToRoot) {
throw new InflateException("merge can be used only with a valid "
+ "ViewGroup root and attachToRoot=true");
}
rInflate(parser, root, attrs);
} else {
View temp = createViewFromTag(name, attrs);
ViewGroup.LayoutParams params = null;
if (root != null) {
params = root.generateLayoutParams(attrs);
if (!attachToRoot) {
temp.setLayoutParams(params);
}
}
rInflate(parser, temp, attrs);
if (root != null && attachToRoot) {
root.addView(temp, params);
}
if (root == null || !attachToRoot) {
result = temp;
}
}
} catch (XmlPullParserException e) {
InflateException ex = new InflateException(e.getMessage());
ex.initCause(e);
throw ex;
} catch (IOException e) {
InflateException ex = new InflateException(
parser.getPositionDescription()
+ ": " + e.getMessage());
ex.initCause(e);
throw ex;
}
return result;
}
}
Summary of This Section:
This section explains Android's LayoutInflater (layout service) and how to dynamically load views and widgets. It is hoped that this will be helpful for beginners learning about widgets. That's all for now, thank you.
- 1.0 Android Basic Introduction Tutorial
- 1.0.1 2015 Latest Android Basic Introduction Tutorial Table of Contents
- 1.1 Background and System Architecture Analysis
- 1.2 Development Environment Setup
- 1.2.1 Using Eclipse + ADT + SDK to Develop Android APP
- 1.2.2 Using Android Studio to Develop Android APP
- 1.3 Solving SDK Update Issues
- 1.4 Genymotion Emulator Installation
- 1.5.1 Git Tutorial: Basic Operations of Local Repository
- 1.5.2 Git: Using GitHub to Build Remote Repository
- 1.6 How to Play with 9-Patch Images
- 1.7 Interface Prototype Design
- 1.8 Project Source Analysis (Various Files, Resource Access)
- 1.9 Android Program Signing and Packaging
- 1.11 Decompiling APK to Obtain Code & Resources
- 2.1 Concepts of View and ViewGroup
- 2.2.1 LinearLayout (Linear Layout)
- 2.2.2 RelativeLayout (Relative Layout)
- 2.2.3 TableLayout (Table Layout)
- 2.2.4 FrameLayout (Frame Layout)
- 2.2.5 GridLayout (Grid Layout)
- 2.2.6 AbsoluteLayout (Absolute Layout)
- 2.3.1 TextView (Text View) Detailed Explanation
- 2.3.2 EditText (Input Box) Detailed Explanation
- 2.3.3 Button and ImageButton
- 2.3.4 ImageView (Image View)
- 2.3.5 RadioButton (Radio Button) & Checkbox (Checkbox)
- 2.3.6 ToggleButton and Switch
- 2.3.7 ProgressBar (Progress Bar)
- 2.3.8 SeekBar (Drag Bar)
- 2.3.9 RatingBar (Star Rating Bar)
- 2.4.1 ScrollView (Scroll Bar)
- 2.4.2 Date & Time Components (Part 1)
- 2.4.3 Date & Time Components (Part 2)
- 2.4.4 Adapter Basics
- 2.4.5 Simple Usage of ListView
- 2.4.6 BaseAdapter Optimization
- 2.4.7 Focus Issues with ListView
- 2.4.8 Solving Checkbox Misalignment Issues in ListView
- 2.4.9 Data Update Issues with ListView
- 2.5.0 Building a Reusable Custom BaseAdapter
- 2.5.1 Implementing Multi-Layout ListView Items
- 2.5.2 Basic Usage of GridView (Grid View)
- 2.5.3 Basic Usage of Spinner (List Option Box)
- 2.5.4 Basic Usage of AutoCompleteTextView (Auto-Complete Text Box)
- 2.5.5 Basic Usage of ExpandableListView (Collapsible List)
- 2.5.6 Basic Usage of ViewFlipper (Flip View)
- 2.5.7 Basic Usage of Toast
- 2.5.8 Detailed Explanation of Notification (Status Bar Notification) ``` -2.5.9 Detailed Explanation of AlertDialog
-2.6.0 Basic Usage of Other Common Dialogs
-2.6.1 Basic Usage of PopupWindow
-2.6.3 Simple Usage of ViewPager
-2.6.4 Simple Usage of DrawerLayout
-3.1.1 Event Handling Mechanism Based on Listeners
-3.2 Event Handling Mechanism Based on Callbacks
-3.3 Analysis of Handler Message Passing Mechanism
-3.4 TouchListener vs OnTouchEvent + Multi-touch
-3.5 Listening for Content Changes in EditText
-3.6 Responding to System Setting Events (Configuration Class)
-3.7 AsyncTask Asynchronous Tasks
-4.1.1 Introduction to Activity
-4.1.2 Getting Started with Activity
-4.2.1 Introduction to Service
-4.3.1 Introduction to BroadcastReceiver
-4.3.2 In-depth BroadcastReceiver
-4.4.1 Introduction to ContentProvider
-4.4.2 Further Exploration of ContentProvider - Document Provider
-4.5.2 Passing Complex Data with Intent
-5.1 Basic Overview of Fragment
-5.2.1 Fragment Example - Bottom Navigation Bar Implementation (Method 1)
-5.2.2 Fragment Example - Bottom Navigation Bar Implementation (Method 2)
-5.2.3 Fragment Example - Bottom Navigation Bar Implementation (Method 3)
-5.2.4 Fragment Example - Bottom Navigation Bar + ViewPager Page Swipe
-5.2.5 Fragment Example - Simple Implementation of News/Shopping App List Fragment
-6.1 Data Storage and Access - File Storage and Reading
-6.2 Data Storage and Access - SharedPreferences for Saving User Preferences
-6.3.1 Data Storage and Access - Introduction to SQLite Database
-6.3.2 Data Storage and Access - Further Exploration of SQLite Database
-7.1.1 Android Network Programming and Learning HTTP Protocol
-7.1.2 Learning Android HTTP Request and Response Headers
-7.1.3 Android HTTP Request Method: HttpURLConnection
-7.1.4 Android HTTP Request Method: HttpClient
-7.2.1 Android XML Data Parsing
-7.2.2 Android JSON Data Parsing
-7.3.2 Android File Download (1)
-7.3.3 Android File Download (2)
-7.4 Android Calling WebService
-7.5.2 WebView and JavaScript Interaction Basics
-7.5.3 WebView Considerations After Android 4.4
-7.5.6 WebView Handling Webpage Error Codes
-7.6.1 Socket Learning Network Basics Preparation
-7.6.2 TCP Protocol Based Socket Communication (1)
-7.6.3 TCP Protocol Based Socket Communication (2)
-7.6.4 UDP Protocol Based Socket Communication
-8.1.1 Summary of 13 Drawable Types in Android Part 1
-8.1.2 Summary of 13 Drawable Types in Android Part 2
-8.1.3 Summary of 13 Drawable Types in Android Part 3
-8.2.1 Comprehensive Analysis of Bitmap Part 1
-8.2.2 OOM Issues Caused by Bitmap
-8.3.1 Detailed Explanation of Three Drawing Tools
-8.3.2 Drawing Class Practical Examples
-8.3.4 Paint API - Xfermode and PorterDuff Detailed Explanation (Part 1)
-8.3.5 Paint API - Xfermode and PorterDuff Detailed Explanation (Part 2)
-8.3.6 Paint API - Xfermode and PorterDuff Detailed Explanation (Part 3)
-8.3.7 Paint API - Xfermode and PorterDuff Detailed Explanation (Part 4)
-8.3.8 Paint API - Xfermode and PorterDuff Detailed Explanation (Part 5)
-8.3.9 Paint API - ColorFilter (Color Filter) (1/3)
-8.3.10 Paint API - ColorFilter (Color Filter) (2/3)
-8.3.11 Paint API - ColorFilter (Color Filter) (3/3)
-8.3.12 Paint API - PathEffect (Path Effect)
-8.3.13 Paint API - Shader (Image Rendering)
-8.3.14 Paint Enum/Constants and ShadowLayer Shadow Effect
- 8.3.15 Paint API - Typeface (Font Style)
- 8.3.16 Canvas API Detailed Explanation (Part 1)
- 8.3.17 Canvas API Detailed Explanation (Part 2) - Clipping Methods Collection
- 8.3.18 Canvas API Detailed Explanation (Part 3) - Matrix and drawBitmapMesh
- 8.4.1 Android Animation Collection - Frame Animation
- 8.4.2 Android Animation Collection - Tween Animation
- 8.4.3 Android Animation Collection - Property Animation - Introduction
- 8.4.4 Android Animation Collection - Property Animation - Further Exploration
- 9.1 Using SoundPool to Play Sound Effects (Duang~)
- 9.2 MediaPlayer to Play Audio and Video
- 9.3 Using Camera to Take Photos
- 9.4 Using MediaRecord to Record Audio
- 10.1 TelephonyManager (Phone Manager)
- 10.2 SmsManager (SMS Manager)
- 10.3 AudioManager (Audio Manager)
- 10.4 Vibrator (Vibrator)
- 10.5 AlarmManager (Alarm Service)
- 10.6 PowerManager (Power Service)
- 10.7 WindowManager (Window Management Service)
- 10.8 LayoutInflater (Layout Service)
- 10.9 WallpaperManager (Wallpaper Manager)
- 10.10 Sensor Topic (1) - Introduction
- 10.11 Sensor Topic (2) - Orientation Sensor
- 10.12 Sensor Topic (3) - Accelerometer/Gyroscope Sensor
- 10.12 Sensor Topic (4) - Understanding Other Sensors
- 10.14 Android GPS Introduction
- 11.0《2015最新Android基础入门教程》Completion Celebration~
- 12.1 Android Practice: DrySister Viewing Girls App (Version 1) - Project Setup and Simple Implementation
- 12.2 DrySister Viewing Girls App (Version 1) - Parsing Backend Data
- 12.3 DrySister Viewing Girls App (Version 1) - Image Loading Optimization (Writing an Image Caching Framework)
- 12.4 DrySister Viewing Girls App (Version 1) - Adding Data Caching (Introducing SQLite)
- 12.5 DrySister Viewing Girls App (Version 1) - Code Review, Adjustment, and Logging Class Writing
- 12.6 DrySister Viewing Girls App (Version 1) - Icon Creation, Obfuscation, Signing, APK Slimming, App Release
WeChat Subscription
English: