android中LayoutInflater.from(context).inflate的分析
在应用中自定义一个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了。