@flyouting
2014-06-26 15:32
字数 3127
阅读 828
按照预期初始化布局--layout inflation as intended
Layout inflation是一个android中的术语,用于表达一个XML布局源文件被解析转变成一个View的层次结构对象。 这在AndroidSDK中是常见的做法,但你也许会惊讶地发现,有一个错误的方式去使用LayoutInflater,你的应用也许就是其中之一。如果你在你的Android应用程序曾经写过类似下面的代码:
请继续读下去,因为你做错了,我想向你解释为什么。 了解LayoutInflater首先我们来看一看
第一个参数指向你想要的图形化的布局资源。第二个参数是你图形化资源后所要依附的根view。第三个参数是否直接将图形化后的view添加进根view。 后边这两个参数,可能会导致一些混乱。在两个参数的方法中, 很多开发者采用这种方式意思是这是种正确的方式,即root参数传null,去禁止在图形化过程中自动附加上view。很多情况下,他们都没有意识到有三个参数的inflate()方法存在,这种方式也导致了我们禁掉了根view的一些重要功能。 Framework中的例子我们来检查一下在Android中,框架希望我们作为开发者inflate部分视图的情况: 适配器中使用LayoutInflater的最常见的方式就是自定义Adapter,重写getView方法:
Fragment也经常通过onCreateView()方法使用LayoutInflater来创建view:
注意到没,每当系统想让你添加一个布局,都会传给你一个父viewgroup,而且,在大多数情况下(包括以上两个例子),如果允许LayoutInflater自动将view添加进父视图,就会抛出一个异常。 那么,如果我们不想直接添加上去,为什么又要我们给出这个viewgroup呢?原来,父view是inflate过程中很重要的一部分,因为我们需要取得XML中根元素的LayoutParams。这里传null意思就好比我也不知道这个view要添加到哪。 这么做的问题是 android:layout_xxx这些属性是在父view的context中获取到。因此,如果没有具体的父view,在XML根元素声明的LayoutParams都会被抛弃。然后你会困惑为啥系统忽略了我设置的这些属性。 没有 LayoutParams,生成view添加进viewgroup时就会依照默认属性。掩盖了你所设置的真正属性。 程序实例你要说你从来没见过这种情况,那看如下代码: R.layout.item_row
我们想把item的高度设置成一个特定值,在这种情况下,优先选定为当前主题,看起来是合理的。 然而当我们以错误的方式生成时:
我们得到的结果如此: 我们设置的行高呢?这就是常见的我们设置了高度,却最终是自适应的情况。 如果我们换一种实现方式:
我们就会得到我们希望的结果: 每个规则都有例外当然有些情况下你可以发现parent确实是个null,但是这种情况很少,其中一例是,初始化一个自定义的布局,然后添加进一个AlertDialog,看一下如下代码:
这里的问题是,AlertDialog.Builder支持一个自定义view,但是没有提供一个支持传入布局资源ID的setView()方法, 所以,我们需要先手动初始化我们的布局XML,然后,因为初始化后的对象是要被添加进Dialog,而不是其他的什么根view(事实上也不存在),我们 没有进入父一级布局,所以实例化过程中我们不能使用它,但这无关紧要,因为AlertDialog会清除布局的任何LayoutParams,且用 match_parent取代。 所以,当你下次又想直接在inflate()方法中传null时,先问下自己,你真的知道这个view最后如何展示么。 最后,你需要记住两个参数的inflate()方法省略的参数代表true,而不是你所认为的代表的false。 |
|