关于qt:如何在QML 中创建Android Pull to Refresh 图标?

How to recreate Android's Pull to Refresh icon in QML?

这是用于在 Android 中刷新视图的下拉刷新图标。

enter

在 QML 中重新创建这应该有多困难?
使用画布是更好的解决方案吗?

正如我第一次看到的那样,在箭头旋转的同时,滑动会以不同的滑动速度将箭头拉下。如果这个箭头来自画布,它如何与外部事件相关联,那就是滑动?


我用过这样的东西:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 //
 //  Slot called when the flick has started
 //
 onFlickStarted: {
     refreshFlik = atYBeginning
 }

 //
 //  Slot called when the flick has finished
 //
 onFlickEnded: {
     if ( atYBeginning && refreshFlik )
     {
         refresh()
     }
 }

它似乎按预期工作并且易于实现


问题在于 Flickable 和派生的 ListView 在视觉行为被禁用的情况下并没有真正提供任何过拖或过冲信息。

如果在开始处拖动视觉对您来说不是问题,您可以简单地使用 contentY 的否定值,如果视图在开始之前被拖动,则该值会变为负值。

我能想到的唯一解决方案是没有任何视觉过度拖动但仍然获得过度拖动信息以驱动您的复习是将视图交互属性设置为 false,并将另一个鼠标区域放在上面并手动将拖动和轻弹重定向到现在的非交互式视图。

最后一部分可能听起来很复杂,但它并不那么复杂,而且我碰巧知道它运行良好,因为我已经使用了这种方法并且源代码已经在 SO 上。<铅>

因此,一旦您可以访问控制视图的鼠标区域,您就可以跟踪负片的数量,并使用该信息来驱动复习的逻辑和动画。

链接答案中的实现与您需要的显着区别在于链接答案在每个代表中都有鼠标区域,这是由于我要解决的特定问题的要求。你不需要那个,你只需要一个覆盖视图的鼠标区域。


基于 dtech\\'s 涉及多个 Flickable 元素的经验,我找到了一个更简单的解决方案,该解决方案基本上包括用 MouseArea 填充 Flickable,将其 boundsBehavior 属性设置为 Flickable.StopAtBounds,以及从那里开始,如果它位于顶部,则根据 mouseY 值执行操作。

我能得到的更好的近似值是下面的代码。一个可能的缺点是对角滑动也算作刷新意图。 GestureArea 可以改进它,但我现在懒得动手。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Window 2.2

ApplicationWindow {
    property real mm: Screen.pixelDensity
    property real margins: 2 * mm
    id: mainWindow
    visible: true
    width: 60 * mm
    height: 120 * mm
    title: qsTr("Hello World")

    ListModel {
        id: myModel
        Component.onCompleted: {
            for(var i = 0; i <= 100; ++i) {
                myModel.append({num: i})
            }
        }
    }
    ListView {
        id: view
        boundsBehavior: Flickable.StopAtBounds
        interactive: true
        anchors.fill: parent
        model: myModel
        spacing: 4
        delegate: Rectangle {
            width: parent.width
            height: 25 * mm
            border.color: 'red'
            Text {
                id: name
                text: num
                anchors.centerIn: parent
            }
        }
        Rectangle {
            signal follow
            id: swatch
            width: 15 * mm
            height: width
            radius: width / 2
            color: 'lightgray'
            anchors.horizontalCenter: parent.horizontalCenter
            y: - height
        }
        MouseArea {
            property int mouseYSart
            property int biggerMouseY
            anchors.fill: view
            onPressed: {
                mouseYSart = mouseY
                biggerMouseY = 0
            }
            onMouseYChanged: {
                if(view.contentY == 0) {
                    var currentMouseY = mouseY
                    if(currentMouseY > biggerMouseY) {
                        biggerMouseY = currentMouseY
                        swatch.y += 1
                    }
                    if(currentMouseY < biggerMouseY) {
                        biggerMouseY = currentMouseY
                        swatch.y -= 1
                    }
                }
            }
            onReleased: swatch.y = - swatch.height
        }
    }
}