Qt的MVD即model-view-delegate分别启用着数据列表,显示总体视图框架以及数据中的每一项对应的显示视图。这十分经典且毋庸置疑,而且作为view的一种常用实现ListView的spacing属性可以指定项目和项目之间的间隔。
一旦model的数据被准备好,比如model有8项那么ListView就会加载8个delegate,与之对应的spacing就会有7个。如果这时在qml侧做手脚,进行一定的过滤如删除4个delegate,妄图满足某些条件就返回一个无效的delegate,达到只加载4个delegate的效果。虽然delegate可以删除,但是之前加载过的spacing依然是7个而不是3个:
正确的效果应该是:
这也许是Qt不够智能的原生问题,不管我在现在code里面是让loader返回undefined还是null,抑或是让delegate如text的高度为0,visible为false都无法解决上述问题。我的原始code如下:
Component {
id: contactDetail
SLContactDetails {
id: contactDetails
currentPageId: pageID
dataModel: pageDataList
dataDelegate: Loader {
sourceComponent: switch (model.type) {
case ListItemType.IconInfoItem:
return undefined
case ListItemType.NoteItem:
if (model.value === "") {
return undefined
} else {
return dnItem
}
case ListItemType.IconMenuItem:
if (model.value != "") {
addTopopupMenuList(model)
}
return undefined
case ListItemType.TextItem:
if (model.value === "") {
return undefined
} else {
return dnItem
}
default:
return undefined
}
Component {
id: dnItem
SLText {
width: Skin.CONTACT_DETAIL_INFO_WIDTH
height: Skin.CONTACT_DETAIL_TEXT_HEIGHT
elide: Text.ElideRight
text: model.value
horizontalAlignment: Text.AlignHCenter
color: QmlGlobal.colors.ivory
font.pixelSize: Skin.CONTACT_DETAIL_TEXT_SIZE
}
}
}
此问题在 qt - Hide an item (delegate) inside a ListView QML - Stack Overflow 也有提及,他意思是model作为数据来源应该就不发不需要的数据,而不是发给qml让qml去过滤,这个不符合MVD的模型。
只想少改动qml的代码解决问题,也有hack的方法。即设置delegate的height为负数以抵消多余的spacing;或者spacing设为0,让每个delegate自带一个spacing。
当然上述hack的方法可读性也不好,归根结底还是要遵守MVD模型去开发。