LayoutInflater (service de mise en page)


Introduction à cette section :

Cette section continue de présenter le LayoutInflater (service de mise en page) dans le service système Android. En matière de mise en page, tout le monde est le premier à le faire. Ce à quoi vous pouvez penser est d'écrire un XML de mise en page, puis d'appeler setContentView() d'Activity pour charger la mise en page, puis de l'afficher. Sur l'écran, n'est-ce pas ? En fait, la couche inférieure est toujours le LayoutInflater, qui est analysé à l'aide de l'analyseur Pull intégré à Android. mise en page. Généralement, il est plus couramment utilisé sous Android pour charger dynamiquement des mises en page ou ajouter des contrôles. Dans cette section, nous apprendrons comment l'utiliser dans le développement réel. Quelques utilisations~

Document officiel de l'API :LayoutInflater


Introduction connexe de LayoutInflater


1) Qu'est-ce que c'est que la mise en page ?

Réponse : Un service système utilisé pour charger la mise en page consiste à instancier l'objet View correspondant au fichier XML de mise en page. Il ne peut pas être utilisé directement. Vous devez utiliser la méthode getLayoutInflater() ou la méthode getSystemService() pour obtenir le contenu lié au contexte actuel Instance LayoutInflater !


2) Utilisation de LayoutInflater

①Trois façons d'obtenir l'instance LayoutInflater :

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

PS : Cette dernière deux utilisent en fait la première méthode en bas~

②La méthode de chargement de la mise en page :

public View inflate (ressource int, racine ViewGroup, booléen attachToRoot) Les trois paramètres de cette méthode sont :

①L'identifiant de ressource correspondant à la mise en page à charger

② Imbriquer une autre couche de mise en page parent en dehors de la mise en page Si ce n'est pas nécessaire, écrivez Null, c'est bien !

③ S'il faut définir une mise en page racine comme couche la plus externe du fichier de mise en page chargé. Si ce paramètre n'est pas défini, Si root n'est pas nul, la valeur par défaut est true Si root est nul, attachToRoot n’a aucun effet ! Si root n'est pas nul et que attachToRoot est vrai, une mise en page racine sera imbriquée dans la couche la plus externe du fichier de mise en page chargé ; Si c'est faux, root perdra sa fonction ! La compréhension simple est la suivante : S'il faut ajouter un conteneur externe racine pour la mise en page chargée~!


③Définissez les attributs associés via LayoutInflater.LayoutParams :

Par exemple, RelativeLayout peut également ajouter des règles via la méthode addRule, qui consiste à définir la position : fait-il référence au conteneur parent ? Ou se référer au contrôle enfant ? Ou définissez la marge, etc., c'est à vous de décider ~


2. Disposition de chargement du code Java pur

Nous sommes habitués depuis longtemps à utiliser XML pour générer. ce dont nous avons besoin de mise en page, mais dans certains cas spécifiques, nous Nous devons utiliser du code Java pour ajouter dynamiquement des composants ou des mises en page à notre mise en page !

Mais il n'est pas recommandé d'utiliser entièrement du code Java pour écrire la mise en page Android. Le premier point est qu'il y aura beaucoup de code. Il est facile de se tromper et n'est pas propice à la séparation des activités. Nous recommandons toujours d'utiliser XML pour terminer la mise en page, puis de l'adopter. Le code Java modifie les composants à l'intérieur. Bien sûr, vous devrez parfois utiliser Java pour ajouter dynamiquement des composants !

Processus de mise en page de chargement de code Java pur :


——Étape 1 :

Créer conteneur:LinearLayout ly = new LinearLayout(this);

Créer un composant:Button btnOne = new Button(this);

— — Étape 2 :

Vous pouvez définir les propriétés associées pour le conteneur ou le composant : Par exemple : LinearLayout, nous pouvons définir le sens de disposition du composant : ly.setOrientation(LinearLayout.VERTICAL);Et le composant peut également être : Par exemple, Button : btnOne.setText("Button 1");Pour la méthode de définition des attributs, veuillez vous référer à l'API Android. Habituellement, les attributs définis en XML doivent uniquement être ajoutés devant : set, tels que . setPadding (gauche, haut, droite, bas) ;

——Étape 3 :

