I have not started my learning Android developing by QML ,I just curious that Toasts seems to be a Android specific widget ,while Qt for Android seems doesn't have a ready-made corresponding widget, so how do you implement a Toast in Android by QML ?
Toast. makeText(getActivity(), "This is my Toast message!", Toast. LENGTH_LONG). show();
android.widget.Toast. A toast is a view containing a quick little message for the user. The toast class helps you create and show those. When the view is shown to the user, appears as a floating view over the application. It will never receive focus.
A similar but IMHO a more elegant approach compared to fpermana's answer is given below.
Toast.qml
, can be used standalone and can be reused in a non-selfdestroying manner:
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
s if more than one are shown simultaneously:
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
that uses the 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)
}
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
I've improved on Ayberk Özgür's answer by making it more similar to the Android implementation while still working the same on iOS. This implementation creates black toast with white text that appears at the bottom of the screen. It also supports multiple simultaneous toasts using 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 standalone and can be reused in a non-selfdestroying manner:
// 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 if more than one are shown simultaneously:
// 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
that uses the 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);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With