diff options
author | Mitch Curtis <[email protected]> | 2022-11-17 15:35:18 +0800 |
---|---|---|
committer | Mitch Curtis <[email protected]> | 2022-12-12 13:38:14 +0800 |
commit | 81b12a5f73bfd61c9e7ca912a3e3f7ab57ff45cd (patch) | |
tree | e035f40e04b778ce9dc99dc63c504d096d11b271 | |
parent | 7e38a9e6efc72cc42af16d9cef6f94703b06474b (diff) |
Update Material Switch to Material 3
Fixes: QTBUG-108555
Change-Id: I6c17812c9cf0dab71ac212ab7cb28cad646f9dfc
Reviewed-by: Mitch Curtis <[email protected]>
-rw-r--r-- | src/quickcontrols/material/Switch.qml | 8 | ||||
-rw-r--r-- | src/quickcontrols/material/impl/SwitchIndicator.qml | 92 | ||||
-rw-r--r-- | src/quickcontrols/material/qquickmaterialstyle.cpp | 96 | ||||
-rw-r--r-- | src/quickcontrols/material/qquickmaterialstyle_p.h | 20 | ||||
-rw-r--r-- | tests/manual/quickcontrols/material/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/manual/quickcontrols/material/material.qml | 2 | ||||
-rw-r--r-- | tests/manual/quickcontrols/material/pages/SwitchPage.qml | 75 |
7 files changed, 256 insertions, 38 deletions
diff --git a/src/quickcontrols/material/Switch.qml b/src/quickcontrols/material/Switch.qml index db3fedfdc3..d27621a74f 100644 --- a/src/quickcontrols/material/Switch.qml +++ b/src/quickcontrols/material/Switch.qml @@ -18,6 +18,14 @@ T.Switch { padding: 8 spacing: 8 + icon.width: 16 + icon.height: 16 + icon.color: checked + ? (Material.theme === Material.Light + ? enabled ? Qt.darker(Material.switchCheckedTrackColor, 1.8) : Material.switchDisabledCheckedIconColor + : enabled ? Material.primaryTextColor : Material.switchDisabledCheckedIconColor) + : enabled ? Material.switchUncheckedTrackColor : Material.switchDisabledUncheckedIconColor + indicator: SwitchIndicator { x: control.text ? (control.mirrored ? control.width - width - control.rightPadding : control.leftPadding) : control.leftPadding + (control.availableWidth - width) / 2 y: control.topPadding + (control.availableHeight - height) / 2 diff --git a/src/quickcontrols/material/impl/SwitchIndicator.qml b/src/quickcontrols/material/impl/SwitchIndicator.qml index e439bc31b7..2d48302e01 100644 --- a/src/quickcontrols/material/impl/SwitchIndicator.qml +++ b/src/quickcontrols/material/impl/SwitchIndicator.qml @@ -3,37 +3,71 @@ import QtQuick import QtQuick.Templates as T +import QtQuick.Controls.impl import QtQuick.Controls.Material import QtQuick.Controls.Material.impl -Item { +Rectangle { id: indicator - implicitWidth: 38 - implicitHeight: 32 + width: 52 + height: 32 + radius: height / 2 + y: parent.height / 2 - height / 2 + color: control.enabled + ? (control.checked + ? control.Material.switchCheckedTrackColor : control.Material.switchUncheckedTrackColor) + : (control.checked + ? control.Material.switchDisabledCheckedTrackColor + : control.Material.switchDisabledUncheckedTrackColor) + border.width: 2 + border.color: control.enabled + ? (control.checked ? control.Material.switchCheckedTrackColor : control.Material.switchUncheckedHandleColor) + : (control.checked ? control.Material.switchDisabledCheckedTrackColor : control.Material.switchDisabledUncheckedTrackBorderColor) property T.AbstractButton control property alias handle: handle - Material.elevation: 1 - - Rectangle { - width: parent.width - height: 14 - radius: height / 2 - y: parent.height / 2 - height / 2 - color: indicator.control.enabled ? (indicator.control.checked ? indicator.control.Material.switchCheckedTrackColor : indicator.control.Material.switchUncheckedTrackColor) - : indicator.control.Material.switchDisabledTrackColor + Behavior on color { + ColorAnimation { + duration: 200 + } + } + Behavior on border.color { + ColorAnimation { + duration: 200 + } } Rectangle { id: handle - x: Math.max(0, Math.min(parent.width - width, indicator.control.visualPosition * parent.width - (width / 2))) + x: Math.max(offset, Math.min(parent.width - offset - width, + indicator.control.visualPosition * parent.width - (width / 2))) y: (parent.height - height) / 2 - width: 20 - height: 20 + // We use scale to allow us to enlarge the circle from the center, + // as using width/height will cause it to jump due to the position x/y bindings. + // However, a large enough scale on certain displays will show the triangles + // that make up the circle, so instead we make sure that the circle is always + // its largest size so that more triangles are used, and downscale instead. + width: normalSize * largestScale + height: normalSize * largestScale radius: width / 2 - color: indicator.control.enabled ? (indicator.control.checked ? indicator.control.Material.switchCheckedHandleColor : indicator.control.Material.switchUncheckedHandleColor) - : indicator.control.Material.switchDisabledHandleColor + color: indicator.control.enabled + ? (indicator.control.checked + ? indicator.control.Material.switchCheckedHandleColor + : indicator.control.hovered + ? indicator.control.Material.switchUncheckedHoveredHandleColor : indicator.control.Material.switchUncheckedHandleColor) + : (indicator.control.checked + ? indicator.control.Material.switchDisabledCheckedHandleColor + : indicator.control.Material.switchDisabledUncheckedHandleColor) + scale: indicator.control.down ? 1 : (indicator.control.checked ? checkedSize / largestSize : normalSize / largestSize) + + readonly property int offset: 2 + readonly property real normalSize: !hasIcon ? 16 : checkedSize + readonly property real checkedSize: 24 + readonly property real largestSize: 28 + readonly property real largestScale: largestSize / normalSize + readonly property bool hasIcon: indicator.control.icon.name.length > 0 + || indicator.control.icon.source.toString().length > 0 Behavior on x { enabled: !indicator.control.pressed @@ -41,9 +75,27 @@ Item { duration: 300 } } - layer.enabled: indicator.Material.elevation > 0 - layer.effect: ElevationEffect { - elevation: indicator.Material.elevation + + Behavior on scale { + NumberAnimation { + duration: 100 + } + } + + Behavior on color { + ColorAnimation { + duration: 200 + } + } + + IconImage { + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + name: indicator.control.icon.name + source: indicator.control.icon.source + sourceSize: Qt.size(indicator.control.icon.width, indicator.control.icon.height) + color: indicator.control.icon.color + visible: handle.hasIcon } } } diff --git a/src/quickcontrols/material/qquickmaterialstyle.cpp b/src/quickcontrols/material/qquickmaterialstyle.cpp index 35ccc59e1f..40304d4d7c 100644 --- a/src/quickcontrols/material/qquickmaterialstyle.cpp +++ b/src/quickcontrols/material/qquickmaterialstyle.cpp @@ -380,16 +380,48 @@ static const QRgb raisedButtonDisabledColorLight = dividerColorLight; static const QRgb raisedButtonDisabledColorDark = dividerColorDark; static const QRgb frameColorLight = hintTextColorLight; static const QRgb frameColorDark = hintTextColorDark; -static const QRgb switchUncheckedTrackColorLight = 0x42000000; -static const QRgb switchUncheckedTrackColorDark = 0x4CFFFFFF; -static const QRgb switchDisabledTrackColorLight = 0x1E000000; -static const QRgb switchDisabledTrackColorDark = 0x19FFFFFF; static const QRgb rippleColorLight = 0x10000000; static const QRgb rippleColorDark = 0x20FFFFFF; static const QRgb spinBoxDisabledIconColorLight = 0xFFCCCCCC; static const QRgb spinBoxDisabledIconColorDark = 0xFF666666; static const QRgb sliderDisabledColorLight = 0xFF9E9E9E; static const QRgb sliderDisabledColorDark = 0xFF616161; +/* + https://m3.material.io/components/switch/specs#57a434cd-5fcc-4d79-9bff-12b2a9768789 + + light / dark + surface: #FFFBFE/#1C1B1F + on-surface: #1C1B1F/#E6E1E5 + surface-variant: #E7E0EC/#49454F + + 12% = 1E + 38% = 61 + + handle + + unchecked checked + disabled #1C1B1F/#E6E1E5 @ 38% (#611C1B1F/#61E6E1E5) #FFFBFE/#1C1B1F @ 100% + + track + + unchecked checked + disabled #E7E0EC/#49454F @ 12% (#1EE7E0EC/#1E49454F) #1C1B1F/#E6E1E5 @ 12% (#1E1C1B1F/#1EE6E1E5) + + track outline + + unchecked checked + disabled #1C1B1F/#E6E1E5 @ 12% (#1E1C1B1F/#1EE6E1E5) same as track +*/ +static const QRgb switchUncheckedTrackColorLight = 0xFFE7E0EC; +static const QRgb switchUncheckedTrackColorDark = 0x49454F; +static const QRgb switchDisabledUncheckedTrackColorLight = 0x1EE7E0EC; +static const QRgb switchDisabledUncheckedTrackColorDark = 0x1E49454F; +static const QRgb switchDisabledUncheckedTrackBorderColorLight = 0x1E1C1B1F; +static const QRgb switchDisabledUncheckedTrackBorderColorDark = 0x1EE6E1E5; +static const QRgb switchDisabledCheckedTrackColorLight = 0x1E1C1B1F; +static const QRgb switchDisabledCheckedTrackColorDark = 0x1EE6E1E5; +static const QRgb switchDisabledUncheckedIconColorLight = 0x611C1B1F; +static const QRgb switchDisabledUncheckedIconColorDark = 0x61E6E1E5; static QQuickMaterialStyle::Theme effectiveTheme(QQuickMaterialStyle::Theme theme) { @@ -952,29 +984,67 @@ QColor QQuickMaterialStyle::switchUncheckedTrackColor() const QColor QQuickMaterialStyle::switchCheckedTrackColor() const { - QColor trackColor(accentColor()); - trackColor.setAlphaF(0.5); - return trackColor; + return accentColor(m_theme == Light ? themeShade() : Shade100); +} + +QColor QQuickMaterialStyle::switchDisabledUncheckedTrackColor() const +{ + return QColor::fromRgba(m_theme == Light + ? switchDisabledUncheckedTrackColorLight : switchDisabledUncheckedTrackColorDark); +} + +QColor QQuickMaterialStyle::switchDisabledCheckedTrackColor() const +{ + return QColor::fromRgba(m_theme == Light + ? switchDisabledCheckedTrackColorLight : switchDisabledCheckedTrackColorDark); +} + +QColor QQuickMaterialStyle::switchDisabledUncheckedTrackBorderColor() const +{ + return QColor::fromRgba(m_theme == Light + ? switchDisabledUncheckedTrackBorderColorLight : switchDisabledUncheckedTrackBorderColorDark); } QColor QQuickMaterialStyle::switchUncheckedHandleColor() const { - return m_theme == Light ? color(Grey, Shade50) : color(Grey, Shade400); + return m_theme == Light ? color(Grey, Shade600) : color(Grey, Shade400); +} + +QColor QQuickMaterialStyle::switchUncheckedHoveredHandleColor() const +{ + const QColor color = switchUncheckedHandleColor(); + return m_theme == Light ? color.darker(140) : color.lighter(120); } QColor QQuickMaterialStyle::switchCheckedHandleColor() const { - return m_theme == Light ? accentColor() : shade(accentColor(), Shade200); + return m_theme == Light ? QColor::fromRgb(0xFFFFFF) : accentColor(Shade800); +} + +QColor QQuickMaterialStyle::switchDisabledUncheckedHandleColor() const +{ + if (m_theme == Light) + return QColor::fromRgba(0x611C1B1F); + + QColor darkHandleColor = color(Grey, Shade800); + darkHandleColor.setAlphaF(0.38f); + return darkHandleColor; +} + +QColor QQuickMaterialStyle::switchDisabledCheckedHandleColor() const +{ + return QColor::fromRgb(m_theme == Light ? 0xFFFBFE : 0x1C1B1F); } -QColor QQuickMaterialStyle::switchDisabledTrackColor() const +QColor QQuickMaterialStyle::switchDisabledCheckedIconColor() const { - return QColor::fromRgba(m_theme == Light ? switchDisabledTrackColorLight : switchDisabledTrackColorDark); + return QColor::fromRgba(m_theme == Light ? 0x611C1B1F : 0x61E6E1E5); } -QColor QQuickMaterialStyle::switchDisabledHandleColor() const +QColor QQuickMaterialStyle::switchDisabledUncheckedIconColor() const { - return m_theme == Light ? color(Grey, Shade400) : color(Grey, Shade800); + return QColor::fromRgba(m_theme == Light + ? switchDisabledUncheckedIconColorLight : switchDisabledUncheckedIconColorDark); } QColor QQuickMaterialStyle::scrollBarColor() const diff --git a/src/quickcontrols/material/qquickmaterialstyle_p.h b/src/quickcontrols/material/qquickmaterialstyle_p.h index 56e541ce07..e133e35b59 100644 --- a/src/quickcontrols/material/qquickmaterialstyle_p.h +++ b/src/quickcontrols/material/qquickmaterialstyle_p.h @@ -51,9 +51,15 @@ class QQuickMaterialStyle : public QQuickAttachedPropertyPropagator Q_PROPERTY(QColor switchUncheckedTrackColor READ switchUncheckedTrackColor NOTIFY themeChanged FINAL) Q_PROPERTY(QColor switchCheckedTrackColor READ switchCheckedTrackColor NOTIFY themeOrAccentChanged FINAL) Q_PROPERTY(QColor switchUncheckedHandleColor READ switchUncheckedHandleColor NOTIFY themeChanged FINAL) + Q_PROPERTY(QColor switchUncheckedHoveredHandleColor READ switchUncheckedHoveredHandleColor NOTIFY themeChanged FINAL) + Q_PROPERTY(QColor switchDisabledUncheckedTrackColor READ switchDisabledUncheckedTrackColor NOTIFY themeChanged FINAL) + Q_PROPERTY(QColor switchDisabledCheckedTrackColor READ switchDisabledCheckedTrackColor NOTIFY themeChanged FINAL) + Q_PROPERTY(QColor switchDisabledUncheckedTrackBorderColor READ switchDisabledUncheckedTrackBorderColor NOTIFY themeChanged FINAL) Q_PROPERTY(QColor switchCheckedHandleColor READ switchCheckedHandleColor NOTIFY themeOrAccentChanged FINAL) - Q_PROPERTY(QColor switchDisabledTrackColor READ switchDisabledTrackColor NOTIFY themeChanged FINAL) - Q_PROPERTY(QColor switchDisabledHandleColor READ switchDisabledHandleColor NOTIFY themeChanged FINAL) + Q_PROPERTY(QColor switchDisabledUncheckedHandleColor READ switchDisabledUncheckedHandleColor NOTIFY themeChanged FINAL) + Q_PROPERTY(QColor switchDisabledCheckedHandleColor READ switchDisabledCheckedHandleColor NOTIFY themeChanged FINAL) + Q_PROPERTY(QColor switchDisabledCheckedIconColor READ switchDisabledCheckedIconColor NOTIFY themeChanged FINAL) + Q_PROPERTY(QColor switchDisabledUncheckedIconColor READ switchDisabledUncheckedIconColor NOTIFY themeChanged FINAL) Q_PROPERTY(QColor scrollBarColor READ scrollBarColor NOTIFY themeChanged FINAL) Q_PROPERTY(QColor scrollBarHoveredColor READ scrollBarHoveredColor NOTIFY themeChanged FINAL) Q_PROPERTY(QColor scrollBarPressedColor READ scrollBarPressedColor NOTIFY themeChanged FINAL) @@ -215,10 +221,16 @@ public: QColor highlightedRippleColor() const; QColor switchUncheckedTrackColor() const; QColor switchCheckedTrackColor() const; + QColor switchDisabledUncheckedTrackColor() const; + QColor switchDisabledCheckedTrackColor() const; + QColor switchDisabledUncheckedTrackBorderColor() const; QColor switchUncheckedHandleColor() const; + QColor switchUncheckedHoveredHandleColor() const; QColor switchCheckedHandleColor() const; - QColor switchDisabledTrackColor() const; - QColor switchDisabledHandleColor() const; + QColor switchDisabledUncheckedHandleColor() const; + QColor switchDisabledCheckedHandleColor() const; + QColor switchDisabledCheckedIconColor() const; + QColor switchDisabledUncheckedIconColor() const; QColor scrollBarColor() const; QColor scrollBarHoveredColor() const; QColor scrollBarPressedColor() const; diff --git a/tests/manual/quickcontrols/material/CMakeLists.txt b/tests/manual/quickcontrols/material/CMakeLists.txt index 1cd3a98d0f..004d3e8708 100644 --- a/tests/manual/quickcontrols/material/CMakeLists.txt +++ b/tests/manual/quickcontrols/material/CMakeLists.txt @@ -23,6 +23,7 @@ set(qmake_immediate_resource_files "pages/ButtonPage.qml" "pages/DelayButtonPage.qml" "pages/RoundButtonPage.qml" + "pages/SwitchPage.qml" "qmldir" ) diff --git a/tests/manual/quickcontrols/material/material.qml b/tests/manual/quickcontrols/material/material.qml index 720ff0a5ec..78efaf72e3 100644 --- a/tests/manual/quickcontrols/material/material.qml +++ b/tests/manual/quickcontrols/material/material.qml @@ -97,7 +97,7 @@ ApplicationWindow { focus: true currentIndex: settings.currentControlIndex anchors.fill: parent - model: ["Button", "DelayButton", "RoundButton"] + model: ["Button", "DelayButton", "RoundButton", "Switch"] delegate: ItemDelegate { width: listView.width text: modelData diff --git a/tests/manual/quickcontrols/material/pages/SwitchPage.qml b/tests/manual/quickcontrols/material/pages/SwitchPage.qml new file mode 100644 index 0000000000..5335fa6290 --- /dev/null +++ b/tests/manual/quickcontrols/material/pages/SwitchPage.qml @@ -0,0 +1,75 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +import QtQuick +import QtQuick.Controls.Material +import QtQuick.Layouts + +import ".." + +Page { + topPadding: Constants.pageTopPadding + + ColumnLayout { + width: parent.width + + RowLayout { + spacing: 40 + + Switch { + text: "Switch" + } + + Switch { + text: "Checked Switch" + checked: true + } + + Switch { + text: "Disabled Switch" + enabled: false + } + + Switch { + text: "Checked disabled Switch" + checked: true + enabled: false + } + + Item { + Layout.fillWidth: true + } + } + + RowLayout { + spacing: 40 + + Switch { + text: "Switch" + icon.source: Constants.iconSource + } + + Switch { + text: "Checked Switch" + icon.source: Constants.iconSource + checked: true + } + + Switch { + text: "Disabled Switch" + icon.source: Constants.iconSource + enabled: false + } + + Switch { + text: "Checked disabled Switch" + icon.source: Constants.iconSource + checked: true + enabled: false + } + + Item { + Layout.fillWidth: true + } + } + } +} |