AndroidのLayoutInflater(レイアウトサービス)

このセクションの概要:

 このセクションでは引き続き、Android システム サービスに LayoutInflater (レイアウト サービス) を導入します。レイアウトに関して最初に思いつくのは、レイアウト XML を作成し、次にアクティビティの setContentView() を呼び出してレイアウトをロードし、その後、それを画面に表示しますよね? 実際、最下層は依然として LayoutInflater であり、Android の組み込みプル パーサーを使用してレイアウトを解析します。Android では動的にレイアウトを読み込んだり、コントロールを追加したりすることが一般的ですが、このセクションでは実際の開発での使用方法をいくつか学びます~

公式 API ドキュメント: LayoutInflater


1. LayoutInflater の概要


1) レイアウトとは一体何ですか?

回答: レイアウトをロードするためのシステム サービスは、レイアウトXMLファイルに対応する View オブジェクトをインスタンス化するものですが、これを直接使用することはできません。getLayoutInflater () メソッドまたは getSystemService () を通じて現在のContextバインドされた LayoutInflater インスタンスを取得する必要があります。方法!


2) LayoutInflaterの使用方法

①LayoutInflaterインスタンスを取得する3つの方法:

LayoutInflater inflater1 = LayoutInflater.from(this);  
LayoutInflater インフレータ 2 = getLayoutInflater();  
LayoutInflater inflater3 = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);

PS: 後の 2 つは、実際には一番下の最初のメソッドです~

②レイアウトの読み込み方法

public View  inflate  (int resource, ViewGroup root, booleanattachToRoot) このメソッドの 3 つのパラメータは次のとおりです。

① 読み込むレイアウトに対応するリソースID

② レイアウトの外側に親レイアウトをもう一つ入れ子にする 不要な場合はnullを書くだけ!

③ロードされたレイアウト ファイルの最外層にルート レイアウトのレイヤを追加するかどうか、このパラメータが設定されていない場合、ルートが null でない場合、デフォルトは true ルートが null の場合、attachToRoot は効果がありません! root は null ではありません、attachToRoot が true の場合、ルート レイアウトのレイヤーは、ロードされたレイアウト ファイルの最も外側のレイヤーにネストされます。false の場合、ルートは何の効果もありません! 簡単に理解すると、ロードされたレイアウトにルートの外部コンテナーを追加するかどうかがわかります。 ~!


③ LayoutInflater.LayoutParams を通じて関連プロパティを設定します

たとえば、RelativeLayout は、addRule メソッドを通じてルールを追加することもできます。これは、位置を設定するためのものです。親コンテナを参照しているかどうかを確認します。それとも子コントロールを参照しますか? またはマージンを設定するなど、これはあなた次第です〜


2. Pure Java コードの読み込みレイアウト

私たちは長い間、XML を使用して必要なレイアウトを生成することに慣れてきましたが、特定のケースでは、コンポーネントまたはレイアウトをレイアウトに動的に追加するために Java コードを使用する必要があることがあります。

ただし、Java コードを使用して Android ページ レイアウトを記述することはお勧めできません。第一の点は、コードが多すぎて、しばらくすると混乱しやすくなり、ページ レイアウトの分離に役立ちません。ビジネス。レイアウトを完成させるには XML を使用し、その後 Java コードを使用することをお勧めします。もちろん、コンポーネントは変更されますが、コンポーネントを動的に追加するために Java を使用する必要がある場合もあります。

Pure Java コードのロード レイアウトの流れ:


——ステップ1

コンテナの作成:LinearLayout ly = new LinearLayout(this);

コンポーネントの作成: Button btnOne = new Button(this);

- ステップ2:

コンテナーまたはコンポーネントの関連プロパティを設定できます: 例: LinearLayout、コンポーネントの配置方向を設定できます: ly.setOrientation(LinearLayout.VERTICAL); コンポーネントは次のこともできます: Button: btnOne.setText("Button 1") );設定について 属性のメソッドは Android API にありますが、通常 xml で設定する属性はsetPadding (left,top,right,bottom); のように set の前に追加するだけです。 

——ステップ3:

コンポーネントまたはコンテナをコンテナに追加します。このとき、コンポーネントを追加する場所やサイズを設定する必要がある場合があります。クラス LayoutParams を使用する必要があります。これは、コンポーネントの情報パッケージとみなすことができます。レイアウト コンテナ! カプセル化 位置やサイズなどの情報のクラス! 最初にサイズを設定する方法を示します: (以前の LinearLayout はさまざまなコンテナに応じて変更できます)

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

非常に簡単ですが、この設定位置にたどり着きました! 位置を設定するときは、通常は RelativeLayout だけを考慮します! このとき、LayoutParams の addRule( ) メソッドを使用します! addRule( ) は複数追加できます! 親コンテナ内のコンポーネントの位置を設定します。

たとえば、コンポーネントの位置合わせ方法を設定します

RelativeLayout rly = new RelativeLayout(this);  
RelativeLayout.LayoutParams lp2 = new RelativeLayout.LayoutParams(   
                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);  
lp2.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);  
ボタン btnOne = 新しいボタン (これ);  
rly.addView(btnOne, lp2);

他のコンポーネントの位置合わせ方法を参照してください: (欠点があります。つまり、参照コンポーネントの ID を手動で設定する必要があります。これは手動です!!!!) 例: btnOne を中央に設定した後、BtnTwo を配置します。 btnOne の下、親コンテナの右側に配置してください。

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");   
        // ボタン 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);   
        // 現在のビューによってロードされるビューを rly として設定します  
        setContentView(rly);   
    }   
}  

——ステップ4:

