Skip to content

Instantly share code, notes, and snippets.

@oKcerG
Last active December 13, 2022 22:38
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oKcerG/81e769ca5c7eb62bab8a04fb8f88d262 to your computer and use it in GitHub Desktop.
Save oKcerG/81e769ca5c7eb62bab8a04fb8f88d262 to your computer and use it in GitHub Desktop.
An experiment trying to recreate Google's Android contact list in QML
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQml 2.2
import QtQuick.Controls.Material 2.0
import QtQuick.Layouts 1.3
// DEMO VIDEO : https://gfycat.com/WarlikeImportantAmericanrobin
ApplicationWindow {
visible: true
width: 640
height: 480
property var materialColors: ["Red","Pink","Purple","DeepPurple","Indigo","Blue","LightBlue","Cyan","Teal","Green","LightGreen","Lime","Yellow","Amber","Orange","DeepOrange","Brown","Grey","BlueGrey"]
function randomColor() {
var colorName = materialColors[Math.floor(Math.random()*materialColors.length)];
return Qt.darker(Material.color(Material[colorName]), 1.1);
}
ListView {
id: listView
anchors.fill: parent
ScrollBar {
id: scrollBar
stepSize: 1 / listView.count
size: listView.visibleArea.heightRatio
active: listView.moving || pressed
anchors {
top: parent.top
bottom: parent.bottom
right: parent.right
}
Binding on position {
when: !scrollBar.pressed
value: listView.visibleArea.yPosition
}
Binding {
when: scrollBar.pressed
target: listView
property: "contentY"
value: Math.round(scrollBar.position/scrollBar.stepSize) * scrollBar.stepSize * listView.contentHeight
}
Rectangle {
visible: scrollBar.pressed
color: Material.primary
width: 96
height: width
radius: width/2
x: -width - 16
y: Math.max(scrollBar.position * scrollBar.height - height + scrollBar.contentItem.height/2, 0)
Rectangle {
width: parent.width/2
height: parent.height/2
x: width
y: height
color: Material.primary
}
Label {
anchors.centerIn: parent
color: "white"
font.bold: true
font.pixelSize: 40
property Item topItem: listView.itemAt(0, listView.contentY)
property Item topItemFix: topItem ? topItem: listView.contentItem.children[0]
text: topItemFix.ListView.section
}
}
}
model: ["Adan Gula","Alexandria Armand","Alverta Gorney","Annalisa Dixion","Arlene Drapeau","Ashely Euler","Ashleigh Terry","Audra Vannorman","Bibi Fraire", "Branda Melgoza","Breanna Rotenberry","Brigette Delk","Bruno Raso","Calandra Dudney","Carrol Dedeaux","Celina Bichrest","Celinda Frutos","Celsa Moen","Charise Milan","Corazon Burrus","Coreen Dehner","Coretta Stillwell","Cornell Fierros","Deedee Ruggerio","Demetrice Mcclaren","Desiree Marcano","Dimple Harig","Divina Fahie","Don Thill","Ellena Fredrick","Elmo Routh","Elsie Raulerson","Ervin Bardsley","Estela Alverson","Eufemia Sheely","Fawn Opie","Fred Ralphs","Genevie Spires","Genna Quin","Gerri Aden","Gianna Shears","Gilda Doyel","Glady Peguero","Guy Sondag","Herschel Flowers","Hilda Hamm","Hiroko Mccarley","Jackeline Millington","Jacqualine Twiss","Jacquelyne Worsley","Janelle Broman","Jani Reddish","Jasper Krone","Jene Gump","Jimmie Cooley","Kellye Wiest","Kristie Jules","Kymberly Moodie","Latesha Netter","Lavelle Lasala","Lesli Czapla","Lorette Prescott","Lorie Hoeft","Lyndia Schwalm","Mable Marron","Marcelino Spence","Marcie Yopp","Margrett Spagnuolo","Maris Ruff","Marvella Bowlby","Mauro Winberg","Maybelle Chute","Meghan Burts","Micah Hoggan","Mireille Eastin","Mitsue Ohler","Monica Mccall","Morris Cappel","Myong Bale","Nannie Poore","Noella Gledhill","Ofelia Bane","Phoebe Bui","Quincy Sweeting","Raguel Ross","Raymundo Headlee","Ressie Helt","Rikki Gilligan","Roselee Swain","Shanda Ballew","Stephine Dimauro","Tamesha Roop","Temple Mcbain","Tiesha Crumley","Tova Kiel","Wade Fossum","Willodean Ferguson","Winfred High","Winter Furrow","Yvone Edge"]
snapMode: ListView.SnapToItem
property Item topItem: itemAt(0, contentY)
property Item topItemFix: topItem ? topItem: contentItem.children[0]
delegate: ItemDelegate {
id: delegate
property ListView listView: ListView.view
property string section: ListView.section
property bool isLastOfSection: ListView.nextSection !== section && index !== 0
property bool wasTopItem: false
property bool isTopItem: delegate === listView.topItemFix
onIsTopItemChanged: if (isTopItem) wasTopItem = true;
width: parent.width
leftPadding: 48
rightPadding: 0
contentItem: RowLayout {
spacing: 16
Rectangle {
height: delegate.height
width: height
radius: height/2
color: randomColor()
Label {
color: Qt.rgba(1, 1, 1, 0.5)
anchors.centerIn: parent
text: delegate.section
font.pixelSize: 20
}
}
Label {
Layout.fillWidth: true
text: delegate.wasTopItem ? modelData : modelData
}
}
background: Label {
id: sectionDummy
visible: (delegate === listView.topItemFix) || (delegate.ListView.previousSection !== delegate.ListView.section) && (y < delegate.height)
width: 48
y: Math.min(Math.max(delegate.ListView.view.contentY - delegate.y, 0), delegate.isLastOfSection ? 0 : delegate.height)
height: delegate.height
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: delegate.section
opacity: Math.max(Math.min(1 - (delegate.ListView.view.contentY - delegate.y - y) / delegate.height, 1), 0)
font.bold: true
color: Material.primary
}
}
section {
property: "modelData"
criteria: ViewSection.FirstCharacter
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment