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

QML实现类iPhone联系人索引栏及滚动Section文本不更新问题求助

Fixing the Static Section Label in Your QML ListView Scroll Indicator

Hey there! I see you're trying to replicate that handy iPhone-style scroll indicator that shows the current section as you scroll, but your label's stuck on "A". Let's break down what's going wrong and fix it.

The Root of the Problem

Your topItem and topItemFix properties are only evaluated once when the Label is created—they don't update as the ListView scrolls. That means even when you scroll to a new section, the Label is still referencing the first item from when the component loaded.

Additionally, itemAt(0, cView.contentY) isn't the right way to get the first visible item. The itemAt() method takes x/y coordinates relative to the ListView's content, not the viewport.

The Fix

We need to make sure we're always grabbing the first visible item in the ListView, and updating that reference whenever the scroll position changes. Here are two solid approaches:

Approach 1: Use visibleItems (Cleanest)

ListView has a visibleItems property that returns an array of currently visible items. We can use this to get the first visible item and its section directly:

Label {
    anchors.centerIn: parent
    color: "White"
    font.bold: true
    font.pixelSize: 40
    // Get the first visible item's section, or fallback to empty if none
    text: cView.visibleItems.length > 0 ? cView.visibleItems[0].ListView.section : ""
}

Approach 2: Listen to Scroll Events

If you need more control, you can explicitly update the current section whenever the ListView's content position changes:

Label {
    anchors.centerIn: parent
    color: "White"
    font.bold: true
    font.pixelSize: 40
    property string currentSection: ""

    // Update section when ListView scrolls
    Connections {
        target: cView
        function onContentYChanged() {
            if (cView.visibleItems.length > 0) {
                currentSection = cView.visibleItems[0].ListView.section
            } else {
                currentSection = ""
            }
        }
    }

    text: currentSection
}

Bonus: Tweak the Indicator Position

Your current y-position formula for bigRect might be off. Here's a more reliable way to center the indicator on the scroll handle:

y: scrollBar.position * scrollBar.height - bigRect.height/2

This ensures the indicator stays centered over the scroll thumb as you drag it.

Full Modified ScrollBar Code

Putting it all together, your ScrollBar should look like this:

ScrollBar.vertical: ScrollBar {
    id: scrollBar
    Rectangle {
        id: bigRect
        visible: scrollBar.pressed
        color: "#1976D2"
        width: 96
        height: width
        radius: width/2
        x: -width - 16
        // Centered over scroll thumb
        y: scrollBar.position * scrollBar.height - height/2
        z:4
        Rectangle {
            width: parent.width/2
            height: parent.height/2
            x: width
            y: height
            color: parent.color
        }
        Label {
            anchors.centerIn: parent
            color: "White"
            font.bold: true
            font.pixelSize: 40
            text: cView.visibleItems.length > 0 ? cView.visibleItems[0].ListView.section : ""
        }
    }
}

Why This Works

  • visibleItems automatically updates as the ListView scrolls, so we always get the latest first visible item.
  • The section property of that item (ListView.section) gives us the correct current section character.

Give this a try—it should update the label to match the current section as you scroll!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:43:58