如何在QML中重新创建Android的Pull to Refresh图标?

时间:2018-01-15 19:12:42

标签: qt qml

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

enter image description here

我一直在尝试将它带到qml,但它并不那么容易。 有很多过渡,很快变得非常复杂。

在QML中重建应该有多困难? 使用canvas是更好的解决方案吗?

正如我第一次看到的那样,当箭头旋转时,滑动会以不同的滑动速度降低箭头。如果此箭头来自画布,它如何与外部事件相关,那就是滑动?

3 个答案:

答案 0 :(得分:1)

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

如果在开头拖动视觉对你来说不是问题,你可以简单地使用contentY的否定值,如果视图在开始之前被拖动,它将进入否定值。

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

最后一部分可能听起来很复杂,但它并不复杂,我碰巧知道它运作良好的事实,因为我已经使用过这种方法而the source code is already here on SO

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

链接答案中的实现与您需要的之间的显着差异是,由于我想要解决的特定问题的要求,链接的答案在每个委托中都有鼠标区域。您不需要,只需要一个覆盖视图的鼠标区域。

答案 1 :(得分:0)

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

我可以获得的更好的近似值在以下代码中。可能的缺点是对角线滑动也算作刷新意图。它可以通过GestureArea得到改善,但我现在懒得搞定。

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
        }
    }
}

答案 2 :(得分:0)

我用了这样的东西:

 //
 //  Slot called when the flick has started
 //
 onFlickStarted: {
     refreshFlik = atYBeginning
 }

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

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