Layoutinflator (layout service) in Android

This section continues to bring the LayoutInflater (layout service) in the Android system service. When it comes to layout, the first thing you can think of is to write a layout XML, then call Activity's setContentView () to load the layout, and then show it to the screen. Use Android's built-in pull parser to parse the layout. It is often used in Android to dynamically load layout or add controls. In this section, we will learn some of its usage in actual development~

A: a system service used to load the layout is to instantiate the view object corresponding to the layout XML file. It can't be used directly. You need to obtain the layoutinflater instance bound to the current context through getlayoutinflater() method or getsystemservice() method!

① There are three ways to get layoutinflator instances:

LayoutInflater inflater1 = LayoutInflater.from(this);  
LayoutInflater inflater2 = getLayoutInflater();  
LayoutInflater inflater3 = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE); 

PS: the latter two are actually the first method~

② How to load the layout:

public View inflate (int resource,ViewGroup root,boolean attachToRoot) 该方法的三个参数依次为:

①要加载的布局对应的资源id

②为该布局的外部再嵌套一层父布局,如果不需要的话,写null就可以了!

③是否为加载的布局文件的最外层套一层root布局,不设置该参数的话, 如果root不为null的话,则认为true 如果root为null的话,attachToRoot就没有作用了! root不为null,attachToRoot为true的话,会在加载的布局文件最外层嵌套一层root布局; 为false的话,则root失去作用! 简单理解就是:是否为加载的布局添加一个root的外层容器~!

③ Set the relevant properties through layoutinflator.layoutparams:

We have long been used to using XML to generate the layout we need, but in some specific cases, we need to use java code to dynamically add components or layouts to our layout!

However, it is not recommended that you completely use java code to write Android page layout. The first thing is that there will be more code, which is easy to be disordered for a long time, and it is not conducive to the separation of business. We still recommend using XML to complete the layout, and then modify the components through Java code. Of course, sometimes you may need to use java to add components dynamically!

——Step 1:

① Create container: LinearLayout ly = new LinearLayout (this);

② Create component: button btnone = new button (this);

——Step 2:

You can set relevant properties for containers or components: for example, LinearLayout. We can set the arrangement direction of components: ly. Setorientation (LinearLayout. Vertical); Components can also be: for example, button: btnone. Settext ("button 1"); For the method of setting attributes, please refer to the Android API. Generally, the attributes set in XML only need to be added in front: set, such as setpadding (left, top, right, bottom);

——Step 3:

To add a component or container to the container, we may need to set the adding location of the component or its size: we need to use a class: layoutparams, which can be regarded as an information package of the layout container! A class that encapsulates information such as location and size! First, show me how to set the size: (the previous LinearLayout can be changed according to different containers)

LinearLayout.LayoutParams lp1 = new LinearLayout.LayoutParams(  
        LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT); 

It's very simple. Then we'll go to the setting location. When setting the location, we usually only consider relativelayout! At this time, the addrule () method of layoutparams is used! You can add multiple addrules ()! Set the position of the component in the parent container,

For example, set the component's alignment method:

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);

For example, after setting btnone to be centered, btntwo should be located below btnone and 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("按钮1");  
        Button btnTwo = new Button(this);  
        btnTwo.setText("按钮2");  
        // 为按钮1设置一个id值  
        btnOne.setId(123);  
        // 设置按钮1的位置,在父容器中居中  
        RelativeLayout.LayoutParams rlp1 = new RelativeLayout.LayoutParams(  
                LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);  
        rlp1.addRule(RelativeLayout.CENTER_IN_PARENT);  
        // 设置按钮2的位置,在按钮1的下方,并且对齐父容器右面  
        RelativeLayout.LayoutParams rlp2 = new RelativeLayout.LayoutParams(  
                LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);  
        rlp2.addRule(RelativeLayout.BELOW,123);  
        rlp2.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);  
        // 将组件添加到外部容器中  
        rly.addView(btnTwo,rlp2);  
        rly.addView(btnOne,rlp1);  
        // 设置当前视图加载的View即rly  
        setContentView(rly);  
    }  
}  

——step 4:

Call setcontentview() method to load the layout object! In addition, if you want to remove the view in a container, you can call the container. Removeview (the component to be removed);

Operation screenshot:

There are two ways to dynamically add components. The difference is whether to set contentview (r.layout. Activity_main) first; The following is an example of adding a button in the following two different ways:

Write a layout file first: 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="我是xml文件加载的布局"/>  
      
</RelativeLayout> 

The first method does not require setcontentview() to load the layout file:

public class MainActivity extends Activity {  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        Button btnOne = new Button(this);  
        btnOne.setText("我是动态添加的按钮");  
        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("我是动态添加的按钮");  
        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 very simple. After creating the button, we create a layoutparams object to set the size of the button, and set the position of the button through the addrule () method!

The first method: the activity is loaded through the expand () method of layoutexpand_ Main layout, obtain the outer container, then add the addview button into the container, and finally setcontentview();

The second method: because we have loaded the layout through setcontentview(), we can find the outer container through findviewbyid, then addview, and finally setcontentview()!

In addition, the view node set by setcontentview () is the root node of the whole XML!

Next, let's change it. This time, the XML file is loaded! Add XML files dynamically! First write down the main layout file and 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="动态加载布局"/>
</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="我是Java代码加载的布局" />  
  
    <Button  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="我是布局里的一个小按钮" />  
  
</LinearLayout> 

Next, go to our mainactivity.java, where the XML layout is dynamically loaded:

public class MainActivity extends Activity {  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        //获得LayoutInflater对象;  
        final LayoutInflater inflater = LayoutInflater.from(this);    
        //获得外部容器对象  
        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) {  
                //加载要添加的布局对象  
                LinearLayout ly = (LinearLayout) inflater.inflate(  
                        R.layout.inflate,null,fa运行截图:

lse).findViewById(  
                        R.id.ly_inflate);  
                //设置加载布局的大小与位置  
                RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(    
                        LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);    
                lp.addRule(RelativeLayout.CENTER_IN_PARENT);    
                rly.addView(ly,lp);  
            }  
        });  
    }  
} 

Operation screenshot:

Code analysis:

① Get container object:

final RelativeLayout rly = (RelativeLayout) findViewById(R.id.RelativeLayout1);

② Get the inflator object, load the XML of the added layout at the same time, and find the outermost root node through findviewbyid

final LayoutInflater inflater = LayoutInflater.from(this);
LinearLayout ly = (LinearLayout) inflater.inflate(R.layout.inflate,false)
   .findViewById(R.id.ly_inflate);

③ Set size and location information for this container:

RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(  
               LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);  
       lp.addRule(RelativeLayout.CENTER_IN_PARENT);

④ Add to outer container:

rly.addView(ly,lp);

Finally, provide the source code of layoutinflator's inflate () method. If you are interested, you can see that it is actually pull parsing

public View inflate(XmlPullParser parser,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;    
    }    
} 

This section explains the layoutinflator (layout service) in Android and things related to dynamically loading views and controls. I believe it will help novice controls ~ OK, that's all. Thank you

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>