diff options
author | J-P Nurmi <jpnurmi@theqtcompany.com> | 2014-11-14 20:24:09 +0100 |
---|---|---|
committer | Jani Heikkinen <jani.heikkinen@theqtcompany.com> | 2014-11-20 16:23:06 +0100 |
commit | 5cb56a1adae19e608787cb39b6d90e0a09258871 (patch) | |
tree | 526abda0748b4482d2a5d76ae1c17582572a3a81 /src/controls | |
parent | 331c10d457b4dd7a9e4aa7d9c8724e0790cfebe0 (diff) | |
download | qtquickcontrols-5cb56a1adae19e608787cb39b6d90e0a09258871.tar.gz |
Android 5.0: add missing state transitionsv5.4.0-rc1
Android 5.0 introduced control state change transitions. Without this
change, CheckBoxes and RadioButtons don't transition between checked
and unchecked states as appropriate.
Task-number: QTBUG-42520
Change-Id: If2aa70898e72b78f105732cc4ee5c9674cc6082c
Reviewed-by: BogDan Vatra <bogdan@kde.org>
Reviewed-by: Caroline Chao <caroline.chao@theqtcompany.com>
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
Diffstat (limited to 'src/controls')
-rw-r--r-- | src/controls/Styles/Android/drawables/AnimationDrawable.qml | 5 | ||||
-rw-r--r-- | src/controls/Styles/Android/drawables/StateDrawable.qml | 76 |
2 files changed, 76 insertions, 5 deletions
diff --git a/src/controls/Styles/Android/drawables/AnimationDrawable.qml b/src/controls/Styles/Android/drawables/AnimationDrawable.qml index a522bfa7..12d576ff 100644 --- a/src/controls/Styles/Android/drawables/AnimationDrawable.qml +++ b/src/controls/Styles/Android/drawables/AnimationDrawable.qml @@ -49,14 +49,17 @@ Drawable { property int currentFrame: 0 readonly property int frameCount: styleDef.frames ? styleDef.frames.length : 0 readonly property var frameDef: styleDef.frames ? styleDef.frames[currentFrame] : undefined + readonly property alias running: timer.running + property bool oneshot: styleDef.oneshot Timer { + id: timer repeat: true running: root.frameCount && root.visible && Qt.application.active interval: root.frameDef ? root.frameDef.duration : 0 onTriggered: { var frame = root.currentFrame + 1 - repeat = !root.styleDef.oneshot || frame < root.frameCount - 1 + repeat = !root.oneshot || frame < root.frameCount - 1 root.currentFrame = frame % root.frameCount } } diff --git a/src/controls/Styles/Android/drawables/StateDrawable.qml b/src/controls/Styles/Android/drawables/StateDrawable.qml index d446542d..862ab9ae 100644 --- a/src/controls/Styles/Android/drawables/StateDrawable.qml +++ b/src/controls/Styles/Android/drawables/StateDrawable.qml @@ -46,10 +46,12 @@ Drawable { implicitWidth: Math.max(loader.implicitWidth, styleDef.width || 0) implicitHeight: Math.max(loader.implicitHeight, styleDef.height || 0) + property int prevMatch: 0 + DrawableLoader { id: loader anchors.fill: parent - styleDef: bestStateMatch() + visible: !animation.active focused: root.focused pressed: root.pressed checked: root.checked @@ -65,17 +67,70 @@ Drawable { clippables: root.clippables } - function bestStateMatch () { + Loader { + id: animation + property var animDef + active: false + anchors.fill: parent + sourceComponent: AnimationDrawable { + anchors.fill: parent + styleDef: animDef + focused: root.focused + pressed: root.pressed + checked: root.checked + selected: root.selected + accelerated: root.accelerated + window_focused: root.window_focused + index: root.index + level: root.level + levelId: root.levelId + orientations: root.orientations + duration: root.duration + excludes: root.excludes + clippables: root.clippables + + oneshot: true + onRunningChanged: if (!running) animation.active = false + } + } + + onStyleDefChanged: resolveState() + Component.onCompleted: resolveState() + + // In order to be able to find appropriate transition paths between + // various states, the following states must be allowed to change in + // batches. For example, button-like controls could have a transition + // path from pressed+checked to unpressed+unchecked. We must let both + // properties change before we try to find the transition path. + onEnabledChanged: resolver.start() + onFocusedChanged: resolver.start() + onPressedChanged: resolver.start() + onCheckedChanged: resolver.start() + onSelectedChanged: resolver.start() + onAcceleratedChanged: resolver.start() + onWindow_focusedChanged: resolver.start() + + Timer { + id: resolver + interval: 15 + onTriggered: resolveState() + } + + function resolveState () { if (styleDef && styleDef.stateslist) { var bestMatch = 0 var highestScore = -1 var stateslist = styleDef.stateslist + var transitions = [] for (var i = 0; i < stateslist.length; ++i) { var score = 0 var state = stateslist[i] + if (state.transition) + transitions.push(i) + for (var s in state.states) { if (s === "pressed") score += (pressed === state.states[s]) ? 1 : -10 @@ -98,8 +153,21 @@ Drawable { highestScore = score } } - return stateslist[bestMatch].drawable + + if (prevMatch != bestMatch) { + for (var t = 0; t < transitions.length; ++t) { + var transition = stateslist[transitions[t]].transition + if ((transition.from == prevMatch && transition.to == bestMatch) || + (transition.reverse && transition.from == bestMatch && transition.to == prevMatch)) { + animation.animDef = stateslist[transitions[t]].drawable + animation.active = true + break + } + } + prevMatch = bestMatch + } + + loader.styleDef = stateslist[bestMatch].drawable } - return undefined } } |