BaseAdapterやちょっと複雑なレイアウトしようとすると登場する inflater とは何者なのか?
2024.1.1
Inflater
inflate メソッドは、XMLレイアウトをコードとして扱って表示できるものです
カスタムViewを生成する以外にも、ListView、RecyclerView、ViewPager2などに使用されています
レイアウトXMLファイルからViewを作るには直接インスタンス化するのではなく、
Activity.getLayoutInflater()または
Context#getSystemService(Class)を使います
getLayoutInflater:
1 |
public LayoutInflater getLayoutInflater () |
Inflaterの使い方
getLayoutnflater()
について使い方を見てみます。
例えば activity_main.xml の中に LinearLayout を作ります。中は何もViewが入っていないのとサイズもView次第なので何も表示されません。この状態では他のViewのButtonとTextViewのみの表示となります。
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout ... > <Button ... /> <LinearLayout android:id="@+id/insert_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" /> <TextView ... /> </LinearLayout> |
この id が insert_layout の箇所に別のレイアウトXMLファイル、inflate_layout.xml を
inflate (int resource, ViewGroup root) を使って挿入します。
inflate_layout.xml
1 2 3 4 5 6 7 8 9 10 11 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout ... > <TextView ... /> <ImageView ..."/> </LinearLayout> |
View inflate (int resource, ViewGroup root)
resource | ID for an XML layout resource to load (e.g., R.layout.main_page) |
root | Optional view to be the parent of the generated hierarchy. This value may be null. |
このように使います。
1 2 3 4 5 6 7 |
LinearLayout linearLayout = findViewById(R.id.insert_layout); // inflate getLayoutInflater().inflate(R.layout.inflate_layout, linearLayout); // 削除 linearLayout.removeAllViews(); |
サンプルコード
これをまとめると
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
//package com.example.testinflate; import android.os.Bundle; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; import android.widget.Button; import android.widget.LinearLayout; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private LinearLayout linearLayout; private boolean flag = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); linearLayout = findViewById(R.id.insert_layout); TextView textView = findViewById(R.id.text); textView.setText(R.string.contents); Button button = findViewById(R.id.button); button.setOnClickListener(v -> { if (!flag) { getLayoutInflater().inflate(R.layout.inflate_layout, linearLayout); flag = true; } else { linearLayout.removeAllViews(); flag = false; } }); } } |
元になるレイアウトです。
LinearLayoutで作るとダイナミックな動きが出せますが
Constraintlayoutでまとめてみました
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#000" tools:context=".MainActivity"> <Button android:id="@+id/button" android:layout_width="150dp" android:layout_height="wrap_content" android:layout_margin="20dp" android:text="@string/button" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.05" /> <LinearLayout android:id="@+id/insert_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.2" /> <TextView android:id="@+id/text" android:textColor="#ff0" android:layout_margin="30dp" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.8" /> </androidx.constraintlayout.widget.ConstraintLayout> |
LinearLayoutだとこのような感じです
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp" android:orientation="vertical" android:background="#000" tools:context=".MainActivity"> <Button android:id="@+id/button" android:layout_width="150dp" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_margin="20dp" android:text="@string/button" /> <LinearLayout android:id="@+id/insert_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" /> <TextView android:id="@+id/text" android:textColor="#ff0" android:layout_margin="30dp" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> |
inflate_layout.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:text="@string/text" android:gravity="center" android:textColor="#ff0" android:textSize="30sp" android:layout_margin="10dp" android:layout_width="match_parent" android:layout_height="wrap_content"/> <ImageView android:src="@drawable/img" android:scaleType="centerCrop" android:layout_width="match_parent" android:layout_height="wrap_content" android:contentDescription="@string/description"/> </LinearLayout> |
strings.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<resources> <string name="app_name">TestInflate</string> <string name="button">Button</string> <string name="description">Yuka</string> <string name="text">Birthday Events!</string> <string name="contents"> "日付:\n" "20XX年05月22日\n" "会場:\n" "東京都新宿区山吹町 Bスタジオ\n\n" "第1部:10時00分~11時00分\n" "(手作りケーキ?お菓子を食べよう!)\n" "第2部:11時15分~12時15分\n" "(ゆかちぃとゲーム!<頭脳編>)\n" "握手会\n" "12時30分~13時00分\n" "(握手会:その1)\n" "第3部:" "14時00分~15時00分\n" "(ゆかちぃとゲーム!<アクティブ編>)\n" "第4部:" "15時15分~16時15分"</string> </resources>じ |
実行させると、
ボタンをタップすると
画像を有したXMLレイアウトが差し込まれます
サンプル動画
LinearLayout を使った古い動画です
1 2 3 4 5 6 7 8 9 10 11 |
ViewGroup viewGroup = findViewById(R.id.root); Context context = getApplicationContext(); LayoutInflater inflater = LayoutInflater.from(context); // LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); // inflate inflater.inflate(R.layout.inflate_layout, viewGroup); // 削除 viewGroup.removeAllViews(); |
-->
References:
LayoutInflater | Android Developers
getLayoutInflater