qml学习:ListView

这篇承接上篇,这回来谈谈ListView的使用,首先的是,先了解ListView的是什么,及其相关的属性代表的作用.

ListView是QML中用于显示垂直或者水平列表的视图组件.他可以显示一系列的项目,并且每个项目的外观和行为由delegate属性定义.ListView通常与数据模型(比ListModel) 搭配使用,以动态生成列表项.它有许多属性可以设置,通过这些不同的属性设置,来达到我们想要达到的列表视图效果;

一.下面是ListView的一些属性说明                                 

1. **model**: 数据模型,可以是一个列表、数组或自定义的模型对象。
2. **delegate**: 用于定义每个列表项的外观和行为。
3. **orientation**: 列表的方向,可以是 `Qt.Vertical` 或 `Qt.Horizontal`。
4. **currentIndex**: 当前选中的项的索引。
5. **currentItem**: 当前选中的项。
6. **highlight**: 用于定义高亮项的外观。
7. **highlightMoveDuration**: 高亮项移动的动画持续时间。
8. **highlightResizeDuration**: 高亮项大小变化的动画持续时间。
9. **highlightFollowsCurrentItem**: 是否让高亮项跟随当前选中的项。
10. **spacing**: 列表项之间的间距。
11. **cacheBuffer**: 用于缓存的像素数。
12. **clip**: 是否裁剪超出边界的内容。
13. **interactive**: 是否允许用户交互。
14. **snapMode**: snapMode属性用于控制 `ListView` 在滚动时是否对齐到项的边界。它可以帮助用户更容易地浏览和选择列表项。`snapMode` 属性有以下几种值:

(1). **ListView.NoSnap**:不对齐到项的边界。滚动是自由的,用户可以停在任意位置。
(2). **ListView.SnapToItem**:对齐到最近的项的边界。当用户停止滚动时,列表会自动调整位置,使最近的项对齐到视图的边界。
(3). **ListView.SnapOneItem**:每次滚动只对齐到一个项的边界。即使用户快速滚动,列表也会逐项对齐。

15. **flickableDirection**: 允许滚动的方向,可以是 `Flickable.AutoFlickDirection`, `Flickable.HorizontalFlick`, `Flickable.VerticalFlick`, 或 `Flickable.HorizontalAndVerticalFlick`.
16. **boundsBehavior**: 控制滚动到边界时的行为,可以是

(1).`Flickable.StopAtBounds`:滚动到边界时停止,不允许超出边界

(2). `Flickable.DragOverBounds`:允许滚动超出边界,但是会有回弹效果


17. **section.property**: 用于分组的属性。
18. **section.criteria**: 分组的标准,可以是 `ViewSection.FullString`, `ViewSection.FirstCharacter`, 或 `ViewSection.FirstLetter`.
19. **section.delegate**: 用于定义分组标题的外观和行为。

上述的属性种类还是比较多的,在实际项目的开发中,只需要使用到一小部分,当需要设置可以来查询对应属性的效果

以下是我个人在项目中的一个示例:

property var numberTexts: ["一", "二", "三", "四", "五", "六", "七", "八", "九"]
ListModel {id: cookStepList}//烹饪步骤
            ListView {
                id: lvCookingStepList
                width: parent.width
                height: contentHeight
                interactive: false
                model:cookStepList
                
                delegate:  Column {
                    width: 552
                    spacing:12
                    Text {
                        id:stepText
                        width: parent.width
                        text: qsTr("步骤%1").arg(numberTexts[index])
                        font.pixelSize: 26
                        color: "white"
                    }
 
                    Item {
                        id: imgCookingStepItem
                        width: parent.width
                        height: 414
                        Rectangle{
                            id:loadingIndicatorCookingStep
                            width: imgCookingStep.width
                            height: imgCookingStep.height
                            radius: 16
                            color:"#CECECE"
                            visible: true
                            Image {
                                id: imgStepLoading
                                anchors.centerIn: parent
                                fillMode: Image.Stretch
                                source: "you/path/img.png"
                            }
                        }

                        Image {
                            id: imgCookingStep
                            width: parent.width
                            height: parent.height
                            source: model.fileUrl
                            clip: true
                             //保持图片原比例再缩放填充到区域
                            fillMode: Image.PreserveAspectCrop
                            asynchronous: true
                            visible: false //因为显示的是OpacityMask需要false


                            onStatusChanged: {
                                if (status == Image.Loading) {
                                    loadingIndicatorCookingStep.visible = true
                                    console.log("Image is loading...")
                                } else if (status == Image.Ready) {
                                    loadingIndicatorCookingStep.visible = false
                                    console.log("Image loaded successfully.")
                                } else if (status == Image.Error) {
                                    loadingIndicatorCookingStep.visible = true
                                    console.log("Failed to load image from URL:",
                                                source)
                                }
                            }
                        }

                        //圆角遮罩Rectangle
                        Rectangle {
                            id: maskRecCookingStep
                            anchors.centerIn: parent
                            width: imgCookingStep.width
                            height: imgCookingStep.height

                            color: "transparent"
                            Rectangle {
                                anchors.fill: parent
                                width: imgCookingStep.paintedWidth
                                height: imgCookingStep.paintedHeight
                                color: "black"
                                radius: 16
                            }
                            visible: false //因为显示的是OpacityMask需要false
                        }

                        //遮罩后的图案
                        OpacityMask {
                            id: maskCookingStep
                            anchors.fill: imgCookingStep
                            source: imgCookingStep.source.length===0 ? loadingIndicatorCookingStep : imgCookingStep
                            maskSource: maskRecCookingStep
                        }
                    }
                   
                    Text {
                        id: textContent
                        width: parent.width
                        text: model.content
                        font.pixelSize: 26
                        color: "white"
                        wrapMode: Text.WordWrap
                        maximumLineCount: 3
                        elide: Text.ElideRight
                    }
                    Item {
                        width: parent.width
                        height: 6
                    }
                }
            }

效果的话,各位未来的大佬们可以自己去测试,搭配特定的属性,实现自己需要的效果;还有就是

UI上的一点心得:

1.布局尽可能的简单化,不要使用太复杂的布局属性(避免一些莫名其妙的布局冲突,比如说能用Column,就不用ColumnLayout)

2.复杂的界面就拆分多个简单布局,控制好代码量(方便复用,方便排查问题)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值