怎么在Ubuntu QML应用中侦测到Swipe手势

我们知道在触屏的手机中,可以利用手势可以产生一下动作。特别是Ubuntu手机,手势的操作利用的非常多。那么怎么可以在QML应用中侦测到手势呢?我以前在我的Flickr应用使用到一个手势的侦测。今天我们利用网上的一个例程来,做一个例子。这个例程更加具有可以重复利用性。我们的参阅代码地址:https://gist.github.com/kovrov/1742405

SwipeArea.qml

/* This code was written by Sergejs Kovrovs and has been placed in the public domain. */

import QtQuick 2.0

MouseArea {
    property point origin
    property bool ready: false
    property int threshold: units.gu(20)
    signal move(int x, int y)
    signal swipe(string direction)

    onPressed: {
        drag.axis = Drag.XAndYAxis
        origin = Qt.point(mouse.x, mouse.y)
    }

    onPositionChanged: {
        switch (drag.axis) {
        case Drag.XAndYAxis:
            if (Math.abs(mouse.x - origin.x) > threshold ) {
                drag.axis = Drag.XAxis
            }
            else if (Math.abs(mouse.y - origin.y) > threshold) {
                drag.axis = Drag.YAxis
            }
            break
        case Drag.XAxis:
            move(mouse.x - origin.x, 0)
            break
        case Drag.YAxis:
            move(0, mouse.y - origin.y)
            break
        }
    }

    onReleased: {
        switch (drag.axis) {
        case Drag.XAndYAxis:
            canceled(mouse)
            break
        case Drag.XAxis:
            swipe(mouse.x - origin.x < 0 ? "left" : "right")
            break
        case Drag.YAxis:
            swipe(mouse.y - origin.y < 0 ? "up" : "down")
            break
        }
    }
}

这里的代码定义了一个新的MouseArea的Component。这个Component可以在任何其它需要用到MouseArea的地方用到。你也可以理解为MouseArea的重载(从C++的角度,虽然并不精确)。我们对原作者的代码没有更多的改动,但是,我重新定义了一个“threshold”。这个是用来调整我们的Swipe的灵敏度的。比如,一个较大的值,使得我们必须使用较大的滑动才可以产生swipe的信号。较小的值,使得swipe的侦测更加容易。这个可以根据我们在实际的应用中进行调整。

那么我们如何使用这个SwipeArea的Component呢?

Swipe.qml

/* This code was written by Sergejs Kovrovs and has been placed in the public domain. */

import QtQuick 2.0

Item {
    id: root
    width: 480
    height: 320

    property var itemData: ["#22eeeeee", "#22bbbbbb", "#22888888", "#22555555", "#22222222"]
    property int currentIndex: 0

    onCurrentIndexChanged: {
        slide_anim.to = - root.width * currentIndex
        slide_anim.start()
    }

    PropertyAnimation {
        id: slide_anim
        target: content
        easing.type: Easing.OutExpo
        properties: "x"
    }

    Image {
        id: img
        anchors.verticalCenter: root.verticalCenter
        source: "images/wallpaper.jpg"
        fillMode: Image.PreserveAspectCrop
    }

    Item {
        id: content
        width: root.width * itemData.length
        property double k: (content.width - root.width) / (img.width - root.width)
        onXChanged: {
            img.x = x / k
//            console.log("img.x: " + img.x );
        }
        Repeater {
            model: itemData.length
            Rectangle {
                x: root.width * index
                width: root.width; height: root.height
                color: itemData[index]
                Text { text: index+1; anchors.centerIn: parent; font.pointSize: 100; color: "#88000000" }
            }
        }
    }

    SwipeArea {
        id: mouse
        anchors.fill: parent
        onMove: {
            content.x = (-root.width * currentIndex) + x
//            console.log("content.x " + content.x);
        }
        onSwipe: {
            switch (direction) {
            case "left":
                if (currentIndex === itemData.length - 1) {
                    currentIndexChanged()
                }
                else {
                    currentIndex++
                }
                break
            case "right":
                if (currentIndex === 0) {
                    currentIndexChanged()
                }
                else {
                    currentIndex--
                }
                break
            }
        }
        onCanceled: {
            currentIndexChanged()
        }
    }

    Row {
        anchors { bottom: parent.bottom; bottomMargin: 16; horizontalCenter: parent.horizontalCenter }
        spacing: 16
        Repeater {
            model: itemData.length
            Rectangle {
                width: 12; height: 12; radius: 6
                color: currentIndex === index ? "#88ffffff" : "#88000000"
                border { width: 2; color: currentIndex === index ? "#33000000" : "#11000000" }
            }
        }
    }
}

就像我们正常情况下使用MouseArea的情况一样,我们可以在我们需要侦测滑动的地方使用SwipeArea。这样,我们只需要捕获SwipeArea中发出的信号:

    SwipeArea {
        id: mouse
        anchors.fill: parent
        onMove: {
            content.x = (-root.width * currentIndex) + x
//            console.log("content.x " + content.x);
        }
        onSwipe: {
            switch (direction) {
            case "left":
                if (currentIndex === itemData.length - 1) {
                    currentIndexChanged()
                }
                else {
                    currentIndex++
                }
                break
            case "right":
                if (currentIndex === 0) {
                    currentIndexChanged()
                }
                else {
                    currentIndex--
                }
                break
            }
        }
        onCanceled: {
            currentIndexChanged()
        }
    }

