Make Toast in Android from QML

I haven't started learning Android while developing QML, I'm just curious that Toast seems to be Android specific widgets, and Qt for Android doesn't seem to have a corresponding widget ready, so how do you implement Toast in Android from QML?

+3


source to share


4 answers


Maybe something like this ..

This is for InfoBanner.qml

import QtQuick 2.2
Loader {
    id: messages

    function displayMessage(message) {
        messages.source = "";
        messages.source = Qt.resolvedUrl("InfoBannerComponent.qml");
        messages.item.message = message;
    }

    width: parent.width
    anchors.bottom: parent.top
    z: 1
    onLoaded: {
        messages.item.state = "portrait";
        timer.running = true
        messages.state = "show"
    }

    Timer {
        id: timer

        interval: 2500
        onTriggered: {
            messages.state = ""
        }
    }

    states: [
        State {
            name: "show"
            AnchorChanges { target: messages; anchors { bottom: undefined; top: parent.top } }
            PropertyChanges { target: messages; anchors.topMargin: 100 }
        }
    ]

    transitions: Transition {
        AnchorAnimation { easing.type: Easing.OutQuart; duration: 300 }
    }
}

      

This is for InfoBannerComponent.qml



import QtQuick 2.2

Item {
    id: banner

    property alias message : messageText.text

    height: 70

    Rectangle {
        id: background

        anchors.fill: banner
        color: "darkblue"
        smooth: true
        opacity: 0.8
    }

    Text {
        font.pixelSize: 24
        renderType: Text.QtRendering
        width: 150
        height: 40
        id: messageText


        anchors.fill: banner
        horizontalAlignment: Text.AlignHCenter
        verticalAlignment: Text.AlignVCenter
        wrapMode: Text.WordWrap

        color: "white"
    }

    states: State {
        name: "portrait"
        PropertyChanges { target: banner; height: 100 }
    }

    MouseArea {
        anchors.fill: parent
        onClicked: {
            messages.state = ""
        }
    }
}

      

This is for main.qml

import QtQuick 2.3
import QtQuick.Window 2.2

Window {
    visible: true
    width: 360
    height: 360

    MouseArea {
        anchors.fill: parent
        onClicked: {
            Qt.quit();
        }
    }

    Text {
        text: qsTr("Hello World")
        anchors.centerIn: parent
    }

    InfoBanner {
        id: messages
    }

    Component.onCompleted: messages.displayMessage("Hello World");
}

      

credit to marxian at marxoft dot co dot uk

+5


source


A similar, but IMHO more elegant approach compared to fpermana's answer is below.

Toast.qml

, can be used autonomously and can be reused in a non-independent way:

import QtQuick 2.0

/**
* @brief An Android-like timed message text in a box that selfdestroys when finished if desired
*/
Rectangle{

    /**
    * Public
    */

    /**
    * @brief Shows this Toast
    *
    * @param {string} text Text to show
    * @param {real} duration Duration to show in milliseconds, defaults to 3000
    */
    function show(text, duration){
        theText.text = text;
        if(typeof duration !== "undefined"){
            if(duration >= 2*fadeTime)
                time = duration;
            else
                time = 2*fadeTime;
            }
        else
            time = defaultTime;
        anim.start();
    }

    property bool selfDestroying: false ///< Whether this Toast will selfdestroy when it is finished

    /**
    * Private
    */

    id: root

    property real time: defaultTime
    readonly property real defaultTime: 3000
    readonly property real fadeTime: 300

    property real margin: 10

    width: childrenRect.width + 2*margin
    height: childrenRect.height + 2*margin
    radius: margin

    anchors.horizontalCenter: parent.horizontalCenter

    opacity: 0
    color: "white"

    Text{
        id: theText
        text: ""

        horizontalAlignment: Text.AlignHCenter
        x: margin
        y: margin
    }

    SequentialAnimation on opacity{
        id: anim

        running: false

        NumberAnimation{
            to: 0.9
            duration: fadeTime
        }
        PauseAnimation{
            duration: time - 2*fadeTime
        }
        NumberAnimation{
            to: 0
            duration: fadeTime
        }

        onRunningChanged:{
            if(!running && selfDestroying)
                root.destroy();
        }
    }
}

      

ToastManager.qml

, creates and organizes Toast

if multiple instances are shown at the same time:



import QtQuick 2.0

/**
 * @brief Manager that creates Toasts dynamically
 */
Column{

    /**
     * Public
     */

    /**
     * @brief Shows a Toast
     *
     * @param {string} text Text to show
     * @param {real} duration Duration to show in milliseconds, defaults to 3000
     */
    function show(text, duration){
        var toast = toastComponent.createObject(root);
        toast.selfDestroying = true;
        toast.show(text, duration);
    }

    /**
     * Private
     */

    id: root

    z: Infinity
    spacing: 5
    anchors.centerIn: parent

    property var toastComponent

    Component.onCompleted: toastComponent = Qt.createComponent("Toast.qml")
}

      

