2017-03-29 4 views
1

Ich möchte ein animiertes Akkordeon-ähnliches Element erstellen, das auf Klick erweitert. So sollte es funktionieren.So erstellen Sie eine animierte, variable Größe Akkordeon-Komponente in QtQuick/QML

Accordion animation

Wenn der Benutzer eine der roten Rechtecke klickt, die das grüne Rechteck sollte der eigentliche Inhalt ist, erweitern. Ich möchte, dass diese Erweiterung animiert wird. Die Höhe des Inhalts der grünen Rechtecke könnte für jeden roten Header unterschiedlich sein.

Ich konnte das Click-to-Expand-Verhalten implementieren, aber es gibt keine Animation. Hier ist der Code, den ich derzeit habe.

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 
    } 
} 

Und das ist, wie es aus dem übergeordneten Elemente verwendet wird:

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 
    } 
} 

Dies erzeugt das folgende Ergebnis (wenn alle Rechtecken erweitert werden):

Expanded

Idealerweise möchte ich, dass die grünen Rechtecke aus den roten Rechtecken rollen (wie Papier aus einem Drucker). Aber ich bin fest, wie ich das machen soll. Ich habe versucht, mehrere Ansätze mit der height -Eigenschaft, und ich habe das grüne Rechteck zu verschwinden, aber der Leerraum bleibt unter dem roten Rechteck.

Jede Hilfe wäre willkommen. Gibt es einen Ansatz, den ich vermisse?

Antwort

1

Hier ist ein schnelles und einfaches Beispiel:

// 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 
    } 
    } 
} 

Sie sind unnötig zu verkomplizieren es mit den Ankern und das Layout. Es scheint nicht, dass das Problem nach irgendwelchen von denen verlangt.

Update: Ich habe die Implementierung etwas verfeinert, im Vergleich zu der ursprünglichen würde der Inhalt tatsächlich aus dem Header als Papier aus dem Drucker herausgleiten, anstatt einfach enthüllt zu werden, und auch die Quelle einer falschen positiven Bindewarnung entfernt.

enter image description here

+0

Es scheint, ich 'ColumnLayout' mir eine Menge Ärger verursacht. Es ist mein erstes QML-Projekt und ich komme von einem Android-Hintergrund, so dass einige Dinge verwirrend sein können. –

+0

Könnte das Layout sein, könnten die Anker sein. Ich habe deinen Code nicht getestet. Mit QML ist es wichtig, es einfach zu halten, weil es oft nicht die Erwartungen oder sogar den gesunden Menschenverstand erfüllt, wenn man etwas komplizierteres wirft. – dtech

+0

Wenn Sie die Zeile "anchors.left: parent.left; anchors.right: parent.right" meinen, wird das Element horizontal gestreckt, damit es dem übergeordneten Element entspricht. Das ist also kein Problem. Über QML mag ich es nicht wirklich. Ich würde lieber HTML, CSS und ein wenig JS zum Entwerfen der GUI verwenden, aber ich muss QML für dieses Projekt verwenden, damit ich feststecke. –

Verwandte Themen