LayoutInflater(レイアウトサービス)
このセクションの紹介:
このセクションでは引き続き、Android システム サービスの LayoutInflater (レイアウト サービス) を紹介します。 レイアウト XML を作成し、Activity の setContentView() を呼び出してレイアウトをロードし、それを表示することが考えられます。 画面上では、実際、最下層は依然として LayoutInflater であり、Android の組み込みプル パーサーを使用して解析されます。 レイアウト。一般に、Android ではレイアウトを動的に読み込んだり、コントロールを追加したりするためによく使用されます。このセクションでは、実際の開発での使用方法を学びます。 いくつかの使い方~
公式 API ドキュメント:LayoutInflater
1. LayoutInflater の関連紹介
1) Layout とは何ですか?
回答: レイアウトをロードするために使用されるシステム サービスは、レイアウト XML ファイルに対応する View オブジェクトをインスタンス化するために使用されます。これを直接使用することはできません。 現在の Context にバインドされているコンテンツを取得するには、getLayoutInflater() メソッドまたは getSystemService() メソッドを使用する必要があります。 LayoutInflaterインスタンス!
2) LayoutInflaterの使い方
①LayoutInflaterインスタンスを取得する3つの方法:
LayoutInflater inflater1 = LayoutInflater.from(this); LayoutInflater inflater2 = getLayoutInflater(); LayoutInflater inflater3 = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
追記:後の2つは実際に一番下の最初のメソッドを使用します~
②レイアウトメソッドの読み込み:
public View inflate (int リソース、ViewGroup ルート、ブール型attachToRoot) このメソッドの 3 つのパラメータは次のとおりです:
①ロードするレイアウトに対応するリソース ID
②レイアウトの外側に親レイアウトのレイヤーをネストします。そうでない場合は、null を記述するだけです!
③ルート レイアウトを設定するかどうか。このパラメータが設定されていない場合、ロードされたレイアウト ファイルの最外層。 root が null でない場合、デフォルトは true になります root が null の場合、attachToRoot は効果がありません。 root が null でなく、attachToRoot が true の場合、ルート レイアウトはロードされたレイアウト ファイルの最外層にネストされます。 false の場合、root は機能を失います。 簡単に理解すると: 読み込まれたレイアウトにルート外部コンテナを追加するかどうか~!
③LayoutInflater.LayoutParams を通じて関連プロパティを設定する:
たとえば、RelativeLayout は addRule メソッドを通じてルールを追加することもできます。場所を設定するだけです。それは親コンテナを参照していますか? それとも子コントロールを参照しますか?マージンなどを設定するかどうかはあなた次第です~
2. レイアウトをロードする Pure Java コード
私たちは長い間、必要なレイアウトを生成するために XML を使用することに慣れてきましたが、特定のケースでは、 コンポーネントまたはレイアウトをレイアウトに動的に追加するには、Java コードを使用する必要があります。
ただし、Android ページ レイアウトを記述するために完全に Java コードを使用することはお勧めできません。最初のポイントは、コードが大量になるということです。 混乱しやすいため、業務の分離には役立ちません。それでも、レイアウトを完成させるために 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); のように前に追加するだけです。 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); Button btnOne = new Button(this); rly.addView(btnOne, lp2);他のコンポーネントの配置を参照してください: (欠点の 1 つは、参照コンポーネントの ID を手動で設定する必要があることです。これは
manual!!!) 例: 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("按钮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); } }——ステップ 4:
setContentView() メソッドを呼び出してレイアウト オブジェクトをロードします。 さらに、コンテナ内のビューを削除したい場合は、コンテナを呼び出します。removeView
(削除するコンポーネント);スクリーンショットを実行
:3. Java コードを動的に追加します。コントロールまたは XML レイアウト
説明した 2 番目のポイントは、純粋な Java コードを使用してレイアウトをロードすることですが、実際にはあまり使用されず、より動的です。 View コントロールを追加し、XML レイアウトを動的に読み込みます。
1) View を動的に追加する 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); 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); } }2 番目のタイプでは、最初にレイアウト ファイルをロードするために setContentView() を必要としません:
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); } }分析概要:
コードは非常に簡単です。ボタンを作成した後、ボタンのサイズを設定する LayoutParams オブジェクトを作成しました。 ボタンの位置は、addRule() メソッドを通じて設定されます。
最初の方法: 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" > <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>次に、ここで
MainActivity.java XML レイアウトの動的ロードに移動します。 :
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); } }); } }
実行中のスクリーンショット:
コード分析:
①コンテナオブジェクトを取得:
final RelativeLayout rly = (RelativeLayout) findViewById(R.id.RelativeLayout1);②Inflaterオブジェクトを取得し、追加したレイアウトのxmlをロードし、最も外側を見つけますfindViewById を介した部分 レイヤーのルート ノード
final LayoutInflater inflater = 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() メソッドのソース コードを提供します。興味がある場合は、見てみてください~、実際には単なるプル分析です~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; } }
このセクションの概要:
このセクションでは、Android の LayoutInflater (レイアウト サービス)、およびビューとコントロールの動的読み込みについて説明します。 関連事項、コントロールに慣れていない友達にも役立つと思います~はい、以上です、ありがとう~