|
在實際開發中LayoutInflater這個類還是非常有用的,它的作用類似於findViewById()。不同點是LayoutInflater是用來找res/layout/下的xml佈局文件,並且實例化;而findViewById()是找xml佈局文件下的具體widget控件(如Button、TextView等)。
具體作用:
1、對於一個沒有被載入或者想要動態載入的界面,都需要使用LayoutInflater.inflate()來載入;
2、對於一個已經載入的界面,就可以使用Activiyt.findViewById()方法來獲得其中的界面元素。
LayoutInflater是一個抽像類,在文檔中如下聲明:
public abstract class LayoutInflater extends Object
獲得LayoutInflater實例的三種方式:
1. LayoutInflater inflater = getLayoutInflater(); //調用Activity的getLayoutInflater()
2. LayoutInflater localinflater =(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 3. LayoutInflater inflater = LayoutInflater.from(context);
其實,這三種方式本質是相同的,從源碼中可以看出:
getLayoutInflater():
Activity的getLayoutInflater()方法是調用PhoneWindow的getLayoutInflater()方法,看一下該源代碼:
- public PhoneWindow(Context context) {
- super(context);
- mLayoutInflater = LayoutInflater.from(context);
- }
複製代碼
可以看出它其實是調用LayoutInflater.from(context)。
- LayoutInflater.from(context):
- public static LayoutInflater from(Context context) {
- LayoutInflater LayoutInflater =
- (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- if (LayoutInflater == null) {
- throw new AssertionError("LayoutInflater not found.");
- }
- return LayoutInflater;
- }
複製代碼
可以看出它其實調用context.getSystemService()。
結論:所以這三種方式最終本質是都是調用的Context.getSystemService()。
inflate方法
通過sdk的api文檔,可以知道該方法有以下幾種過載形式,返回值均是View對象,如下:
- public View inflate (int resource, ViewGroup root)
- public View inflate (XmlPullParser parser, ViewGroup root)
- public View inflate (XmlPullParser parser, ViewGroup root, boolean attachToRoot)
- public View inflate (int resource, ViewGroup root, boolean attachToRoot)
複製代碼
1:
public View inflate (int resource, ViewGroup root)
reSource:View的layout的ID
root:如果為null,則將此View作為根,此時既可以應用此View中的其他控件了。
如果!null,則將默認的layout作為View的根。
2:
public View inflate ( XmlPullParser parser, ViewGroup root)
parser:你需要解析xml的解析接口
root:如果null,則將此View作為根,此時既可以應用此View中的其他控件了。
如果!null,則將默認的layout作為View的根。
3:
public View inflate ( XmlPullParser parser, ViewGroup root, boolean attachToRoot)
parser:你需要解析View的xml的解析接口
root:如果null,則將此View作為根,此時既可以應用此View中的其他控件了。
如果!null,則將默認的layout作為View的根。
attachToRoot:
ture:也就將此解析的xml作為View根
fase:則為默認的xml,做為根視圖View
4:
public View inflate (int resource, ViewGroup root, boolean attachToRoot)
resource:View的layout的ID
root:如果null,則將此View作為根,此時既可以應用此View中的其他控件了。
如果!null,則將默認的layout作為View的根。
attachToRoot:
ture:也就將此解析的xml作為View根
fase:則為默認的xml,做為根視圖View
示意代碼:
- public View inflate (int resource, ViewGroup root)
- public View inflate (XmlPullParser parser, ViewGroup root)
- public View inflate (XmlPullParser parser, ViewGroup root, boolean attachToRoot)
- public View inflate (int resource, ViewGroup root, boolean attachToRoot)
複製代碼
同時在此講講讓我去API中去理解這四個函數的原因吧!
在Activity中:
大家是否知道,在setContentView(new MySurfaceView(this))後,此Activity中聲明的View控件,
如:TextView為什麼引用不到layout佈局文件中的控件ID呢!初一看能夠應用到,但是為什麼編譯就報空指針呢!原因:在setContentView(new MySurfaceView(this))後,此時的View變為了根視圖了,雖然能應用到TextView對應的ID,但是我在MySurfaceView中根本就沒有這個對象,所以就報空指針咯!
解決辦法:
View view = LayoutInflater.from(this).inflate(R.layout.passover, null);注:每解析一次都會產生不同的對象
然後你再引用沒問題,使用自如了。
Android中inflate方法的用法
Inflate()作用就是將xml定義的一個佈局找出來,但僅僅是找出來而且隱藏的,沒有找到的同時並顯示功能。而setContentView()將佈局設置成當前屏幕即Activity的內容,可以直接顯示出來。
SetContentView()一旦調用, layout就會立刻顯示UI;而inflate只會把Layout形成一個以view類實現成的對象。有需要時再用setContentView(view)顯示出來。
注:Inflate()或可理解為“隱性膨脹”,隱性擺放在view裡,inflate()前只是獲得控件,但沒有大小沒有在View裡佔據空間,inflate()後有一定大小,只是出於隱藏狀態。
一般在activity中通過setContentView()將界面顯示出來,但是如果在非activity中如何對控件佈局設置操作了,這需LayoutInflater動態加載。
- <TextView
- android:id="@+id/tview"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="ATAAW.COM" />
- <Button
- android:id="@+id/button"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="按钮" />
複製代碼
在程序中動態加載以上佈局。
LayoutInflater flater = LayoutInflater.from(this);View view = flater.inflate(R.layout.example, null);
獲取佈局中的控件。
button = (Button) view.findViewById(R.id.button);textView = (TextView)view.findViewById(R.id.tview);
接下來結合源碼說說inflate方法的二種形式:
1.通過LayoutInflater類的inflate()方法動態加載。兩種獲得LayoutInflater的方法
a.通過SystemService獲得
LayoutInflater inflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLEATER_SERVICE);
b.從給定的context中獲取
Public static LayoutInflater from(Context context)
c.兩者的區別:實際上是一樣的,源碼
- public static LayoutInflater from(Context context) {
- LayoutInflater LayoutInflater =
- (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- if (LayoutInflater == null) {
- throw new AssertionError("LayoutInflater not found.");
- }
- return LayoutInflater;
- }
複製代碼
d.實現代碼:
第一步,先獲得LayoutInflater對象。
LayoutInflater inflater=context.getSystemService(Context.LAYOUT_INFLEATER_SERVICE);
第二步,調用inflate()方法加載佈局資源。
View view=inflater.inflate(int resource, ViewGroup root);
參數1:要加載的xml資源文件,加載出錯拋出InflateException異常。
參數2:新生成視圖的父層,可設置為NULL。
第三步,將新生成的View加入到需要的View中,我們可以通過findViewById()方法獲取當前Acitivty中的視圖MyView,然後把新生成的view加入到Myview中。
MyView.add(view, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
注意:需要指定視圖屬性。
也可以調用inflater.inflate(int resource, ViewGroup root)方法時直接將視圖加入到父視圖中。
如:inflater.inflate(R.layout.login,MyView);
這種情況不好控制新視圖的長寬。建議使用第一種。
注: LayoutInflater.inflate()將Layout文件轉換為View,專門供Layout使用的Inflater。雖然Layout也是View的子類,但在android中如果想將xml中的Layout轉換為View放入.java代碼中操作,只能通過Inflater,而不能通過findViewById()。
第二種方法:使用View的靜態方法:
static View inflate(Context context, int resource, ViewGroup root)
參數1:Acitivity或Application的上下文
參數2:指定的xml佈局文件
參數3:指定父組件。
同樣可以通過:
View view=View.inflate(this,R.layout.*,null);
生成一個新的View,然後調用Add方法指定View的屬性並加入的父組件中。
當然也可以使用View.inflate(this,R.layout.*,MyView)直接加入到父組件中。
findViewById有兩種形式:
R.layout.xx是引用res/layout/xx.xml的佈局文件(inflate方法),R.id.xx是引用佈局文件裡面的組件,組件的id是xx(findViewById方法) 。所有的組件id都能用R.id.xx來查看,但是組件不在setContentView()裡面的layout中就無法使用,Activity.findViewById()會出現空指針異常
a. activity中的findViewById(int id)
b. View中的findViewById(int id)
6.不同點是LayoutInflater是用來找layout下xml佈局文件,並且實例化!而findViewById()是找具體xml下的具體widget控件(如:Button,TextView等)。
Android上還有一個與Inflate()類似功能的方法叫findViewById(),二者有時均可使用,但也有區別,
區別在於:
findViewById()只能找出當前佈局中的組件,即setConentView()的那個layout裡的組件.
如果你的Activity裡用到別的layout,比如對話框layout,你還要設置這個layout上的其他組件的內容,你就必須用inflate()方法先將對話框的layout找出來,然後再用findViewById()找到它上面的其它組件。例如:
- View view1=View.inflate(this,R.layout.dialog_layout,null);
- TextViewdialogTV=(TextView)view1.findViewById(R.id.dialog_tv);
- dialogTV.setText("abcd");
複製代碼
注:R.id .dialog_tv是在對話框layout上的組件,而這時若直接用this.findViewById(R.id.dialog_tv)肯定會報錯。
View viewStub = ((ViewStub) findViewById(R.id.stubView)).inflate();
原文链接:https://blog.csdn.net/robertcpp/article/details/51523218
|
|