From e7b80a9ae2130fb50c1178849c496ed359ef601d Mon Sep 17 00:00:00 2001 From: Mikhail Rogachev Date: Thu, 14 Jul 2022 15:29:14 +0300 Subject: [PATCH] feat(StatusScrollView): New scrollview component without twitches (#766) --- .../StatusAppCommunitiesPortalView.qml | 2 +- sandbox/demoapp/StatusAppCommunityView.qml | 2 +- .../demoapp/StatusAppProfileSettingsView.qml | 3 +- sandbox/main.qml | 398 +++++++++--------- src/StatusQ/Controls/StatusScrollBar.qml | 24 ++ src/StatusQ/Controls/qmldir | 1 + src/StatusQ/Core/StatusScrollView.qml | 48 +++ src/StatusQ/Core/qmldir | 2 + src/StatusQ/Popups/StatusColorDialog.qml | 2 +- 9 files changed, 272 insertions(+), 210 deletions(-) create mode 100644 src/StatusQ/Controls/StatusScrollBar.qml create mode 100644 src/StatusQ/Core/StatusScrollView.qml diff --git a/sandbox/demoapp/StatusAppCommunitiesPortalView.qml b/sandbox/demoapp/StatusAppCommunitiesPortalView.qml index a9f4e23d..c7923468 100644 --- a/sandbox/demoapp/StatusAppCommunitiesPortalView.qml +++ b/sandbox/demoapp/StatusAppCommunitiesPortalView.qml @@ -10,7 +10,7 @@ import StatusQ.Components 0.1 import "../demoapp/data" 1.0 -ScrollView { +StatusScrollView { id: root QtObject { diff --git a/sandbox/demoapp/StatusAppCommunityView.qml b/sandbox/demoapp/StatusAppCommunityView.qml index d39f1287..72e5b650 100644 --- a/sandbox/demoapp/StatusAppCommunityView.qml +++ b/sandbox/demoapp/StatusAppCommunityView.qml @@ -59,7 +59,7 @@ StatusAppThreePanelLayout { } } - ScrollView { + StatusScrollView { id: scrollView anchors.top: statusChatInfoToolBar.bottom diff --git a/sandbox/demoapp/StatusAppProfileSettingsView.qml b/sandbox/demoapp/StatusAppProfileSettingsView.qml index 7303136c..3e149a5b 100644 --- a/sandbox/demoapp/StatusAppProfileSettingsView.qml +++ b/sandbox/demoapp/StatusAppProfileSettingsView.qml @@ -3,6 +3,7 @@ import QtQuick.Controls 2.14 import StatusQ.Components 0.1 import StatusQ.Layout 0.1 +import StatusQ.Core 0.1 import StatusQ.Core.Theme 0.1 import "data" 1.0 @@ -21,7 +22,7 @@ StatusAppTwoPanelLayout { text: "Profile" } - ScrollView { + StatusScrollView { anchors.top: profileHeadline.bottom anchors.topMargin: 16 anchors.bottom: parent.bottom diff --git a/sandbox/main.qml b/sandbox/main.qml index 17a22e88..52c10226 100644 --- a/sandbox/main.qml +++ b/sandbox/main.qml @@ -132,215 +132,201 @@ StatusWindow { storeSettings.fillPage = false } - leftPanel: Item { + leftPanel: StatusScrollView { anchors.fill: parent - ScrollView { - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.horizontalCenter: parent.horizontalCenter - contentHeight: navigation.height + 56 - contentWidth: navigation.width - clip: true - Column { - id: navigation - anchors.top: parent.top - anchors.topMargin: 48 - anchors.horizontalCenter: parent.horizontalCenter - spacing: 0 + anchors.topMargin: 48 - StatusListSectionHeadline { text: "StatusQ.Core" } - StatusNavigationListItem { - title: "Icons" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.control(title); - } + Column { + id: navigation + spacing: 0 - StatusListSectionHeadline { text: "StatusQ.Layout" } - StatusNavigationListItem { - title: "Layouts" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.control(title.substring(0, title.length - 1)); - } + StatusListSectionHeadline { text: "StatusQ.Core" } + StatusNavigationListItem { + title: "Icons" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.control(title); + } - StatusListSectionHeadline { text: "StatusQ.Controls" } - StatusNavigationListItem { - title: "Buttons" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.control(title); - } - StatusNavigationListItem { - title: "StatusSwitchTab" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page("StatusTabSwitch"); - } - StatusNavigationListItem { - title: "StatusChatCommandButton" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusNavigationListItem { - title: "Controls" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.control(title); - } - StatusNavigationListItem { - title: "StatusTabBarButton" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusNavigationListItem { - title: "StatusTabBarIconButton" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusNavigationListItem { - title: "StatusInput" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusNavigationListItem { - title: "StatusSelect" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusNavigationListItem { - title: "StatusAccountSelector" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusNavigationListItem { - title: "StatusAssetSelector" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusNavigationListItem { - title: "StatusColorSelector" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusNavigationListItem { - title: "StatusWalletColorButton" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusNavigationListItem { - title: "StatusWalletColorSelect" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusNavigationListItem { - title: "StatusPasswordStrengthIndicator" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusNavigationListItem { - title: "StatusPinInput" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusListSectionHeadline { text: "StatusQ.Components" } - StatusNavigationListItem { - title: "StatusAddress" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusNavigationListItem { - title: "List Items" - selected: viewLoader.source.toString().includes(title.replace(/\s+/g, '')) - onClicked: mainPageView.control(title.replace(/\s+/g, '')); - } - StatusNavigationListItem { - title: "StatusChatInfoToolBar" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusNavigationListItem { - title: "Others" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.control(title); - } - StatusNavigationListItem { - title: "StatusExpandableItem" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page("StatusExpandableSettingsItem"); - } - StatusNavigationListItem { - title: "StatusTagSelector" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusNavigationListItem { - title: "StatusToastMessage" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusNavigationListItem { - title: "StatusWizardStepper" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusNavigationListItem { - title: "StatusListPicker" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusNavigationListItem { - title: "StatusCommunityCard" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusNavigationListItem { - title: "StatusCommunityTags" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusNavigationListItem { - title: "StatusItemSelector" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusListSectionHeadline { text: "StatusQ.Popup" } - StatusNavigationListItem { - title: "StatusPopupMenu" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusNavigationListItem { - title: "StatusModal" - selected: viewLoader.source.toString().includes("Popups") - onClicked: mainPageView.control("Popups"); - } - StatusNavigationListItem { - title: "StatusDialog" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusListSectionHeadline { text: "StatusQ.Platform" } - StatusNavigationListItem { - title: "StatusMacNotification" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusNavigationListItem { - title: "StatusColorSelectorGrid" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title); - } - StatusNavigationListItem { - title: "StatusImageCropPanel" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title, true); - } - StatusNavigationListItem { - title: "StatusColorSpace" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title, true); - } - StatusNavigationListItem { - title: "StatusCard" - selected: viewLoader.source.toString().includes(title) - onClicked: mainPageView.page(title, true); - } + StatusListSectionHeadline { text: "StatusQ.Layout" } + StatusNavigationListItem { + title: "Layouts" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.control(title.substring(0, title.length - 1)); + } + + StatusListSectionHeadline { text: "StatusQ.Controls" } + StatusNavigationListItem { + title: "Buttons" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.control(title); + } + StatusNavigationListItem { + title: "StatusSwitchTab" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page("StatusTabSwitch"); + } + StatusNavigationListItem { + title: "StatusChatCommandButton" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusNavigationListItem { + title: "Controls" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.control(title); + } + StatusNavigationListItem { + title: "StatusTabBarButton" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusNavigationListItem { + title: "StatusTabBarIconButton" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusNavigationListItem { + title: "StatusInput" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusNavigationListItem { + title: "StatusSelect" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusNavigationListItem { + title: "StatusAccountSelector" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusNavigationListItem { + title: "StatusAssetSelector" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusNavigationListItem { + title: "StatusColorSelector" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusNavigationListItem { + title: "StatusWalletColorButton" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusNavigationListItem { + title: "StatusWalletColorSelect" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusNavigationListItem { + title: "StatusPasswordStrengthIndicator" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusNavigationListItem { + title: "StatusPinInput" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusListSectionHeadline { text: "StatusQ.Components" } + StatusNavigationListItem { + title: "StatusAddress" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusNavigationListItem { + title: "List Items" + selected: viewLoader.source.toString().includes(title.replace(/\s+/g, '')) + onClicked: mainPageView.control(title.replace(/\s+/g, '')); + } + StatusNavigationListItem { + title: "StatusChatInfoToolBar" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusNavigationListItem { + title: "Others" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.control(title); + } + StatusNavigationListItem { + title: "StatusExpandableItem" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page("StatusExpandableSettingsItem"); + } + StatusNavigationListItem { + title: "StatusTagSelector" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusNavigationListItem { + title: "StatusToastMessage" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusNavigationListItem { + title: "StatusWizardStepper" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusNavigationListItem { + title: "StatusListPicker" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusNavigationListItem { + title: "StatusCommunityCard" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusNavigationListItem { + title: "StatusCommunityTags" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusListSectionHeadline { text: "StatusQ.Popup" } + StatusNavigationListItem { + title: "StatusPopupMenu" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusNavigationListItem { + title: "StatusModal" + selected: viewLoader.source.toString().includes("Popups") + onClicked: mainPageView.control("Popups"); + } + StatusNavigationListItem { + title: "StatusDialog" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusListSectionHeadline { text: "StatusQ.Platform" } + StatusNavigationListItem { + title: "StatusMacNotification" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusNavigationListItem { + title: "StatusColorSelectorGrid" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title); + } + StatusNavigationListItem { + title: "StatusImageCropPanel" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title, true); + } + StatusNavigationListItem { + title: "StatusColorSpace" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title, true); + } + StatusNavigationListItem { + title: "StatusCard" + selected: viewLoader.source.toString().includes(title) + onClicked: mainPageView.page(title, true); } } } @@ -349,7 +335,7 @@ StatusWindow { id: rightPanel anchors.fill: parent - ScrollView { + StatusScrollView { visible: !storeSettings.fillPage anchors.fill: parent anchors.topMargin: 64 diff --git a/src/StatusQ/Controls/StatusScrollBar.qml b/src/StatusQ/Controls/StatusScrollBar.qml new file mode 100644 index 00000000..409f7b76 --- /dev/null +++ b/src/StatusQ/Controls/StatusScrollBar.qml @@ -0,0 +1,24 @@ +import QtQuick 2.14 +import QtQuick.Controls 2.14 as T + +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 + +T.ScrollBar { + id: root + + // TODO: add this sizes to Theme + implicitWidth: 14 + implicitHeight: 14 + + background: null + + contentItem: Rectangle { + color: root.hovered || root.active ? Theme.palette.primaryColor3 : Theme.palette.baseColor2 + opacity: enabled ? 1.0 : 0.0 + radius: Math.min(width, height) / 2 + + Behavior on opacity { NumberAnimation { duration: 100 } } + } +} + diff --git a/src/StatusQ/Controls/qmldir b/src/StatusQ/Controls/qmldir index 2ef09670..f37f87b3 100644 --- a/src/StatusQ/Controls/qmldir +++ b/src/StatusQ/Controls/qmldir @@ -47,3 +47,4 @@ StatusFloatingButtonsSelector 0.1 StatusFloatingButtonsSelector.qml StatusActivityCenterButton 0.1 StatusActivityCenterButton.qml StatusDropdown 0.1 StatusDropdown.qml StatusIconTextButton 0.1 StatusIconTextButton.qml +StatusScrollBar 0.1 StatusScrollBar.qml diff --git a/src/StatusQ/Core/StatusScrollView.qml b/src/StatusQ/Core/StatusScrollView.qml new file mode 100644 index 00000000..4b504d0d --- /dev/null +++ b/src/StatusQ/Core/StatusScrollView.qml @@ -0,0 +1,48 @@ +import QtQuick 2.14 +import QtQuick.Controls 2.14 + +import StatusQ.Controls 0.1 + +/*! + \qmltype StatusScrollView + \inherits ScrollView + \inqmlmodule StatusQ.Core + \since StatusQ.Core 0.1 + \brief ScrollView wrapper with tuned flickable. + + The \c StatusScrollView can be used just like a plain ScrollView but with tuned scrolling parameters. + + Example of how to use it: + + \qml + StatusScrollView { + id: scrollView + anchors.fill: parent + + ColumnView { + width: scrollView.avaiulableWidth + } + } + \endqml + + For a list of components available see StatusQ. +*/ +ScrollView { + id: root + + clip: true // NOTE: in Qt6 clip true will be default + background: null + + ScrollBar.horizontal.policy: ScrollBar.AsNeeded + ScrollBar.vertical.policy: ScrollBar.AsNeeded + + Flickable { + id: flickable + + contentWidth: contentItem.childrenRect.width + contentHeight: contentItem.childrenRect.height + boundsBehavior: Flickable.StopAtBounds + maximumFlickVelocity: 0 + synchronousDrag: true + } +} diff --git a/src/StatusQ/Core/qmldir b/src/StatusQ/Core/qmldir index e0da87df..86dddf32 100644 --- a/src/StatusQ/Core/qmldir +++ b/src/StatusQ/Core/qmldir @@ -11,3 +11,5 @@ StatusModalHeaderSettings 0.1 StatusModalHeaderSettings.qml StatusTooltipSettings 0.1 StatusTooltipSettings.qml StatusAppNavBarFilterModel 0.1 StatusAppNavBarFilterModel.qml StatusAnimatedStack 0.1 StatusAnimatedStack.qml +StatusScrollView 0.1 StatusScrollView.qml + diff --git a/src/StatusQ/Popups/StatusColorDialog.qml b/src/StatusQ/Popups/StatusColorDialog.qml index ce614363..a5209a41 100644 --- a/src/StatusQ/Popups/StatusColorDialog.qml +++ b/src/StatusQ/Popups/StatusColorDialog.qml @@ -33,7 +33,7 @@ StatusModal { width: 680 implicitHeight: 820 - contentItem: ScrollView { + contentItem: StatusScrollView { id: scroll width: parent.width topPadding: 30