基本效果:上浮逐渐显示,短暂停留后上浮逐渐消失
为了能同时显示多个提示框,一是需要动态创建每个弹框 Item,二是弹出位置问题,如果是底部为基准位置就把已经弹出的往上移动。
效果展示:
主要实现代码:
(github链接:https://github.com/gongjianbo/MyTestCode/tree/master/Qml/TestQml_20240622_Toast)
(组件分ToastItem、ToastManager两个部分)
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15// 消息提示框
// 龚建波 2024-06-22
Window {id: control// width: context.implicitWidth + 40// height: context.implicitHeight + 30y: yShow - yOffsetflags: Qt.ToolTipcolor: "transparent"// 移动起始位置property real yFrom: 0// 移动暂留位置property real yStay: 0// 移动结束位置property real yTo: 0// 移动当前位置property real yShow: 0// 位置偏移property real yOffset: 0// 背景Rectangle {id: bganchors.fill: parentradius: 4color: "#99000000"}// 文字内容Text {id: contextanchors.centerIn: parentcolor: "white"}Behavior on yOffset {NumberAnimation {duration: 200}}SequentialAnimation {id: sequentialParallelAnimation {NumberAnimation {target: controlproperties: "opacity"from: 0.1to: 1duration: 200}NumberAnimation {target: controlproperties: "yShow"from: control.yFromto: control.yStayduration: 200}}NumberAnimation {target: controlproperties: "opacity"to: 1duration: 2500}ParallelAnimation {NumberAnimation {target: controlproperties: "opacity"to: 0.1duration: 200}NumberAnimation {target: controlproperties: "yShow"to: control.yToduration: 200}}onFinished: {control.close()}}// 弹出消息框function pop(tipText, screenRect) {context.text = tipTextcontrol.width = context.implicitWidth + 40control.height = context.implicitHeight + 20control.x = screenRect.x + (screenRect.width - control.width) / 2control.yStay = screenRect.y + (screenRect.height - control.height) / 4control.yFrom = control.yStay + 80control.yTo = control.yStay - 80control.opacity = 0.1control.yShow = control.yFromcontrol.show()sequential.start()}// 需要显示下一个消息,位置上移property int nextCount: 0function next() {// 限制同时显示的个数,多余的关闭if (nextCount >= 2) {control.close()return}nextCount++// 消息框之间保留间隔control.yOffset = nextCount * (control.height + 10)}
}
import QtQuick 2.15
import Test 1.0// 消息框管理
// 龚建波 2024-06-22
Item {id: control// 弹出新的消息时,信号通知已有的消息框上移signal showNext()property var toastArray: []Component {id: toast_compToastItem {id: toast_itemConnections {target: controlfunction onShowNext() {toast_item.next()}}onClosing: {toastArray.shift()toast_item.destroy()}Component.onDestruction: {console.log("onDestruction")}Component.onCompleted: {console.log("onCompleted")}}}ScreenTool {id: screen_tool}function showToast(msg) {let rect = screen_tool.focusRect()if (rect.width <= 0)returncontrol.showNext()let toast = toast_comp.createObject()// 存起来避免被gctoastArray.push(toast)toast.pop(msg, rect)}
}
#include "ScreenTool.h"
#include <QGuiApplication>
#include <QWindow>QRect ScreenTool::focusRect()
{QScreen *screen{nullptr};auto &&window = qApp->focusWindow();if (window) {screen = window->screen();} else {screen = qApp->primaryScreen();}if (screen) {return screen->availableGeometry();}return QRect();
}
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15Window {width: 640height: 480visible: truetitle: qsTr("Qml Toast")// 也可以注册为单例使用ToastManager {id: toast_manager}Row {anchors.centerIn: parentspacing: 10TextField {id: text_filedtext: "GongJianBo"}Button {text: "Pop"onClicked: {toast_manager.showToast(text_filed.text)}}}
}