这里,我们可以捕获onSwipe就可以得到Swipe的方向。在本例子中,我们只对左右感兴趣。我们可以通过手势向左或向右滑动来看一个图片的其它的部分。

  

整个测试项目的源码在:git clone https://gitcafe.com/ubuntu/swipe.git

时间: 2024-10-31 10:17:56

怎么在Ubuntu QML应用中侦测到Swipe手势的相关文章

如何在Ubuntu QML应用中播放视频

在这篇文章中,我们将介绍如何在Ubuntu QML应用中播放一个视频.为了实现方便,我们可以事先用手机录下一个视频,并置于我们已经创建好的项目中. 首先,我们利用Ubuntu SDK来创建一个"QML app with Simple UI (qmake)"的项目.我们修改我们的Main.qml文件如下: import QtQuick 2.0 import Ubuntu.Components 1.1 import QtMultimedia 5.0 /*! \brief MainView

如何在Ubuntu QML应用中播放音乐

昨天我看见一个开发者发了一个问题,询问如何播放声音.目前由于一些原因在模拟器中没法测试.其实,播放声音很容易.如果使用qmake的话,可能需要做一些修改才可以正确地在手机上播放. 我们首先使用SDK来创建一个简单的项目(QML app with Simple UI "qmake").我们记得修改我们的Main.qml如下: import QtQuick 2.0 import Ubuntu.Components 1.1 import QtMultimedia 5.0 /*! \brief

如何在Ubuntu QML应用中震动(vibration)

对于有些QML应用来说,震动是非常重要的一个功能.特别是对一下游戏来说.那么我们怎么在QML应用中震动呢? 我们官方有一个API HapticsEffect,这个API的功能就是让我们的应用来震动的.使用这个API非常容易: import QtQuick 2.0 import Ubuntu.Components 1.1 import QtFeedback 5.0 /*! \brief MainView with a Label and Button elements. */ MainView {

如何在Ubuntu QML应用中进行语言录音

在QML API中,目前并没有一个相应的API来进行录音.我们必须使用Qt C++ API QAudioRecorder来进行录音的工作.在这篇文章中,我们来介绍如何使用这个API来进行录音. 首先,我们来创建一个"QML App with C++ plugin (qmake)"模版的应用.注意qmake的项目必须是在15.04及以上的target上才可以运行. 为了录音,我创建了一个叫做"AudioRecorder"的类: audiorecorder.h #ifn

如何在Ubuntu QML应用中判断应用的方位(landscape或portrait)

我们知道对于一些应用来说,判断方位可以使得我们可以重新定位我们的应用的布局,以使得我们的应用在不同的方位中更加合理及好看.在这篇文章中,我们来介绍如何来侦测应用方位的变化. 我们首先来创建一个我们自己的简单的QML应用.对于大多数的QML应用来说,一般是含有一个"MainView"的: MainView { id: root // objectName for functional testing purposes (autopilot-qt5) objectName: "m

如何在Ubuntu QML应用中使用Push Notification

我们知道目前Ubuntu手机平台有些类似iPhone平台,是一个单任务的操作系统,虽然系统本身具有多任务的功能.如果当前的应用被推到后台的话,应用将会被自动挂起,而不会被系统所运行.在这个时候如果我们的应用需要等待一个消息,比如就想微信之类的信息,我们就要使用Ubuntu平台所提供的Push Notification机制来实现我们的类似多任务的东西.当通知被收到后,我们就可以直接点击接受到的通知,应用又会被重新运行到前台. 关于Push notification,在我们的开发者网站上,有一篇文章

如果在Ubuntu QML应用中在应用一启动时就得到屏幕的分辨率

对于有些应用来说,获取屏幕分辨率这个信息可能是重要的.比如有些游戏或阅读器应用,希望在应用启动后,马上得到屏幕的分辨率,这样可以和容易地适配不同屏幕尺寸的手机或装置.有些应用可以是用QtQuick.Window的Screen来得到这个信息,但是我们可以看一下在文章中如下的提醒: Note that the Screen type is not valid at Component.onCompleted, because the Item or Window has not been displ

如何在Ubuntu QML应用中实现一个垂直的Slider

我们在使用Ubuntu SDK中的Slider的时候,我们发现,它没有orientation的属性尽管在Qt官方网站的slider是有这个属性的.在默认的情况下,这个Slider是水平的.那么我们该如实现这个呢? 我们的任何一个QML Item都有一个属性叫做rotation.我们可以通过这个属性来得到一个旋转90度的水平Slider.这样我们就可以用如下的代码来实现了: import QtQuick 2.0 import Ubuntu.Components 1.1 /*! \brief Mai

在QML应用中实现threading多任务

在这个样例中,我们将介绍怎样在QML应用中使用QML语言提供的threading功能,实现多任务. 很多其它的阅读在:http://doc.qt.io/qt-5/qtquick-threading-example.html 我们使用Ubuntu SDK来创建以个最主要的QML项目: Main.qml import QtQuick 2.0 import Ubuntu.Components 1.1 /*! \brief MainView with a Label and Button element