You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在QML中制作带细节效果的自定义ListView

问题描述

我想做一个带有丰富细节的ListView,不想只用单一扁平化的带轮廓元素。希望每个列表项有渐变、额外矩形这类细节来做出光泽效果,但不确定是自己知识不够还是ListView本身做不到。如果ListView不支持的话,有没有办法让Column组件支持方向键滚动,并且元素能切换选中状态?

菜单原型图

单个列表项的设计代码
Rectangle {
    id: selection1
    width: 240
    height: 29
    gradient: Gradient {
        GradientStop {
            position: 0
            color: "#d9d9d9"
        }

        GradientStop {
            position: 1
            color: "#c2c2c2"
        }
        orientation: Gradient.Vertical
    }
    Rectangle {
        id: rectangle7
        x: 0
        y: 27
        width: 240
        height: 1
        color: "#708c8c8c"
    }

    Text {
        id: text3
        x: 8
        y: 5
        width: 164
        height: 19
        color: "#000000"
        text: "Selection 1"
        font.pixelSize: 13
        styleColor: "#000000"
        smooth: false
        renderType: Text.QtRendering
        font.weight: Font.Normal
        font.styleName: "SemiBold"
        font.family: "Open Sans"
        font.bold: false
        DesignEffect {
            effects: [
                DesignDropShadow {
                    offsetY: -1
                    blur: 0
                }]
        }
    }
}
解决方案

一、用ListView实现自定义样式列表

完全可以用ListView实现你要的效果,ListView本身支持自定义委托(Delegate),只要把你设计的单个元素作为委托,结合ListView的选中状态就能切换样式。

实现步骤:

  • 用ListModel提供列表数据,ListView绑定模型
  • 把你写的单个元素作为委托,通过ListView.isCurrentItem判断当前选中项,动态修改渐变、底部线条颜色和文字加粗状态
  • 开启ListView的键盘导航,支持方向键切换选中项

示例代码:

ListView {
    width: 240
    height: 200
    model: ListModel {
        ListElement { text: "Selection 1" }
        ListElement { text: "Selection 2" }
        ListElement { text: "Selection 3" }
        ListElement { text: "Selection 4" }
    }
    delegate: Rectangle {
        width: 240
        height: 29
        gradient: Gradient {
            GradientStop { position: 0; color: ListView.isCurrentItem ? "#a9a9a9" : "#d9d9d9" }
            GradientStop { position: 1; color: ListView.isCurrentItem ? "#8c8c8c" : "#c2c2c2" }
            orientation: Gradient.Vertical
        }
        Rectangle {
            x: 0
            y: 27
            width: 240
            height: 1
            color: ListView.isCurrentItem ? "#50666666" : "#708c8c8c"
        }
        Text {
            x: 8
            y: 5
            width: 164
            height: 19
            color: "#000000"
            text: model.text
            font.pixelSize: 13
            styleColor: "#000000"
            smooth: false
            renderType: Text.QtRendering
            font.weight: Font.Normal
            font.styleName: "SemiBold"
            font.family: "Open Sans"
            font.bold: ListView.isCurrentItem
            DesignEffect {
                effects: [
                    DesignDropShadow {
                        offsetY: -1
                        blur: 0
                    }]
            }
        }
        MouseArea {
            anchors.fill: parent
            onClicked: listView.currentIndex = index
        }
    }
    id: listView
    focus: true
    keyNavigationEnabled: true
}

二、用Column实现带方向键滚动和选中状态的列表

如果一定要用Column,可以结合Flickable实现滚动,再手动处理方向键事件和选中状态:

实现步骤:

  • 用Flickable包裹Column,让列表可以滚动
  • 定义变量记录当前选中项的索引
  • 监听方向键上下事件,修改选中索引,同时调整Flickable的滚动位置确保选中项可见
  • 每个列表项根据是否为当前选中项切换样式

示例代码:

Flickable {
    width: 240
    height: 200
    contentHeight: column.height
    focus: true
    property int currentIndex: 0

    Column {
        id: column
        spacing: 0
        Repeater {
            model: ["Selection 1", "Selection 2", "Selection 3", "Selection 4", "Selection 5"]
            delegate: Rectangle {
                width: 240
                height: 29
                gradient: Gradient {
                    GradientStop { position: 0; color: flickable.currentIndex === index ? "#a9a9a9" : "#d9d9d9" }
                    GradientStop { position: 1; color: flickable.currentIndex === index ? "#8c8c8c" : "#c2c2c2" }
                    orientation: Gradient.Vertical
                }
                Rectangle {
                    x: 0
                    y: 27
                    width: 240
                    height: 1
                    color: flickable.currentIndex === index ? "#50666666" : "#708c8c8c"
                }
                Text {
                    x: 8
                    y: 5
                    width: 164
                    height: 19
                    color: "#000000"
                    text: modelData
                    font.pixelSize: 13
                    styleColor: "#000000"
                    smooth: false
                    renderType: Text.QtRendering
                    font.weight: Font.Normal
                    font.styleName: "SemiBold"
                    font.family: "Open Sans"
                    font.bold: flickable.currentIndex === index
                    DesignEffect {
                        effects: [
                            DesignDropShadow {
                                offsetY: -1
                                blur: 0
                            }]
                    }
                }
                MouseArea {
                    anchors.fill: parent
                    onClicked: flickable.currentIndex = index
                }
            }
        }
    }

    Keys.onUpPressed: {
        if (currentIndex > 0) {
            currentIndex--
            var item = column.children[currentIndex]
            flickToItem(item)
        }
    }
    Keys.onDownPressed: {
        if (currentIndex < column.children.length - 1) {
            currentIndex++
            var item = column.children[currentIndex]
            flickToItem(item)
        }
    }

    function flickToItem(item) {
        var itemTop = item.y
        var itemBottom = item.y + item.height
        var viewTop = contentY
        var viewBottom = contentY + height

        if (itemTop < viewTop) {
            contentY = itemTop
        } else if (itemBottom > viewBottom) {
            contentY = itemBottom - height
        }
    }
}

内容的提问来源于stack exchange,提问作者SwiftySpeedy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.01 13:27:39