height设置无效果的原因分析

在android开发中相信大家对ListView、GridView等组建都很熟悉,在使用它们的时候需要自己配置相关的Adapter,并且配置现骨干的xml文件作为ListView等组建的子View,这些xml文件在Adapter的getView方法中调用。例如:

public View getView(int position, View convertView, ViewGroup parent) {if(convertView==null) {convertView = App.getLayoutInflater().inflate(R.layout.item, null);}return convertView;}item.xml文件如下:<RelativeLayout xmlns:android=""xmlns:tools=""android:layout_width="match_parent"android:layout_height="400dp"android:background="#008000"><ImageViewandroid:src="@drawable/ic_launcher"android:layout_width="match_parent"android:layout_height="match_parent" ></ImageView></RelativeLayout>用上面的方法会发现无论根View也就是RelativeLayout的layout_width和layout_height设置多大,运行效果始终都是一样的;也就是说此时你想通过RelativeLayout来改变里面子ImageView的大小是行不通的,通常用的解决方式就是里面在添加一个View把ImageView包裹起来,通过设置该View的大小来改变ImageView的大小(注意不一定是ImageView,也可能里面包含了若干个view):<RelativeLayout xmlns:android=""xmlns:tools=""android:layout_width="match_parent"android:layout_height="400dp"android:background="#008000"><RelativeLayoutandroid:layout_width="900dp"android:layout_height="200dp"android:background="@android:color/black"><ImageViewandroid:src="@drawable/ic_launcher"android:layout_width="match_parent"android:layout_height="match_parent" ></ImageView></RelativeLayout></RelativeLayout>虽然找到了解决方法,但是知其然还要知其所以然,为什么好这样呢?在分析之前要弄清一个概念性的问题:

layout_width不是width!layout_height不是height!也就是说这两个属性设置的并不是View的宽和高,layout是布局的意思,也即是说这两个属性是View在布局中的宽和高!既然是布局,肯定都有个放置该View的地方,也就是说有一个媒介来放置View,,并且在该媒介上划出一个layout_width和layout_heigth的大小来放置该View。如果没有该媒介View布局在哪儿呢?所以说为了上面的问题的根本原因就是因为你没有为xml文件设置一个布局媒介(该媒介也是个View,也即是rootView),所以为了保障你的item.xml中根View的layout_width和layout_heigth能起作用,需要设置一个这样的媒介。代码inflate(int,ViewGroup root)中这个root就是这样的一个媒介,但是通常传递的都是null,所以item.xml文件的根View是没有媒介作为布局依据的,所以不起作用;既然问题的原因找到了那么就可以用一个笨的方法来解决这个问题:为inflate提供一个root,在代码里面我简单的做了一下处理,验证了自己的想法:

public View getView(int position, View convertView, ViewGroup parent) {if(convertView==null) {convertView = App.getLayoutInflater().inflate(R.layout.item, null);//手动设置一个root,此时在设置layout_width或者layout_height就会起作用了convertView = App.getLayoutInflater().inflate(R.layout.item, (ViewGroup)convertView);}return convertView;}之所以是笨方法,因为它把item做了两次的xml解析,因为inflate调用了两次。当然此时的item是:<RelativeLayout xmlns:android=""xmlns:tools=""android:layout_width="match_parent"android:layout_height="400dp"android:background="#008000"><ImageViewandroid:src="@drawable/ic_launcher"android:layout_width="match_parent"android:layout_height="match_parent" ></ImageView></RelativeLayout>

既然跟inflate第二个参数root有关,那么看看root都干了些什么,追踪源代码最终解析xml的方法代码如下:

//切记,此时root为null,attachToRoot在源码中为root!=null,所以此处为falsepublic View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {synchronized (mConstructorArgs) {……View result = root; //根View ,为nulltry {….final String name = parser.getName(); //节点名,如果是自定义View的话 就是全限定名//该if语句暂不用看if (TAG_MERGE.equals(name)) { // 处理<merge />标签…} else {// Temp is the root view that was found in the xml//这个是xml文件对应的那个根View,在item.xml文件中就是RelativeLayoutView temp = createViewFromTag(name, attrs);ViewGroup.LayoutParams params = null;//因为root==null,if条件不成立if (root != null) {// Create layout params that match root, if supplied//根据AttributeSet属性获得一个LayoutParams实例,记住调用者为root。params = root.generateLayoutParams(attrs);if (!attachToRoot) { //重新设置temp的LayoutParams// 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//遍历temp下所有的子节点,也就是xml文件跟文件中的所有字ViewrInflate(parser, temp, attrs);//把xml文件的根节点以及根节点中的子节点的view都添加到root中,当然此时root等于null的情况下此处是不执行的if (root != null && attachToRoot) {root.addView(temp, params);}//如果根节点为null,就直接返回xml中根节点以及根节点的子节点组成的Viewif (root == null || !attachToRoot) {result = temp;}}}…return result;}} 走马观花之外,这才是深入体验,探索自我的最佳时间,

height设置无效果的原因分析

相关文章:

你感兴趣的文章:

标签云: