[Qt-qml] Section header 'always on top'

Gregory Schlomoff gregory.schlomoff at gmail.com
Fri Aug 13 10:20:30 CEST 2010


Hehehe, that's so funny. We made a component that does the exact same thing,
except that we would keep all section headers visible on screen, stacked
either on top or bottom of the ListView, so that you could click on a
section header to jump to this section.

But that's definetely a proof that this is a much needed feature.

And yes, ListView.previousSection / nextSection are much needed!

On Fri, Aug 13, 2010 at 3:10 PM, <tapani.mikola at nokia.com> wrote:

> Hi,
>
> Wanted to share one exciting (at least IMO) piece of code.
>
> Some existing devices have this fancy visual feature that when scrolling
> a list the section header stays on top and only when the next section
> header scrolls in it 'pushes' the old one away. (See the attached picture)
> Unfortunately QML in Qt 4.7 does not support that kind of property for
> ListView. Section headers always scroll along with the list items. But
> no worries, as the following example (extended from the ListView
> documentation example) does the trick. Hopefully the comments in line
> the code are enough for documentation. Post any comments or questions to
> this list.
>
> As continuation, I am planning to create a couple of JIRA items:
> * To have a section.alwaysOnTop -property (or something similar) for
> ListView (the below trick wouldn't be needed at all)
> * To have a 'ListView.previousSection et al' attached properties
> available also to the section delegate (currently only available for
> item delegate). These would make these kind of things easier to do. Now
> the code has to refer to list & model through their id:s
>
> First a component to draw the section header:
>
> ---- Code snippet starts <SectionHeader.qml> ----
>
> import Qt 4.7
>
> Rectangle {
>     color: "lightsteelblue"
>     height: childrenRect.height
>     property alias text: hdrText.text
>     opacity:  0.85
>
>     Text {
>         id: hdrText
>         font.bold: true
>         font.pixelSize:26
>     }
> }
>
> ---- Code snippet ends <SectionHeader.qml> ----
>
> and then the main qml file:
>
> --- Code snippet starts <alwaysonsectionheader.qml> ----
>
> import Qt 4.7
>
> Rectangle {
>      id: container
>      width: 200
>      height: 250
>      gradient: Gradient {
>          GradientStop { position:  0.0; color: "#555555" }
>          GradientStop { position:  1.0; color: "#eeeeee" }
>      }
>      Rectangle {
>          x: 180
>          width: 20
>          height: parent.height
>          gradient: Gradient {
>              GradientStop { position:  0.0; color: "#eeeeee" }
>              GradientStop { position:  1.0; color: "#555555" }
>          }
>      }
>
>      ListModel {
>          id: animalsModel
>          ListElement { name: "Parrot"; size: "Small" }
>          ListElement { name: "Guinea pig"; size: "Small" }
>          ListElement { name: "Mouse"; size: "Small" }
>          ListElement { name: "Sparrow"; size: "Small" }
>          ListElement { name: "Dog"; size: "Medium" }
>          ListElement { name: "Cat"; size: "Medium" }
>          ListElement { name: "Dolphin"; size: "Medium" }
>          ListElement { name: "Seal"; size: "Medium" }
>          ListElement { name: "Elephant"; size: "Large" }
>          ListElement { name: "Blue whale"; size: "Large" }
>          ListElement { name: "Rhino"; size: "Large" }
>          ListElement { name: "Ostrich"; size: "Large" }
>          ListElement { name: "Sperm whale"; size: "Large" }
>          ListElement { name: "Giraffe"; size: "Large" }
>      }
>
>      // The section header delegate
>      Component {
>          id: sectionDelegate
>          Item {
>              id: sectionItem
>              height:  childrenRect.height
>              property real myPos: y - animalsList.contentY
>
>              // For some reason, this does not work
>              //visible: myPos >= 0
>
>              // The visible -property setting(s) below are needed only,
> if SectionHeader has transparency (opacity < 1.0)
>              onMyPosChanged: {
>                  if (animalsList.contentY >= 0) {
>                      if (myPos < height*2 && myPos > -height*2) {
>                          // In the 'hot' area
>
>                          // Set the correct text.
>                          if (myPos < 0) {
>                              sectionHeader.text = section
>                              visible = false
>                          }
>                          else {
>                              // Oooh, would it be nice to have
> 'previousSection' property
>
>                              // One can do this, if there is a
> cacheBuffer for the list, if not I sometimes get undefined from get() as
>                              // the listitem above the section header
> is already deleted
>                              //sectionHeader.text = y >= 1 ?
> animalsModel.get(animalsList.indexAt(0, y-1)).size :
> animalsModel.get(0).size
>
>                              // Safer version that does not require
> cacheBuffer for the animalsList
>                              var nextIndex = animalsList.indexAt(0,
> y+height+1)
>                              sectionHeader.text = nextIndex >= 1 ?
> animalsModel.get(nextIndex-1).size : animalsModel.get(0).size
>                              visible = true
>                          }
>
>                          // Then set y of the section header overlay to
> give an illusion of 'push'
>                          if (myPos < height && myPos >= 0)
>                              sectionHeader.y = 0 - (height - myPos) //
> push the old header away -effect
>                          else
>                              sectionHeader.y = 0 // clean up after push
>                      }
>                      else visible = true
>                  }
>                  else visible = true
>              }
>              SectionHeader {
>                  width: animalsList.width
>                  text: section
>              }
>          }
>      }
>
>      Item {
>          anchors.fill: parent
>          ListView {
>              id: animalsList
>              anchors.fill: parent
>              model: animalsModel
>              delegate: Text { text: name; font.pixelSize: 24 }
>
>              section.property: "size"
>              section.criteria: ViewSection.FullString
>              section.delegate: sectionDelegate
>          }
>
>          // The section header item (rectangle+text overlayed on top of
> the ListView)
>          SectionHeader {
>              id: sectionHeader
>              visible: !animalsList.atYBeginning // not wanted when list
> is at beginning (list can bounce and the section delegate is at right
> place)
>              width: parent.width
>              text: animalsList.currentSection
>          }
>      }
>  }
>
> ---- Code snippet ends <alwaysonsectionheader.qml> ----
>
>
> _______________________________________________
> Qt-qml mailing list
> Qt-qml at trolltech.com
> http://lists.trolltech.com/mailman/listinfo/qt-qml
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.qt.nokia.com/pipermail/qt-qml/attachments/20100813/72f89e5a/attachment.html 


More information about the Qt-qml mailing list