作為Android開發(fā)烤惊,在做ListView相關(guān)的開發(fā)時(shí)溉奕,可能會(huì)遇到這樣的問題:我辛辛苦苦寫的item布局压语,結(jié)果在提供給ListView時(shí)丟失了寬高等信息啸罢,效果慘不忍睹,就像下面這樣:
這里item的布局文件很簡(jiǎn)單胎食,代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="80dp">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:textSize="14sp" />
</RelativeLayout>
可以看到扰才,根節(jié)點(diǎn)上設(shè)置了80dp的高度,而實(shí)際的顯示效果中的高度顯然不是80dp厕怜,而是wrap_content衩匣。
為什么會(huì)這樣呢蕾总?我們先來看一下填充View的代碼:
// 出現(xiàn)異常的代碼示例
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(MainActivity.this).inflate(R.layout.list_item, null);
}
TextView textView = convertView.findViewById(R.id.text);
textView.setText(items[position]);
return convertView;
}
如果平時(shí)注意一下代碼警告,應(yīng)該就能看到在inflate方法的第二個(gè)參數(shù)上會(huì)有這樣的提示:
也就是說琅捏,要想解析待填充View的根節(jié)點(diǎn)的layout參數(shù)生百,就需要指定一個(gè)父節(jié)點(diǎn)(view root)。調(diào)研一下代碼可以發(fā)現(xiàn)柄延,此時(shí)convertView的LayoutParams是空的:
我們來修改一下inflate這一行的代碼蚀浆,給他傳遞一個(gè)父View:
convertView = LayoutInflater.from(MainActivity.this).inflate(R.layout.list_item, parent, false);
需要注意一定要給inflate方法的第三個(gè)參數(shù)傳遞false∷寻桑可以思考一下為什么市俊。
運(yùn)行一下,可以看到效果已經(jīng)達(dá)到了預(yù)期:
通常情況下我們不希望使用固定的Item高度滤奈,而是希望使用margin定義布局的邊界摆昧。接下來我們修改一下布局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:textSize="14sp" />
</RelativeLayout>
這里將高度定義為了wrap_content并增加了四周的邊界。
運(yùn)行一下看看僵刮,結(jié)果又回到了最初的樣子:
這又是什么原因呢据忘?前面說了鹦牛,填充View的時(shí)候需要提供一個(gè)父View搞糕,這樣才能生成LayoutParams,這也說明了LayoutParams是和View的父View關(guān)聯(lián)的曼追。先來看一下View填充之后得到的LayoutParams對(duì)象具體是什么:
這個(gè)LayoutParams對(duì)象的類型是AbsListView.LayoutParams窍仰,是在ListView的父類中定義的(ListView本身并沒有定義LayoutParams對(duì)象)。再仔細(xì)看AbsListView.LayoutParams這個(gè)類礼殊,發(fā)現(xiàn)它是直接繼承自ViewGroup.LayoutParams驹吮,也就是說并不支持margin參數(shù)。(支持margin參數(shù)的類是ViewGroup.MarginLayoutParams晶伦,)
原因找到了碟狞,那么解決辦法也就有了。這里不支持margin參數(shù)婚陪,那么我們只能用padding了族沃。下面是將margin修改為padding之后的效果:
padding不是布局參數(shù)(LayoutParam),即使填充時(shí)不指定父View泌参,也會(huì)保留在填充后的布局中脆淹。