Ajoutez le composant ou le conteneur au conteneur. il faudra peut-être définir la position d'ajout du composant, ou définir sa taille : Nous devons utiliser une classe : LayoutParams, nous pouvons la considérer comme un package d'informations sur la position et la taille du conteneur d'encapsulation ! Une classe en attente d'informations ! Démontrez d'abord la méthode de réglage de la taille : (le LinearLayout précédent peut être modifié en fonction de différents conteneurs)

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

est très simple, puis arrive à la position de réglage. , nous considérons généralement que c'est juste RelativeLayout ! Actuellement, la méthode addRule() de LayoutParams est utilisée ! Vous pouvez ajouter plusieurs addRule() ! Définissez la position du composant dans le conteneur parent,

Par exemple, Définissez la méthode d'alignement du composant:

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

Reportez-vous à la méthode d'alignement de autres composants : (Un inconvénient est que vous devez définir manuellement un identifiant pour le composant de référence, qui est manuellement!!!!) Par exemple : après avoir défini btnOne au centre, laissez BtnTwo se trouver en dessous de btnOne et à droite du conteneur parent

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

——étape 4 :

Appel ! la méthode setContentView() pour charger la mise en page Juste l'objet ! De plus, si vous souhaitez supprimer une View dans un conteneur, vous pouvez appeler le conteneur.removeView(composant à supprimer);

Exécuter une capture d'écran :

1.png


3. Le code Java ajoute dynamiquement des contrôles ou une mise en page XML

Le deuxième point que nous avons expliqué est d'utiliser du code Java pur pour charger le mise en page En fait, elle n'est pas beaucoup utilisée, elle est le plus souvent dynamique. Ajoutez un contrôle View et chargez dynamiquement la mise en page XML !

1) Le code Java ajoute dynamiquement View

Il existe deux façons d'ajouter dynamiquement des composants. La différence est de savoir si vous devez d'abord setContentView(. R.layout .activity_main); Ce qui suit montre deux méthodes d'écriture différentes pour ajouter un bouton :

Écrivez d'abord un fichier de mise en page : 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>

La première méthode n'est pas SetContentView () est requis pour charger le fichier de mise en page en premier :

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

Le deuxième type ne nécessite pas setContentView() pour charger le fichier de mise en page en premier :

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

Résumé de l'analyse

Le code est très simple. Après avoir créé le bouton, nous avons créé un objet LayoutParams pour définir la taille du bouton. La position du bouton est définie via la méthode addRule() !

La première méthode  : chargez la mise en page Activity_main via la méthode inflate() de LayoutInflate et obtenez le conteneur externe. Ensuite, addView ajoute le bouton dans le conteneur, et enfin setContentView();

Deuxième méthode : Parce que nous avons chargé la mise en page via la méthode setContetView(), à ce stade, nous pouvons passer findViewById trouve le conteneur externe, puis addView et enfin setContentView() !

De plus, le nœud de vue défini par setContentView() est le nœud racine de l'ensemble du XML !


2) Le code Java charge dynamiquement la mise en page XML

Ensuite, modifions-le, cette fois en chargeant le fichier XML !Ajoutez dynamiquement le fichier XML ! Notez d'abord le fichier de mise en page principal et le fichier de mise en page chargé dynamiquement :

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>

Ensuite, allez dans notre MainActivity.java et chargez dynamiquement la mise en page XML ici :

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, false).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);  
            }  
        });  
    }  
}

Exécutez la capture d'écran  :

2.gif

Analyse du code :

①Obtenir l'objet conteneur:

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

②Obtenir l'objet Inflater et chargez-le en même temps Dans le XML de la mise en page ajoutée, recherchez le nœud racine le plus externe via findViewById

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

③ Définissez les informations de taille et de position pour ce conteneur :

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

④Ajouter au conteneur externe :

rly.addView(ly,lp);

4. Code source de la méthode inflate() de LayoutInflater

Enfin , le gonflement de LayoutInflater est fourni Le code source de la méthode (), si vous êtes intéressé, vous pouvez y jeter un oeil~, il s'agit en fait juste d'une analyse Pull~

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

Résumé de cette section :

Cette section explique à tout le monde LayoutInflater (service de mise en page) dans Android, ainsi que le chargement dynamique des vues et des contrôles. Choses connexes, je pense que cela sera utile aux amis qui débutent dans les contrôles~D'accord, c'est tout, merci~3.gif