在这篇文章中我们将一步一步地教大家怎么在Ubuntu手机平台来开发一个QML的应用。我们知道QML开发对很多初学者来说并不难。我们需要有一些简单的javascript的基础就可以开始我们的开发了。QML应用的调试也是很方便的。我们通过这个教程的学习,掌握基本的开发流程及界面设计。最终的应用显示的图片如下:
如果大家想对这个开发有更多的了解,可以参阅文章“Ubuntu手机应用QML开发 (视频)”
width: units.gu(80) height: units.gu(100)
import QtQuick 2.0 Item { anchors.fill: parent }
MainView { // objectName for functional testing purposes (autopilot-qt5) objectName: "mainView" // Note! applicationName needs to match the "name" field of the click manifest applicationName: "com.ubuntu.developer.liu-xiao-guo.flickr" /* This property enables the application to change orientation when the device is rotated. The default is false. */ //automaticOrientation: true // Removes the old toolbar and enables new features of the new header. useDeprecatedToolbar: false width: units.gu(80) height: units.gu(100) Page { id:mainPage title: i18n.tr("Flickr") clip:true PictureListView { anchors.fill: parent } } }
import QtQuick 2.0 import Ubuntu.Components 1.1 import Ubuntu.Components.ListItems 1.0 Item { id: mainScreen UbuntuListView { id: listView width: mainScreen.width height:mainScreen.height model: 10 delegate: Text { text: "Hi" } Scrollbar { flickableItem: listView } } }
import QtQuick 2.0 import Ubuntu.Components 1.1 import Ubuntu.Components.ListItems 1.0 Item { id: mainScreen ListModel { id: sampleListModel ListElement { imagePath: "images/sample.jpg" title: "First picture" } ListElement { imagePath: "images/sample.jpg" title: "Second picture" } ListElement { imagePath: "images/sample.jpg" title: "Third picture" } } Component { id: listDelegate BorderImage { source: "images/list.png" border { top:4; left:4; right:100; bottom: 4 } anchors.right: parent.right // width: mainScreen.width width: ListView.view.width property int fontSize: 25 Rectangle { id: imageId x: 6; y: 4; width: parent.height - 10; height:width; color: "white"; smooth: true anchors.verticalCenter: parent.verticalCenter BorderImage { source: imagePath; x: 0; y: 0 height:parent.height width:parent.width anchors.verticalCenter: parent.verticalCenter } } Text { x: imageId.width + 20 y: 15 width: ListView.view.width*2/3 text: title; color: "white" font { pixelSize: fontSize; bold: true } elide: Text.ElideRight; style: Text.Raised; styleColor: "black" } } } UbuntuListView { id: listView width: mainScreen.width height:mainScreen.height model: sampleListModel delegate: listDelegate } Scrollbar { flickableItem: listView } }
BorderImage { id:toolbar anchors.bottom:parent.bottom anchors.horizontalCenter: parent.horizontalCenter width: parent.width height: units.gu(6) source: "images/toolbar.png" border.left: 4; border.top: 4 border.right: 4; border.bottom: 4 Row { id:inputcontainer anchors.centerIn:toolbar anchors.verticalCenterOffset:6 spacing:12 Text { id:label font.pixelSize:30 anchors.verticalCenter:parent.verticalCenter; text: i18n.tr("Search:") font.bold:true style:Text.Raised styleColor:"#fff" color:"#444" } TextField { id:input placeholderText: "Please input a text to search:" width:220 text:"Beijing" } } Image { id: backbutton opacity:0 source: "images/back.png" anchors.verticalCenter:parent.verticalCenter anchors.verticalCenterOffset:0 anchors.left:parent.left anchors.leftMargin:8 MouseArea{ anchors.fill:parent onClicked: mainScreen.state="" scale:4 } } }
UbuntuListView { id: listView width: mainScreen.width height:mainScreen.height - toolbar.height model: sampleListModel delegate: listDelegate }
import QtQuick.XmlListModel 2.0
XmlListModel { id: feedModel // source: "http://api.flickr.com/services/feeds/photos_public.gne?format=rss2" source: "http://api.flickr.com/services/feeds/photos_public.gne?format=rss2&tags=" + escape(input.text) query: "/rss/channel/item" // flickr namespaceDeclarations: "declare namespace media=\"http://search.yahoo.com/mrss/\";" // Flickr XmlRole { name: "title"; query: "title/string()" } XmlRole { name: "imagePath"; query: "media:thumbnail/@url/string()" } XmlRole { name: "photoAuthor"; query: "author/string()" } XmlRole { name: "photoDate"; query: "pubDate/string()" } XmlRole { name: "url"; query: "media:content/@url/string()" } XmlRole { name: "description"; query: "description/string()" } XmlRole { name: "tags"; query: "media:category/string()" } XmlRole { name: "photoWidth"; query: "media:content/@width/string()" } XmlRole { name: "photoHeight"; query: "media:content/@height/string()" } XmlRole { name: "photoType"; query: "media:content/@type/string()" } }
UbuntuListView { id: listView width: mainScreen.width height:mainScreen.height - toolbar.height model: feedModel delegate: listDelegate }
import QtQuick 2.0 Image { id:image property bool loading:status != Image.Ready Image { id: container property bool on: false source: "images/spinner.png"; visible: loading anchors.centerIn:parent NumberAnimation on rotation { running: loading ; from: 0; to: 360; loops: Animation.Infinite; duration: 2000 } } }
Row { id:viewcontainer UbuntuListView { id: listView width: mainScreen.width height:mainScreen.height - toolbar.height model: feedModel delegate: listDelegate Scrollbar { flickableItem: listView } } SpinnerImage { id:viewscreen clip:true width:mainScreen.width height:mainScreen.height - toolbar.height smooth:true fillMode:Image.PreserveAspectFit } }
Component { id: listDelegate BorderImage { source: "images/list.png" border { top:4; left:4; right:100; bottom: 4 } anchors.right: parent.right // width: mainScreen.width width: ListView.view.width height: 180 property int fontSize: 25 Rectangle { id: imageId x: 6; y: 4; width: parent.height - 10; height:width; color: "white"; smooth: true anchors.verticalCenter: parent.verticalCenter SpinnerImage { source: imagePath; x: 0; y: 0 height:parent.height width:parent.width anchors.verticalCenter: parent.verticalCenter } } Text { x: imageId.width + 20 y: 15 width: mainScreen.width - x - 40 text: title; color: "white" font { pixelSize: fontSize; bold: true } elide: Text.ElideRight; style: Text.Raised; styleColor: "black" } MouseArea { anchors.fill: parent onClicked: { viewcontainer.x -= mainScreen.width } } } }
states: [ State { name: "view" PropertyChanges { target: viewcontainer x:-mainScreen.width } PropertyChanges { target: backbutton opacity:1 } PropertyChanges { target: inputcontainer opacity:0 } } ] transitions: [ Transition { NumberAnimation { target: viewcontainer; property: "x"; duration: 500 easing.type:Easing.OutSine} NumberAnimation { target: inputcontainer; property: "opacity"; duration: 200} NumberAnimation { target: backbutton; property: "opacity"; duration: 200} } ]
MouseArea { anchors.fill: parent onClicked: { viewscreen.source = imagePath.replace("_s", "_m") mainScreen.state = "view" } }
Image { id: backbutton opacity:0 source: "images/back.png" anchors.verticalCenter:parent.verticalCenter anchors.verticalCenterOffset:0 anchors.left:parent.left anchors.leftMargin:8 MouseArea{ anchors.fill:parent onClicked: mainScreen.state="" scale:4 } }
anchorToKeyboard: true
Rectangle { id: imageId x: 6; y: 4; width: parent.height - 10; height:width; color: "white"; smooth: true anchors.verticalCenter: parent.verticalCenter SpinnerImage { source: imagePath; x: 0; y: 0 height:parent.height width:parent.width anchors.verticalCenter: parent.verticalCenter } }
UbuntuListView { id: listView width: mainScreen.width height:mainScreen.height - toolbar.height model: feedModel delegate: listDelegate // let refresh control know when the refresh gets completed PullToRefresh { refreshing: listView.model.status === XmlListModel.Loading onRefresh: listView.model.reload() } Scrollbar { flickableItem: listView } }
import QtQuick 2.0 Image { id:image property bool loading:status != Image.Ready Image { id: container property bool on: false source: "images/spinner.png"; visible: loading anchors.centerIn:parent NumberAnimation on rotation { running: loading ; from: 0; to: 360; loops: Animation.Infinite; duration: 2000 } } // Create the detection of swipe signal swipeRight; signal swipeLeft; signal swipeUp; signal swipeDown; MouseArea { anchors.fill: parent property int startX; property int startY; onPressed: { startX = mouse.x; startY = mouse.y; } onReleased: { var deltax = mouse.x - startX; var deltay = mouse.y - startY; if (Math.abs(deltax) > 50 || Math.abs(deltay) > 50) { if (deltax > 30 && Math.abs(deltay) < 30) { // swipe right swipeRight(); } else if (deltax < -30 && Math.abs(deltay) < 30) { // swipe left swipeLeft(); } else if (Math.abs(deltax) < 30 && deltay > 30) { // swipe down swipeDown(); } else if (Math.abs(deltax) < 30 && deltay < 30) { // swipe up swipeUp(); } } } } }
Row { id:viewcontainer UbuntuListView { id: listView width: mainScreen.width height:mainScreen.height - toolbar.height model: feedModel delegate: listDelegate // let refresh control know when the refresh gets completed PullToRefresh { refreshing: listView.model.status === XmlListModel.Loading onRefresh: listView.model.reload() } Scrollbar { flickableItem: listView } } DetailedImage { id:viewscreen clip:true width:mainScreen.width height:mainScreen.height - toolbar.height smooth:true fillMode:Image.PreserveAspectFit onSwipeRight: { onClicked: mainScreen.state="" } } }