问题
I want to create an animated accordion-like element that expands on click. Here's how it should work.
When the user clicks one of the red rectangles, the green rectangle which is the actual content, should expand. I want this expansion to be animated. The height of the contents of the green rectangles could be different for each red header.
I have been able to implement the click-to-expand behavior, but there's no animation. Here is the code I currently have.
AccordionElement.qml
import QtQuick 2.5
import QtQuick.Layouts 1.1
ColumnLayout {
id: rootElement
property string title: ""
property bool isOpen: false
default property alias accordionContent: contentPlaceholder.data
anchors.left: parent.left; anchors.right: parent.right
// Header element
Rectangle {
id: accordionHeader
color: "red"
anchors.left: parent.left; anchors.right: parent.right
height: 50
MouseArea {
anchors.fill: parent
Text {
text: rootElement.title
anchors.centerIn: parent
}
cursorShape: Qt.PointingHandCursor
onClicked: {
rootElement.isOpen = !rootElement.isOpen
}
}
}
// This will get filled with the content
ColumnLayout {
id: contentPlaceholder
visible: rootElement.isOpen
anchors.left: parent.left; anchors.right: parent.right
}
}
And this is how it is used from the parent element:
Accordion.qml
ColumnLayout {
Layout.margins: 5
visible: true
AccordionElement {
title: "Title1"
accordionContent: Rectangle {
anchors.left: parent.left; anchors.right: parent.right
height: 20
color: "green"
}
}
AccordionElement {
title: "Title2"
accordionContent: Rectangle {
anchors.left: parent.left; anchors.right: parent.right
height: 50
color: "green"
}
}
AccordionElement {
title: "Title3"
accordionContent: Rectangle {
anchors.left: parent.left; anchors.right: parent.right
height: 30
color: "green"
}
}
// Vertical spacer to keep the rectangles in upper part of column
Item {
Layout.fillHeight: true
}
}
This produces the following result (when all rectangles are expanded):
Ideally I would like the green rectangles to roll out of the red rectangles (like paper out of a printer). But I am stuck on how to do this. I have tried several approaches using the height
property, and I got the green rectangle to disappear but the white space remains under the red rectangle.
Any help would be appreciated. Is there an approach I'm missing?
回答1:
Here is a quick and simple example:
// AccItem.qml
Column {
default property alias item: ld.sourceComponent
Rectangle {
width: 200
height: 50
color: "red"
MouseArea {
anchors.fill: parent
onClicked: info.show = !info.show
}
}
Rectangle {
id: info
width: 200
height: show ? ld.height : 0
property bool show : false
color: "green"
clip: true
Loader {
id: ld
y: info.height - height
anchors.horizontalCenter: info.horizontalCenter
}
Behavior on height {
NumberAnimation { duration: 200; easing.type: Easing.InOutQuad }
}
}
}
// Acc.qml
Column {
spacing: 5
AccItem {
Rectangle {
width: 50
height: 50
radius: 50
color: "blue"
anchors.centerIn: parent
}
}
AccItem {
Rectangle {
width: 100
height: 100
radius: 50
color: "yellow"
anchors.centerIn: parent
}
}
AccItem {
Rectangle {
width: 75
height: 75
radius: 50
color: "cyan"
anchors.centerIn: parent
}
}
}
You are needlessly over-complicating it with the anchors and the layouts. It doesn't seem the problem calls for any of those.
Update: I slightly refined the implementation, compared to the initial one the content would actually slide out of the header as paper out of printer rather than simply being unveiled, and also removed the source of a false positive binding loop warning.
来源:https://stackoverflow.com/questions/43093280/how-to-create-an-animated-variable-size-accordion-component-in-qtquick-qml