Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

[Solved] Making a swipeable panel with buttons on top


  • Qt Champions 2016

    Hi,

    I would like to make a navigation drawer / bottom sheet for Android in Material design. One of the requirement is it should be able to dismiss by swipe. However, if it has button on top, the mouse event will not be able to propagate to parent.

    Any suggested method to implement this kind of widget?

    Screenshot



  • You can propagate the events to parent using the property propagateComposedEvents, but I dont think you really need it. You can swipe the drawer using, for example, the drag property to move it away to the left and then using an animation that would be fired on mouse released event, to complete the hidding process.


  • Qt Champions 2016

    Thanks for your reply. Do you mean to set drag property on buttons over the panel? Seem to be quite troublesome becoz it may have multiple buttons on it and you need to set per button.



  • No I dont mean that, I mean set the drag property on the panel itself.
    If I understood you correctly you have a panel with buttons that is on a z order above the main window, the panel is hidden to the user because it's moved to the left of the main window. Clicking on some button will make it move it to the right making it visible.
    Now to dismiss it, you swipe it to left, and it moves accordingly, because you set a drag property, the pitfall is that when the user stops the swipe, the panel stops moving. Thats when you fire an animation, using the release property of the "swipe", to make the panel fully hidden. I have done this before and it works like a charm. Note that you have to prevent the swipe from moving the panel further to the right and make sure the "hidding" animation is only fired if the swipe is done to the left.


  • Qt Champions 2016

    oh, I just find that MouseArea has "drag.filterChildren" property. That is prefect. Your solution works! Thank you!



  • @benlau
    If you don't mind can you please post the working piece of code? Thanks



  • Take a look to this sample code
    http://www.4shared.com/zip/FcvUAuCVba/SideMenu.html



  • @BlackDal
    Thanks a lot Man!!! But it is littlebit different from the requirement
    alt text.
    In your example 1)It is not hiding completely. 2) It is based on the button pressed events. How can i make them based on swipe events? thanks a lot. @benlau Please post the piece of code if you don'T mind Thanks.


  • Qt Champions 2016



  • @benlau
    Thanks a lot. What i didn't understand is
    what is

    • Activity{
      I can see a qml file here. Can you please describe me what it does? I mean its purpose.
      *BottomSheet {
      I didn't find any qml file. so no idea what it does. thanks


  • @vishnu That's an uncompleted project and has so much dirty codes (Excuse me)
    This sample has a right to left swipe menu, You can convert to left-to-right. and extract required code and classes from sample.

    http://www.4shared.com/archive/_gbu_ULyce/Shoptar.html



  • @BlackDal
    Thanks a lot for the quick reply.
    It says error at ToojQmlHelper::registerQmlTypes(&engine); and ended with 422 issues.
    like this
    Any idea how to solve this? I tried with Qt5.5, 5.4, 5.2. Everythings resulted the same.





  • @BlackDal
    Sorry to say this but same errors at
    ToojQmlHelper::registerQmlTypes(&engine);
    ToojQmlHelper::initFonts(&engine);
    should i add something to pro file or some settings ?



  • You are right. There was a problem in the MSVC compiling that was solved.
    I'm so sorry for this fail.
    https://drive.google.com/open?id=0B5E1thzUK4mJTmt6QmJRTlk1TkE



  • @BlackDal
    perfect. Thanks a lot but small error i found.

    qrc:/Page1.qml:14:19: Unable to assign [undefined] to QString
    qrc:/main.qml:46: TypeError: Property 't' of object Units_QMLTYPE_0(0x2a94b238) is not a function
    QSGThreadedRenderLoop: expose event received for window MainWindow_QMLTYPE_86(0x29f0ab28) with invalid geometry: QRect(1920,332 640x360) on QScreen(0x265deac8)
    qrc:///tooj/qml/Tooj/App/MainWindow.qml:122:16: Unable to assign [undefined] to QString
    

    Also, for some reason its work perfect on windows but on android the swipe function is little bit draggy and needs 2 or 3 time to swipe. just to inform you. Thanks a lot.



  • Thanks for bug reporting.
    As I said this is a little and incomplete source. As you can see this sample has menu button, fontawesome and some small components. This is part of a library for mobile-first QtQuick applications and games. I will release this library in next months. I guess drag bug relate to dpi calculation (Units components has some unfinished tasks).

    You might be interested to this project:
    http://papyros.io/


  • Qt Champions 2016

    @vishnu said:

    @benlau
    Thanks a lot. What i didn't understand is
    what is

    • Activity{
      I can see a qml file here. Can you please describe me what it does? I mean its purpose.
      *BottomSheet {
      I didn't find any qml file. so no idea what it does. thanks

    Please switch to "DEV" branch. BottomSheet is not available at master branch yet.

    Activity is a page of UI. You may just ignore it.

    There also has a daily build for Android, you may try if you have an Android device.
    Downloads | quickandroid



  • Here is another very simple example with a nice animation that works how of the box:

    import QtQuick 2.4
    
    Rectangle {
        id: root
        width: 400
        height: 380
        color: "yellow"
    
        Rectangle {
            id: panel
            width: parent.width * 0.8
            height: parent.height * 0.8
            radius: 20
            color: "orange"
            MouseArea {
                id: mouseArea
                anchors.fill: parent
                drag.target: panel
                drag.minimumY: 0
                drag.maximumY: 0
                drag.minimumX: -panel.width
                drag.maximumX: 0
                onReleased: {
                    //if the panel is swiped more than 30% it will hide
                    //else it will go back to the original position
                    //this makes a pretty nice effect :)
                    if (panel.x < -panel.width * 0.3) {
                        //we need to make sure that a state change happens to
                        //fire the transition animation
                        root.state = "show"
                        root.state = "hide"
                    }
                    else {
                        root.state = "hide"
                        root.state = "show"
                    }
                }
            }
            onXChanged: {
                console.log(x)
            }
        }
    
        Rectangle {
            id: button
            width: 45
            height: width
            radius: 5
            color: "lightblue"
            anchors.bottom: parent.bottom
            anchors.left: parent.left
            MouseArea {
                anchors.fill: parent
                onClicked: {
                    root.state = root.state === "show" ? "hide" : "show"
                }
            }
        }
    
        state: "show"
        states: [
            State {
                name: "hide"
                PropertyChanges { target: panel; x: -panel.width }
            },
            State {
                name: "show"
                PropertyChanges { target: panel; x: 0 }
            }
        ]
    
        transitions: Transition {
            NumberAnimation {
                target: panel
                property: "x"
                duration: 1000
                easing.type: Easing.OutCubic
            }
        }
    }

Log in to reply