Android Layout Inflater.inflateの使用とソース分析
16505 ワード
転載を歓迎します.転載は出所を明記してください.http://blog.csdn.net/johnny901114/article/details/61913656 本論は「余志強のブログ」です.
実際の開発にはしばしばinflateが必要です.レイアウトにその後、あるレイアウト容器に追加します.xmlレイアウトファイルをViewオブジェクトに変換するには、Layout Inflate.inflate方法が必要です.開発にはよく次のような方法があります.
inflanter.inflate(layoutId,null)
今はMainActivityを持っています.このレイアウトにaddのレイアウトを見たいです.このレイアウトは下記の通りです.
その後MainActivityで追加操作を実行します.
上の図からわかるように、追加されたViewの幅は
ソースを見てみます.
inflanter.inflate(R.layout.inflater 01,null)メソッドでinflate(@LayoutRes int resource,@Nullable View Groot,boot atch ToRoot)を呼び出しました.この方法ではinflate(XmlPulser parser)を呼び出しました.
上のコードからinflanter.inflate(layoutId,null)の方法を見て、rootは私達がnullを伝えたため、atach ToRoot=false.
ソースのinflatlate.inflayoutIdによると、nullの方法は次の通りです.
1,xmlの中の関連する属性をViewの対象に変えます.
だからこのViewにはLayoutParaamsの対象がないのです.
信じないなら、プリントしてもいいです.
一つのViewはLayoutParaamsがないとスクリーンに展示できないです.
今はroot.addViewの方法を見るしかないです.
だからゲナートDefault LayoutParaamsを見てみます.方法はどうなりますか?私達のこのrootはLineear Layoutなので、Linerer Layoutのgenerate Default LayoutParaamsに行くつもりです.VieGroupではなく、見に行きます.
inflanter.inflate(layoutId、root、false);
MainActivityにViewを追加する方法は、以下のようになります.
これこそ私達が求めている効果です.幅の高さと左側の距離は私達が求めている効果です.
ソース
1,xmlの中の関連する属性をViewの対象に変えます.
だから、最終的に現れたのは私達の予想に合致したのです.
inflanter.inflate(layoutid、root、true);
inflanter.inflate(layoutid、root、true);とinflater.inflate(layoutId、root、false);唯一の違いはinflater.inflateです.自動的にViewをrootに追加します.私達がaddに入る必要はありません.
実際の開発にはしばしばinflateが必要です.レイアウトにその後、あるレイアウト容器に追加します.xmlレイアウトファイルをViewオブジェクトに変換するには、Layout Inflate.inflate方法が必要です.開発にはよく次のような方法があります.
inflater.inflate(layoutId, null);
inflater.inflate(layoutId, root,false);
inflater.inflate(layoutId, root,true);
特に初心者はこのような違いが分かりません.次に彼らの違いを見てみます.inflanter.inflate(layoutId,null)
今はMainActivityを持っています.このレイアウトにaddのレイアウトを見たいです.このレイアウトは下記の通りです.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:background="#50000000" android:orientation="vertical">
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="inflate01" android:textAllCaps="false" android:textSize="20sp" />
</LinearLayout>
この配置は非常に簡単で、外層はLineear Layoutで、背景色は#50000000
で、大きさは全部wrap_content
で、左から20 dpです.その後MainActivityで追加操作を実行します.
LayoutInflater inflater = LayoutInflater.from(this);
View view = inflater.inflate(R.layout.inflater01, null);
root.addView(view);
Viewを追加したら、私達が欲しいのではなく、下の図のようになっています.上の図からわかるように、追加されたViewの幅は
wrap_content
ではなく、スクリーンいっぱいになっています.leftも効果がありません.つまり私達が設定したこれらは無効になりました.ソースを見てみます.
inflanter.inflate(R.layout.inflater 01,null)メソッドでinflate(@LayoutRes int resource,@Nullable View Groot,boot atch ToRoot)を呼び出しました.この方法ではinflate(XmlPulser parser)を呼び出しました.
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
synchronized (mConstructorArgs) {
final Context inflaterContext = mContext;
final AttributeSet attrs = Xml.asAttributeSet(parser);
Context lastContext = (Context) mConstructorArgs[0];
mConstructorArgs[0] = inflaterContext;
View result = root;
try {
// Look for the root node.
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG &&
type != XmlPullParser.END_DOCUMENT) {
// Empty
}
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, inflaterContext, attrs, false);
} else {
// Temp is the root view that was found in the xml
// xml View
final View temp = createViewFromTag(root, name, inflaterContext, attrs);
ViewGroup.LayoutParams params = null;
// root
if (root != null) {
// Create layout params that match root, if supplied
// XML , LayoutParamsView LayoutParameter root
//root ( LinearLayout) params params(LinearLayout.LayoutParams)
params = root.generateLayoutParams(attrs);
// , params
if (!attachToRoot) {
// Set the layout params for temp if we are not
// attaching. (If we are, we use addView, below)
temp.setLayoutParams(params);
}
}
// Inflate all children under temp against its context.
// View
rInflateChildren(parser, temp, attrs, true);
// We are supposed to attach all the views we found (int temp)
// to root. Do that now.
if (root != null && attachToRoot) {
// View root
root.addView(temp, params);
}
// Decide whether to return the root that was passed in or the
// top view found in xml.
if (root == null || !attachToRoot) {
result = temp;
}
}
} catch (XmlPullParserException e) {
//igore code...
} catch (Exception e) {
//igore code...
} finally {
//igore code...
}
return result;
}
}
上のコードの方が分かりやすいです.主なところにコメントを入れました.上のコードからinflanter.inflate(layoutId,null)の方法を見て、rootは私達がnullを伝えたため、atach ToRoot=false.
ソースのinflatlate.inflayoutIdによると、nullの方法は次の通りです.
1,xmlの中の関連する属性をViewの対象に変えます.
final View temp = createViewFromTag(root, name, inflaterContext, attrs);
2,最後にView tempを返しました.だからこのViewにはLayoutParaamsの対象がないのです.
信じないなら、プリントしてもいいです.
View view = inflater.inflate(R.layout.inflater01, null);
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
if (layoutParams == null) {
Log.e("MainActivity", "layoutParams is null");
} else {
Log.e("MainActivity", "layoutParams width:height" + layoutParams.width + ":" + layoutParams.height);
}
間違いなくnullを出力します.一つのViewはLayoutParaamsがないとスクリーンに展示できないです.
今はroot.addViewの方法を見るしかないです.
public void addView(View child) {
addView(child, -1);
}
public void addView(View child, int index) {
if (child == null) {
throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup");
}
LayoutParams params = child.getLayoutParams();
if (params == null) {
params = generateDefaultLayoutParams();
if (params == null) {
throw new IllegalArgumentException("generateDefaultLayoutParams() cannot return null");
}
}
addView(child, index, params);
}
上から見れば、childのLayoutParaamsがnullであれば、rootはデフォルトのLayoutParaamsを生成します.だからゲナートDefault LayoutParaamsを見てみます.方法はどうなりますか?私達のこのrootはLineear Layoutなので、Linerer Layoutのgenerate Default LayoutParaamsに行くつもりです.VieGroupではなく、見に行きます.
@Override
protected LayoutParams generateDefaultLayoutParams() {
if (mOrientation == HORIZONTAL) {
return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
} else if (mOrientation == VERTICAL) {
return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
return null;
}
私達のrootはLine earLayout方向がVERRTICALなので、LayoutParaams=new LayoutParaams(LayoutParames.MATCHupartENT、LayoutParaams.WRAPuCONTENT)です.これは上の運転の効果を説明しました.設定されている幅と高さはWRAP_です.CONTENTは、最後に幅MATCHになりました.PART、高さはWRAP_CONTENT.viewGroup.addView(view, LayoutParams);
:
view.setLayoutParams(LayoutParams);
viewGroup.addView(view)
ある人は次の三つの属性が失効したと聞きますが、android:background="#50000000"
はまた働きますか?android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
ラyoutなのでwidth,layout_height,layout_margin Left,layout_margingLeftは全部LayoutParamesに属していますが、background属性はこの範囲ではなく、同時にすべてのラベル属性はAttributeSetオブジェクトに存在します.inflanter.inflate(layoutId、root、false);
MainActivityにViewを追加する方法は、以下のようになります.
/** * inflater.inflate(layoutId, root, false); */
private void add02() {
View view = inflater.inflate(R.layout.inflater01, root, false);
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
if (layoutParams == null) {
Log.e("MainActivity", "layoutParams is null");
} else {
Log.e("MainActivity", "layoutParams width:height" + layoutParams.width + ":" + layoutParams.height);
}
root.addView(view);
}
レイアウトファイルですか?それともそのレイアウトファイルですか?違うのはinflate方法のパラメータを指定しただけです.inflater.inflate(R.layout.inflater01, root, false);
効果は下図の通りです.これこそ私達が求めている効果です.幅の高さと左側の距離は私達が求めている効果です.
ソース
inflater.inflate(R.layout.inflater01, root, false);
方法によって実行されるプロセスは以下の通りです.1,xmlの中の関連する属性をViewの対象に変えます.
final View temp = createViewFromTag(root, name, inflaterContext, attrs);
2,XMLファイルでの設定により、LayoutParames Viewを生成するLayoutParameeterはrootレイアウトに適応し、Viewに設定されている.params = root.generateLayoutParams(attrs);
if (!attachToRoot) {
// Set the layout params for temp if we are not // attaching. (If we are, we use addView, below) temp.setLayoutParams(params);
}
2,最後にView tempを返しました.だから、最終的に現れたのは私達の予想に合致したのです.
inflanter.inflate(layoutid、root、true);
inflanter.inflate(layoutid、root、true);とinflater.inflate(layoutId、root、false);唯一の違いはinflater.inflateです.自動的にViewをrootに追加します.私達がaddに入る必要はありません.
/** * inflater.inflate(layoutId, root, true); */
private void add03() {
View view = inflater.inflate(R.layout.inflater01, root, true);
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
if (layoutParams == null) {
Log.e("MainActivity", "layoutParams is null");
} else {
Log.e("MainActivity", "layoutParams width:height" + layoutParams.width + ":" + layoutParams.height);
}
}