如何在QML中使用ListView并导航到其它页面中

我们知道ListView在QML应用中扮演非常重要的角色。看看我们的很多的应用都是在使用ListView。那么当我们点击ListView中的item并导航到另外一个页面呢?其实这样的方法有很多。在这篇文章中,我们来介绍其中的几种。开发者可以参照其中的设计,或自己想出更好的设计。


1)使用PageStack来完成


在我们的 RssReader中的例子中,我们使用了PageStack来完成我们的导航。我们可以把我们的每个页面都做成我们的Page。当我们的页面被点击后,我们把新的Page压入栈中。在返回时,我们只需要点击返回按钮即可:


     

我们可以在我的例程中找到相应的代码。


2)使用一个不可见的显示在需要时显示出来


在我们的使用中,我们使用两个重叠在一起的窗口,但是详细的页面只有在ListView中的item被点击后才能显示。在默认的情况下,我们显示ListView。

        ListView {
            id: listview

            clip: true
            anchors.fill: parent
            model:mymodel

            header: Text {
                text: "This is the header"
                font.pixelSize: 30

                Rectangle {
                    anchors.top: parent.bottom
                    width: listview.width
                    height: units.gu(0.4)
                    color: "blue"
                }
            }

            delegate: MyDelegate {}

            footer: Text {
                text: "This is the footer"
                font.pixelSize: 30
            }
        }

        Item {
            id: popup
            visible: false
            clip: true
            property url loadUrl
            onLoadUrlChanged: {
                opacity = 0;
                visible = (loadUrl == '' ? false : true);
                console.log("opacity: " + opacity );
                console.log("visible: " + visible );
            }
            anchors.fill: parent
            Rectangle {
                id: bg
                anchors.fill: parent
                color: "white"
            }
            MouseArea{
                anchors.fill: parent
                enabled: popup.visible
                //Eats mouse events
            }
            Loader{
                focus: true
                source: popup.loadUrl
                width: parent.width
                height: parent.height -toolbar.height
            }

            Rectangle {
                id: toolbar
                width: parent.width
                height: units.gu(4)
                anchors.bottom: parent.bottom
                color: "blue"

                Icon {
                    name: "previous"
                    width: units.gu(3.5)
                    height: units.gu(3.5)

                    MouseArea {
                        anchors.fill: parent
                        onClicked: {
                            popup.loadUrl = "";
                            ani.running = true;
                        }
                    }
                }
            }

            NumberAnimation on opacity {
                id: ani
                from: 0
                to: 1
                duration: 3000
            }
        }
    }


在上面的代码中,默认的情况下,我们试popup为不可见,它和listview是重叠在一起的。当item被点击后,我们才修改它为可见。这个代码在MyDelegate中实现的:

MyDelegate.qml


import QtQuick 2.0

Item {
    property Item item

    width: listview.width
    height: units.gu(8)
    Text {
        id: text
        text: title
        anchors.verticalCenter: parent.verticalCenter
        anchors.leftMargin: units.gu(10)
        font.pixelSize: 30

    }

    Rectangle {
        anchors.top: text.bottom
        width: parent.width
        height: units.gu(0.2)
        color: "gray"
    }

    Image {
        anchors.right: parent.right
        anchors.verticalCenter: parent.verticalCenter
        source: "images/arrow.png"
        rotation: -90
    }

    MouseArea {
        anchors.fill: parent
        onClicked: {
            console.log("it is clicked");
            popup.loadUrl = "ExampleQml.qml"
        }
    }
}

  

代码在地址  https://github.com/liu-xiao-guo/listview_visible



3)使用一个左右结构的页面,每次只有一个页面显示


同样的方法,我们可以使用一个左右排列的两个页面。每个页面的大小和主屏是一样大小的。但是,只有一个页面在不同的时间显示。我们可以通javascript来控制什么时候显示哪个页面。我们可以通过改变x坐标来显示我们所需要的页面。可以结合动画来展示效果:

        Row {
            id: view

            ListView {
                id: listview

                clip: true
                width: root.width
                height: root.height
                model:mymodel

                header: Text {
                    text: "This is the header"
                    font.pixelSize: 30

                    Rectangle {
                        anchors.top: parent.bottom
                        width: listview.width
                        height: units.gu(0.4)
                        color: "blue"
                    }
                }

                delegate: MyDelegate {}

                footer: Text {
                    text: "This is the footer"
                    font.pixelSize: 30
                }
            }

            // This is the second page
            DetailedPage {
                id: detailPage
                width: root.width
                height: root.height
            }

            Behavior on x {
                 NumberAnimation { duration: 500 }
            }
        }

通过使用Row来把两个页面并列显示,但是,每次只显示其中的一个页面。当点击ListView中的item后,改变当前view的x坐标来显示另外一个页面。这个是通过MyDelegate来改变的:

MyDelegate.qml


import QtQuick 2.0

Item {
    property Item item

    width: listview.width
    height: units.gu(8)
    Text {
        id: text
        text: title
        anchors.verticalCenter: parent.verticalCenter
        anchors.leftMargin: units.gu(10)
        font.pixelSize: 30

    }

    Rectangle {
        anchors.top: text.bottom
        width: parent.width
        height: units.gu(0.2)
        color: "gray"
    }

    Image {
        anchors.right: parent.right
        anchors.verticalCenter: parent.verticalCenter
        source: "images/arrow.png"
        rotation: -90
    }

    MouseArea {
        anchors.fill: parent
        onClicked: {
//            popup.loadUrl = "ExampleQml.qml"
            view.x = -root.width;
        }
    }
}

  

当然我们也可以把画面弄成上下排列的,使用同样的方法,我们可以把详细的画面移动到我们的视口中即可。