ListView填充子View時(shí)為什么丟失了寬高

作為Android開發(fā),在做ListView相關(guān)的開發(fā)時(shí),可能會遇到這樣的問題:我辛辛苦苦寫的item布局,結(jié)果在提供給ListView時(shí)丟失了寬高等信息,效果慘不忍睹,就像下面這樣:

慘不忍睹的Item效果

這里item的布局文件很簡單,代碼如下:

<?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。

為什么會這樣呢?我們先來看一下填充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ù)上會有這樣的提示:


參數(shù)警告

也就是說,要想解析待填充View的根節(jié)點(diǎn)的layout參數(shù),就需要指定一個(gè)父節(jié)點(diǎn)(view root)。調(diào)研一下代碼可以發(fā)現(xiàn),此時(shí)convertView的LayoutParams是空的:


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ù)期:


image.png

通常情況下我們不希望使用固定的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é)果又回到了最初的樣子:


加了margin后不生效

這又是什么原因呢?前面說了,填充View的時(shí)候需要提供一個(gè)父View,這樣才能生成LayoutParams,這也說明了LayoutParams是和View的父View關(guān)聯(lián)的。先來看一下View填充之后得到的LayoutParams對象具體是什么:

查看生成的LayoutParams對象

這個(gè)LayoutParams對象的類型是AbsListView.LayoutParams,是在ListView的父類中定義的(ListView本身并沒有定義LayoutParams對象)。再仔細(xì)看AbsListView.LayoutParams這個(gè)類,發(fā)現(xiàn)它是直接繼承自ViewGroup.LayoutParams,也就是說并不支持margin參數(shù)。(支持margin參數(shù)的類是ViewGroup.MarginLayoutParams,)

原因找到了,那么解決辦法也就有了。這里不支持margin參數(shù),那么我們只能用padding了。下面是將margin修改為padding之后的效果:

將margin修改為padding

padding不是布局參數(shù)(LayoutParam),即使填充時(shí)不指定父View,也會保留在填充后的布局中。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容