Last active
December 13, 2022 22:38
-
-
Save oKcerG/81e769ca5c7eb62bab8a04fb8f88d262 to your computer and use it in GitHub Desktop.
An experiment trying to recreate Google's Android contact list in QML
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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