在應用中自定義一個view,需要獲取這個view的佈局,需要用到
(LinearLayout) LayoutInflater.from(context).inflate(R.layout.contentitem, null);
這個方法。
一般的資料中的第二個引數會是一個null。通常情況下沒有問題,但是如果我想給這個view設定一個對應的類,然後通過這個類來操作的話就會出問題。
先看下面的例子
1 <?xml version="1.0" encoding="utf-8"?> 2 3 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 4 android:orientation="vertical" 5 android:layout_width="match_parent" 6 android:layout_height="match_parent" 7 android:background="@color/white"> 8 9 <TextView 10 android:layout_width="match_parent" 11 android:layout_height="wrap_content" 12 android:id="@+id/textViewTitle" 13 android:textColor="@color/black" 14 android:gravity="center" android:textSize="26dp"/> 15 16 <TextView 17 android:layout_width="match_parent" 18 android:layout_height="wrap_content" 19 android:id="@+id/textViewAuthor" 20 android:layout_gravity="left" android:textColor="@android:color/darker_gray" android:textSize="16dp"/> 21 22 <ImageView 23 android:layout_width="wrap_content" 24 android:layout_height="wrap_content" 25 android:id="@+id/imageView" 26 android:layout_gravity="center_horizontal" 27 android:scaleType="center"/> 28 29 <TextView 30 android:layout_width="match_parent" 31 android:layout_height="wrap_content" 32 android:id="@+id/textViewContent" 33 android:layout_gravity="center_horizontal" android:textColor="@color/black" android:textSize="20dp"/> 34 35 <LinearLayout 36 android:layout_width="fill_parent" 37 android:layout_height="2dp" 38 android:layout_gravity="center" 39 android:background="@color/black"> 40 </LinearLayout> 41 42 <TextView 43 android:layout_width="match_parent" 44 android:layout_height="wrap_content" 45 android:id="@+id/textViewOtherInfo" 46 android:layout_gravity="left" android:clickable="true" android:textColor="@android:color/darker_gray" 47 android:textSize="16dp"/> 48 </LinearLayout>
對應的類是
1 public class ContentItemView extends LinearLayout { 2 3 private TextView title; 4 private TextView author; 5 private TextView content; 6 private TextView otherInfo; 7 private ImageView contentImage; 8 9 private ContentInfo info; 10 11 public ContentItemView(Context context) { 12 super(context); 13 init(context); 14 } 15 16 private void init(Context context) { 17 LinearLayout convertView = 18 (LinearLayout) LayoutInflater.from(context).inflate(R.layout.contentitem, null); 19 title = (TextView) convertView.findViewById(R.id.textViewTitle); 20 author = (TextView) convertView.findViewById(R.id.textViewAuthor); 21 content = (TextView) convertView.findViewById(R.id.textViewContent); 22 otherInfo = (TextView) convertView.findViewById(R.id.textViewOtherInfo); 23 contentImage = (ImageView) convertView.findViewById(R.id.imageView); 24 } 25 }
這個自定義view我想將它新增到一個listview中。
1 public void add(final ContentInfo info) { 2 ContentItemView contentItemView = new ContentItemView(context); 3 contentItemView.setContentInfo(info); 4 contentItemView.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT)); 5 6 data.add(contentItemView); 7 } 8 9 @Override 10 public View getView(int position, View convertView, ViewGroup parent) { 11 return data.get(position); 12 }
程式執行起來以後,沒有任何問題,但是介面沒有顯示出來,僅僅是在listview中多了一系列黑色的條條
如果將
(LinearLayout) LayoutInflater.from(context).inflate(R.layout.contentitem, null);
修改為
(LinearLayout) LayoutInflater.from(context).inflate(R.layout.contentitem, this);
顯示就會正常
上面的東西很多資料裡面都有,但是原因是什麼?我在網路上找了很久都沒有找到,於是就自己研究了下程式碼
1 public View inflate(int resource, ViewGroup root) { 2 return inflate(resource, root, root != null); 3 } 4 5 public View inflate(int resource, ViewGroup root, boolean attachToRoot) { 6 if (DEBUG) System.out.println("INFLATING from resource: " + resource); 7 XmlResourceParser parser = getContext().getResources().getLayout(resource); 8 try { 9 return inflate(parser, root, attachToRoot); 10 } finally { 11 parser.close(); 12 } 13 } 14 public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) { 15 ........ 16 if (TAG_MERGE.equals(name)) { 17 if (root == null || !attachToRoot) { 18 throw new InflateException("<merge /> can be used only with a valid " 19 + "ViewGroup root and attachToRoot=true"); 20 } 21 22 rInflate(parser, root, attrs, false); 23 } else { 24 // Temp is the root view that was found in the xml 25 View temp; 26 if (TAG_1995.equals(name)) { 27 temp = new BlinkLayout(mContext, attrs); 28 } else { 29 temp = createViewFromTag(root, name, attrs); 30 } 31 32 ViewGroup.LayoutParams params = null; 33 34 if (root != null) { 35 if (DEBUG) { 36 System.out.println("Creating params from root: " + 37 root); 38 } 39 // Create layout params that match root, if supplied 40 params = root.generateLayoutParams(attrs); 41 if (!attachToRoot) { 42 // Set the layout params for temp if we are not 43 // attaching. (If we are, we use addView, below) 44 temp.setLayoutParams(params); 45 } 46 } 47 48 .............. 49 if (root != null && attachToRoot) { 50 root.addView(temp, params); 51 } 52 53 // Decide whether to return the root that was passed in or the 54 // top view found in xml. 55 if (root == null || !attachToRoot) { 56 result = temp; 57 } 58 } 59 ..... 60 }
可以看到在inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)函式中,只有root不等於空的情況下才能夠真正的把view新增到listview中。
看看引數root的含義:@param root Optional view to be the parent of the generated hierarchy
就是說這個表示的事view的容器是什麼。如果不告訴SDK你要把這個view放到哪裡,當然就不能生成view了。