setContentView() メソッドを呼び出すだけで、レイアウト オブジェクトをロードできます! さらに、コンテナ内のビューを削除したい場合は、コンテナを呼び出すことができます

スクリーンショットを実行します


3. Java コードによりコントロールまたは XML レイアウトが動的に追加されます

2 番目のポイントでは、レイアウトを読み込むための Pure Java コードの使用について説明しましたが、実際にはあまり使用されません。より頻繁に使用されるのは、View コントロールを動的に追加し、XML レイアウトを動的に読み込むためです。

1) Java コードによりビューが動的に増加します。

コンポーネントを動的に追加するには 2 つの方法があります。違いは、最初にsetContentView(R.layout.activity_main)を行う必要があるかどうかです。以下は、2 つの異なる方法でボタンを追加する例を示しています。

最初にレイアウト ファイル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>  

最初の方法では、最初にレイアウト ファイルをロードするために setContentView() を必要としません。

public class MainActivity extends Activity {   
    @Override   
    protected void onCreate(Bundle SavedInstanceState) {   
        super.onCreate(savedInstanceState);  
        ボタン btnOne = 新しいボタン (これ);  
        btnOne.setText("我是动态追加的按钮");  
        RelativeLayout.LayoutParams lp2 = new RelativeLayout.LayoutParams(     
                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);    
        lp2.addRule(RelativeLayout.CENTER_IN_PARENT);    
        LayoutInflater インフレータ = LayoutInflater.from(this);  
        RelativeLayout rly = (RelativeLayout) inflater.inflate(   
                R.layout.activity_main, null)   
                .findViewById(R.id.RelativeLayout1);   
        rly.addView(btnOne,lp2);  
        setContentView(rly);  
    }   
}

2 番目の方法では、最初にレイアウト ファイルをロードするために setContentView() を必要としません。

public class MainActivity extends Activity {   
    @Override   
    protected void onCreate(Bundle SavedInstanceState) {   
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        ボタン btnOne = 新しいボタン (これ);  
        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);  
    }   
}

分析の概要:

コードは非常にシンプルで、ボタンを作成した後、LayoutParams オブジェクトを作成して Button のサイズを設定し、addRule() メソッドで Button の位置を設定しました。

最初の方法: LayoutInflate の inflate() メソッドを通じて activity_main レイアウトをロードし、外側のコンテナを取得し、次に addView でコンテナにボタンを追加し、最後に setContentView();

2 番目の方法: setContetView() メソッドを通じてレイアウトをロードしたため、findViewById、addView、最後に setContentView() を通じて外側のコンテナを見つけることができます。

また、この setContentView() に関しては、設定するビュー ノードが XML 全体のルート ノードになります。


2) Java コードが XML レイアウトを動的にロードします。

次に、別のレイアウトを変更して、今度は xml ファイルをロードしてみましょう! xml ファイルを動的に追加します! まず、メイン レイアウト ファイルと動的にロードされるレイアウト ファイルを書き留めます。

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" > 
    <ボタン
        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>

次に、MainActivity.javaに移動して、ここで XML レイアウトを動的にロードします。

public class MainActivity extends Activity {   
    @Override   
    protected void onCreate(Bundle SavedInstanceState) {   
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        //获得LayoutInflater对象;  
        最終的な LayoutInflater インフレータ = LayoutInflater.from(this);    
        //外部コンテナの取得  
        final RelativeLayout rly = (RelativeLayout) findViewById(R.id.RelativeLayout1);  
        ボタン btnLoad = (ボタン) 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);   
            }   
        });   
    }   
}

スクリーンショットを実行します

コード分​​析:

① コンテナオブジェクトを取得します

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

② Inflater オブジェクトを取得し、同時に追加したレイアウトの xml を読み込み、findViewById で最も外側のルート ノードを検索します。

最終的な LayoutInflater インフレータ = LayoutInflater.from(this); 
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);

4. LayoutInflaterのinflate()メソッドのソースコード

最後に、LayoutInflaterのinflate()メソッドのソースコードを載せておきますので、興味のある方は見てみてください~、実際は単なるPull解析です~

public View inflate(XmlPullParser parser, ViewGroup root, booleanattachToRoot) {     
    synchronized (mConstructorArgs) {     
        Final AttributeSet attrs = Xml.asAttributeSet(parser);    
        mConstructorArgs[0] = mContext;    
        結果を表示 = ルート;    
        {     
            int 型;    を試してください。
            while ((type = parser.next()) != XmlPullParser.START_TAG &&     
                    type != XmlPullParser.END_DOCUMENT) {     
            }     
            if (type != XmlPullParser.START_TAG) {     
                throw new InflateException(parser.getPositionDescription()     
                        + ": 開始しませんタグが見つかりました!");    
            }    
            最終文字列名 = parser.getName();    
            if (TAG_MERGE.equals(name)) {     
                if (root == null || !attachToRoot) {     
                    throw new InflateException("マージは有効な " + "ViewGroup ルートおよびattachToRoot=trueでのみ使用できます    
                            ");    
                rInflate     
                (パーサー、ルート、属性);    
            } else {     
                View temp = createViewFromTag(name, attrs);    
                ViewGroup.LayoutParams パラメータ = null;    
                if (root != null) {     
                    params = root.generateLayoutParams(attrs);    
                    if (!attachToRoot) {     
                        temp.setLayoutParams(params);    
                    rInflate     (パーサー、一時
                属性);    
                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);    
            元を投げます。    
        catch (IOException e) {     
            InflateException ex = new InflateException(     
                    parser.getPositionDescription()     
                    + ": " + e.getMessage());    
            ex.initCause(e);    
            元を投げます。    
        結果を返します    
    }     
}

おすすめ

転載: blog.csdn.net/leyang0910/article/details/132438292