Les flèches latérales indiquent la possibilité de glisser son doigt vers la droite ou vers la gauche :
J'ai créé un projet avec deux fichiers QML : main.qml et Diaporama.qml ; le fichier main.qml contient à peu de chose près un code similaire à celui décrit dans l'article de lecteur video ; intéressons-nous au second fichier en charge d'afficher le diaporama : les images sont stockées localement dans le fichier binaire mais rien ne vous empêche de récupérer les images depuis le réseau par exemple :
Rectangle {
id: diaporama
signal leaveDiaporama()
width: 640
height: 360
color: "black"
Le diaporama est un écran en mode paysage avec un fond noir et un signal émis lorsque l'utilisateur clique sur la croix. Nous définissons ensuite un modèle statique de type ListModel:
ListModel {
id: myListModel
ListElement { file: "./images/0.jpg"; name: "Picture n°0"; desc:"Lorem ipsum dolor sit amet"}
ListElement { file: "./images/1.jpg"; name: "Picture n°1"; desc:"Lorem ipsum dolor sit amet"}
ListElement { file: "./images/2.jpg"; name: "Picture n°2"; desc:"Lorem ipsum dolor sit amet"}
ListElement { file: "./images/3.jpg"; name: "Picture n°3"; desc:"Lorem ipsum dolor sit amet"}
ListElement { file: "./images/4.jpg"; name: "Picture n°4"; desc:"Lorem ipsum dolor sit amet"}
ListElement { file: "./images/5.jpg"; name: "Picture n°5"; desc:"Lorem ipsum dolor sit amet"}
ListElement { file: "./images/6.jpg"; name: "Picture n°6"; desc:"Lorem ipsum dolor sit amet"}
ListElement { file: "./images/7.jpg"; name: "Picture n°7"; desc:"Lorem ipsum dolor sit amet"}
ListElement { file: "./images/8.jpg"; name: "Picture n°8"; desc:"Lorem ipsum dolor sit amet"}
ListElement { file: "./images/9.jpg"; name: "Picture n°9"; desc:"Lorem ipsum dolor sit amet"}
ListElement { file: "./images/10.jpg"; name: "Picture n°10"; desc:"Lorem ipsum dolor sit amet"}
...
}
Chaque élément représente un slide symbolisé par la triplette suivante :
- "file" : chemin pointant sur l'image
- "name" : titre du slide
- "desc" : légende du slide
Row {
anchors.fill: parent
Rectangle{
width: 64
height: parent.height
color: "black"
z:1
Image {
id: leftArrow
source: "images/left_arrow.png"
width: 26
anchors.centerIn: parent
}
}
ListView{
id:listView
orientation:ListView.Horizontal
width:parent.width-closeButton.width*2
height: parent.height
model:myListModel
delegate:myDelegate
maximumFlickVelocity:700
snapMode: ListView.SnapToItem
preferredHighlightBegin: 0; preferredHighlightEnd: 0
highlightRangeMode: ListView.StrictlyEnforceRange
highlightFollowsCurrentItem: true
onCurrentIndexChanged: {
if(listView.currentIndex == 0) leftArrow.visible = false;
else leftArrow.visible = true;
if(listView.currentIndex == listView.count-1) rightArrow.visible = false;
else rightArrow.visible = true;
}
}
Rectangle{
width: 64
height: parent.height
color: "black"
Button {
id: closeButton
iconSource: "images/close.png"
width: 64
MouseArea{
anchors.fill: parent
onClicked: {
leaveDiaporama()
}
}
}
Image {
id: rightArrow
source: "images/right_arrow.png"
width: 26
anchors.centerIn: parent
}
}
}
Les rectangles de droite et de gauche permettent d'afficher des petites flêches indiquant si des photos sont disponibles en slidant dans chacune des directions. La propriété orientation est donc positionnée à la valeur ListView.Horizontal pour le défilement latéral. La propriété delegate pointe sur le composant en charge de dessiner un slide identifié myDelegate (nous le décrirons juste après). La prorpriété maximumFlickVelocity indique la vitesse maximale de défilement en pixels/seconde. La propriété snapMode permet de définir où s'arrête le défilement : la valeur par défaut ListView.NoSnap indique que le défilement s'arrête n'importe où ; dans notre cas nous souhaitons l'arrêter sur un item (en l'occurence un slide) : nous pouvons donc utiliser soit ListView.SnapToItem soit ListView.SnapOneItem. ensuite il nous faut pister la valeur courante de l'index afin d'afficher ou de masquer les flêches latérales. Pour cela il faut fixer la propriété highlightRangeMode à ListView.StrictlyEnforceRange. Ainsi le signal onCurrentIndexChanged sera émis à chaque sélection/défilement de slide : nous pouvons alors jouer sur la visibilité des flêches droite/gauche.
Pour finir, je définis le composant delegate en charge de dessiner le slide composé d'un titre, d'une photo et d'une description :
Component{
id:myDelegate
Rectangle {
width:ListView.view.width
height:ListView.view.height
color: "black"
// Title
Text{
id:myTitle
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: myImage.top
anchors.bottomMargin: 10
color:"white"
font.bold: true
font.pointSize: 9
elide:Text.ElideRight
text: name
}
// Image
Image{
id:myImage
anchors.centerIn: parent
source: file
}
// Description
Text{
id:txt
width: parent.width
color:"white"
text:desc
font.pointSize: 7
wrapMode : Text.WordWrap
horizontalAlignment: Text.AlignHCenter
anchors.top:myImage.bottom
anchors.topMargin:10
anchors.left: myImage.left
anchors.right: myImage.right
}
}
}
Le titre du slide est bindé avec la propriété "name" du modèle myListModel. L'image est initialisée à partir de la source et le descriptif à partir du champ "desc".
Et voilà.
Le code complet est disponible ici
Aucun commentaire:
Enregistrer un commentaire