Xml转换成view的原理
在開發過程中,我們通常都有在用View.inflate(context, resource, root)方法來創建視圖,這個方法非常方便,但是它有個缺點就是沒有加載xml 里面設置的布局參數。舉個例子創建一個叫ListViewDemo 的工程。它里面主界面布局里面就放置一個listview
<RelativeLayout 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"><ListView android:id="@+id/listview"android:layout_width="match_parent"android:layout_height="match_parent" /></RelativeLayout>在activity 中就是獲取到listview 控件并給它設置一個適配器
MainActivity .java
package com.itheima.listviewdemo;import android.os.Bundle;import android.app.Activity;import android.content.Context;import android.view.LayoutInflater;import android.view.Menu;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ListView;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ListView listview = (ListView) findViewById(R.id.listview);listview.setAdapter(new MyAdapater(this));}private class MyAdapater extends BaseAdapter {private LayoutInflater mInflater;public MyAdapater(Context mcontext) {mInflater = (LayoutInflater) mcontext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);}@Overridepublic int getCount() {// TODO Auto-generated method stubreturn 10;}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stubreturn null;}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {View view = mInflater.inflate(R.layout.item, parent, false);// View view = mInflater.inflate(R.layout.item, null);return view;}}}listview 的item 布局為item.xml,它是一個寬度為match_parent,高度為100dp 的線性
布局,線性布局包含了一個寬度為match_parent、高度為match_parent 的TextView。
【文件1-3】item.xml
從布局上來看,listview 的條目textview 控件的高度應該為100dp。但是我們在適配器方法getview 中使用mInflater.inflate(R.layout.item, null)方法后(見【文件1-2】54 行),運行的效果如圖1-1(a)所示,它的高
度為包裹內容,這說明它沒有使用到xml 中設置的屬性高度。
ListViewDemo 運行效果
如果使用mInflater.inflate(R.layout.item, parent, false),運行效果如圖1-1(b)所示,它的高度為100dp,
這樣xml 里設置的高度就生效了,這才是inflate 方法的正確用法。
那我們來看看它為什么可以正確顯示xml 布局中的數據。我按住ctrl+左鍵進入mInflater.inflate
(R.layout.item, parent, false) 方法的源碼,方法中通過第一個參數布局資源id 獲取到一個XmlResourceParser
對象,接著調用inflate(parser, root, attachToRoot)方法(見【文件1-4】3~5 行)。在該方法中首先通過final
AttributeSet attrs = Xml.asAttributeSet(parser) 這段代碼拿到xml 中的屬性值; 再通過temp =
createViewFromTag(root, name, attrs) 這段代碼得到根據屬性值attrs 對象創建出來的view 。
createViewFromTag(root, name, attrs)方法中通過調用createView 方法使用反射的方式創建出控件對象;在
inflate(parser, root, attachToRoot)方法中還有一步重要的操作:temp.setLayoutParams(params),這里temp 的
是上面createViewFromTag 方法根據xml 創建出來的view,給它設置了xml 里設置的布局參數,這樣xml
里設置的高度就生效了。(這里源碼過多就不貼出來了)
源碼執行順序:inflate(R.layout.item, parent,false)→XmlResourceParser →inflate(parser, root,
attachToRoot)→AttributeSet attrs = Xml.asAttributeSet(parser)→temp = createViewFromTag(root, name, attrs)→
→temp.setLayoutParams(params),這是inflate 方法的執行順序。其中createViewFromTag(root, name, attrs)
方法中通過view = createView(name, null, attrs)方法使用反射來創建xml 中的控件,這樣一個xml 轉換為
view 的步驟原理就介紹完了。
【文件1-4】Inflate 源碼
總結
以上是生活随笔為你收集整理的Xml转换成view的原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RecyclerView notifyI
- 下一篇: setDrawingCacheEnabl