main.qml

which uses ToastManager

:

import QtQuick 2.0

ApplicationWindow{
    visible: true

    /* other components of the application */

    ToastManager{ id: toast }

    onSomeEvent: toast.show("Some event happened")
    onImportantEvent: toast.show("An important event happened!", 5000)
}

      

+7


source


I improved on Ayberk Özgür 's answer by making it more like an Android implementation while still working on iOS. This implementation creates a black toast with white text that appears at the bottom of the screen. It also supports many simultaneous toasts using the ToastManager with the newest toast at the bottom and uses nice animations.

The code is available on Github and copied below for convenience:

Toast.qml

, can be used autonomously and can be reused in a non-independent way:

// Toast.qml
import QtQuick 2.0

/**
  * @brief An Android-like timed message text in a box that self-destroys 
  * when finished if desired
  */
Rectangle {

    /**
      * Public
      */

    /**
      * @brief Shows this Toast
      *
      * @param {string} text Text to show
      * @param {real} duration Duration to show in milliseconds, defaults to 3000
      */
    function show(text, duration) {
        message.text = text;
        if (typeof duration !== "undefined") { // checks if parameter was passed
            time = Math.max(duration, 2 * fadeTime);
        }
        else {
            time = defaultTime;
        }
        animation.start();
    }

    // whether this Toast will self-destroy when it is finished
    property bool selfDestroying: false  

    /**
      * Private
      */

    id: root

    readonly property real defaultTime: 3000
    property real time: defaultTime
    readonly property real fadeTime: 300

    property real margin: 10

    anchors {
        left: parent.left
        right: parent.right
        margins: margin
    }

    height: message.height + margin
    radius: margin

    opacity: 0
    color: "#222222"

    Text {
        id: message
        color: "white"
        wrapMode: Text.Wrap
        horizontalAlignment: Text.AlignHCenter
        anchors {
            top: parent.top
            left: parent.left
            right: parent.right
            margins: margin / 2
        }
    }

    SequentialAnimation on opacity {
        id: animation
        running: false 


        NumberAnimation {
            to: .9
            duration: fadeTime
        } 

        PauseAnimation {
            duration: time - 2 * fadeTime
        } 

        NumberAnimation {
            to: 0
            duration: fadeTime
        }

        onRunningChanged: {
            if (!running && selfDestroying) {
                root.destroy();
            }
        }
    }
}

      

ToastManager.qml

, creates and organizes toasts when multiple images are displayed at the same time:

// ToastManager.qml
import QtQuick 2.0

/**
  * @brief Manager that creates Toasts dynamically
  */
ListView {
    /**
      * Public
      */

    /**
      * @brief Shows a Toast
      *
      * @param {string} text Text to show
      * @param {real} duration Duration to show in milliseconds, defaults to 3000
      */
    function show(text, duration) {
        model.insert(0, {text: text, duration: duration});
    }

    /**
      * Private
      */

    id: root

    z: Infinity
    spacing: 5
    anchors.fill: parent
    anchors.bottomMargin: 10
    verticalLayoutDirection: ListView.BottomToTop

    interactive: false

    displaced: Transition {
        NumberAnimation {
            properties: "y"
            easing.type: Easing.InOutQuad
        }
    }

    delegate: Toast {
        Component.onCompleted: {
            if (typeof duration === "undefined") {
                show(text);
            }
            else {
                show(text, duration);
            }
        }
    }

    model: ListModel {id: model}
}

      

main.qml

which uses ToastManager

:

// main.qml
import QtQuick 2.0
import QtQuick.Controls 2.0

ApplicationWindow {
    visible: true
    height: 640
    width: 480
    id: root

    ToastManager {
        id: toast
    }

    Timer {
        interval: 1000
        repeat: true
        running: true
        property int i: 0
        onTriggered: {
            toast.show("This timer has triggered " + (++i) + " times!");
        }
    }

    Timer {
        interval: 3000
        repeat: true
        running: true
        property int i: 0
        onTriggered: {
            toast.show("This important message has been shown " + (++i) + " times.", 5000);
        }
    }
}

      

+2


source


I am writing this method (call from Qt)

public static void notify(String s)
{
m_instance.setNote(s);
int duration = Toast.LENGTH_SHORT;        
m_instance.runOnUiThread(new Runnable() {

            public void run() {
                Toast.makeText(m_instance, m_instance.getNote(), Toast.LENGTH_SHORT).show();
                Log.i(QtApplication.QtTAG,"run run Toast.makeText");

            }
    });

}

      

You need to store the context in the OnCreate event:

  public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);

     baseContext = getApplicationContext();
      m_instance = this;
}

      

credit to victorrbravo

0


source







All Articles