本博介绍个人使用toast心得,现在 还未搞清楚,一点点来,这几天研究这个,目前还未学习qt for Android 的qml使用,暂时也没 时间去研究,所以就简单的先用c++实现,采用qt widget界面方式。toast效果实现两种方式,一种是原生调用,就得构建类去调用java的源代码,还有一种是自己写一种方式去实现toast的效果,下面我会详细介绍两种方式的 纯小白也能学会的创建和使用方式,然后也会附加上例程。
忘了附上参考链接,Qt for Android调用android原生Toast控件https://www.2cto.com/kf/201702/603177.html
Qt for Android创建AndroidManifest.xml和Java类文件https://blog.csdn.net/luoyayun361/article/details/72993841
附上gif效果
最近时间 比较匆忙,在午休空闲之间才能去研究一下qt for Android的各个应用,所以接下来我就以最简单的方式详细的说明 两种方法的创建使用流程。
1.自建仿toast方式
顾名思义,这个就是自己建一个仿真toast的类,在其中写好实现的效果,然后外部需要调用是直接调用这个类的成员函数即可,在此帖最后会放上一个链接,包含源代码,需要的可自行下载参考。(注:此方法也是参考其他帖子下载内容源代码)
创建好子类文件
代码分别如下
stoast.h
// 仿Android的toast提示框
// 适宜将此类实现为多线程下的单例模式
#ifndef STOAST_H
#define STOAST_H
#ifdef Q_OS_WIN32 //Windows 下使用VC++编译器的utf-8字符集解析源码
#if _MSC_VER >=1600
#pragma execution_character_set("utf-8")
#endif
#endif
SToast 部分用到
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
SingleTonSToast 部分用到
#include
#include
#include
#include
class SToast : public QWidget
{
Q_OBJECT
public:
explicit SToast(QWidget *parent = 0);
~SToast();
int duration()const;
void SetDuration(int msec); //持续显示时间,ms
signals:
public slots:
void setMessageVDuration(QString msg, int msecDisplayTime=2500); //消息显示多少毫秒消失
protected:
void paintEvent(QPaintEvent *event);
private:
QHBoxLayout *hLayout;
QVBoxLayout *vLayout;
QLabel *label; //提示文字
QLabel *labIcon; //图标
int msDuration; //单位ms
QTimer durationTimer;
QPropertyAnimation *animation;
void fadeInAnimation(); //淡出动画
void fadeOutAnimation(); //淡入动画
private slots:
void timeOver(); //定时器超时响应函数
void fadeInAnimationFinished(); //淡出动画结束响应槽
};
class SingleTonSToast
{
public:
/*! \brief 用于获得SingleTonSToast实例,使用单例模式。
* \return SingleTonSToast实例的引用。
*/
static /*SingleTonSToast*/SToast &getInstance(void)
{
#ifndef Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
if(!QAtomicPointer*SingleTonSToast*/SToast>::isTestAndSetNative()) //运行时检测
qDebug() << "SingleTonSToast类 Error: TestAndSetNative not supported!";
#endif
//使用双重检测。
/*! testAndSetOrders操作保证在原子操作前和后的的内存访问
* 不会被重新排序。
*/
if(instance.testAndSetOrdered(0, 0)){ //第一次检测
QMutexLocker locker(&mutex);//加互斥锁。
instance.testAndSetOrdered(0, new /*SingleTonSToast*/SToast);//第二次检测。
}
return *instance;
}
private:
SingleTonSToast(); //禁止构造函数。
SingleTonSToast(const SingleTonSToast &);//禁止拷贝构造函数。
SingleTonSToast & operator=(const SingleTonSToast &);//禁止赋值拷贝函数。
QReadWriteLock internalMutex; //函数使用的读写锁。
static QMutex mutex; //实例互斥锁。
static QAtomicPointer*SingleTonSToast*/SToast> instance; /*!<使用原子指针,默认初始化为0。*/
};
#endif // STOAST_H
stoast.cpp
#include "stoast.h"
//静态成员变量初始化。
QMutex SingleTonSToast::mutex;
QAtomicPointer*SingleTon*/SToast> SingleTonSToast::instance = 0;
SToast::SToast(QWidget *parent) : QWidget(parent)
{
//初始化成员
msDuration = 5000;
animation = new QPropertyAnimation(this, "windowOpacity");
//初始化窗口属性
setWindowOpacity(0); //达到比较好的淡出效果,需要将窗口设置完全透明,否则会有卡顿的效果
this->setAttribute(Qt::WA_TranslucentBackground,true); //设置背景透明
setWindowFlags(Qt::CustomizeWindowHint|Qt::FramelessWindowHint|Qt::Tool|Qt::WindowStaysOnTopHint);
setStyleSheet("background: black;color: white;border-radius: 5px;");
//窗口大小及位置属性
setFixedSize(700,100); //设置为固定窗口大小达到禁止调节窗口大小
// Unbtun下有当前桌面扩展,显示的桌面只是逻辑上的一部分,所以看不到居中的效果
//move((QApplication::desktop()->width() - width())/2,(QApplication::desktop()->height() - height())/2);
// 此方方法可以解决居中显示的问题
QRect curDesktopRc = QApplication::desktop()->screenGeometry(this); //获取显示本窗口的屏幕区域
move((curDesktopRc.width() - width())/2, (curDesktopRc.height() - height())/8*7); //屏幕居下显示
//图标、字容器初始化
//labIcon = new QLabel();
label = new QLabel();
label->setFont(QFont("宋体",16));
label->setAlignment(Qt::AlignCenter);
label->adjustSize(); //自适应文本
//label->setWordWrap(true); //自动折行
label->setMargin(4); //边距调整
//初始化布局
vLayout = new QVBoxLayout(); //承载文字
vLayout->addWidget(label);
vLayout->setAlignment(Qt::AlignCenter);
hLayout = new QHBoxLayout(); //承载图标和vLayout
//hLayout->addWidget(labIcon); 预留显示图标
hLayout->addLayout(vLayout);
hLayout->setAlignment(Qt::AlignCenter);
this->setLayout(hLayout);
//初始化定时器
connect(&durationTimer, &QTimer::timeout, this, &SToast::timeOver);
}
SToast::~SToast()
{
delete label; label = NULL;
delete labIcon; labIcon = NULL;
delete vLayout; vLayout = NULL;
delete hLayout; hLayout = NULL;
}
int SToast::duration() const
{
return msDuration;
}
void SToast::SetDuration(int msec)
{
msDuration = msec;
}
void SToast::setMessageVDuration(QString msg, int msecDisplayTime/*=2500*/)
{
// 待完善的功能
// 1. 对消息进行排队显示,忽略用户指定的显示时间,采用默认的显示时间
// 2. 对msg的长度适当限制
this->show();
if(!msg.isEmpty()){
label->setText(msg);
}
else{
label->setText("");
}
msDuration = msecDisplayTime;
//淡出画效果
fadeOutAnimation();
//开始显示计时
durationTimer.start(msDuration);
}
void SToast::fadeInAnimation()
{
//界面动画,改变透明度的方式消失1 - 0渐变
if(!animation)
return;
connect(animation, &QPropertyAnimation::finished, this, &SToast::fadeInAnimationFinished );
animation->setDuration(1500);
animation->setStartValue(0.8);
animation->setEndValue(0);
//animation->setEasingCurve(QEasingCurve::OutBounce);
animation->start();
}
void SToast::fadeOutAnimation()
{
//界面动画,改变透明度的方式出现0 - 1渐变
if(!animation)
return;
animation->setDuration(1500);
animation->setStartValue(0);
animation->setEndValue(0.8);
animation->start();
}
void SToast::timeOver()
{
durationTimer.stop();
//测试
//label->setText("显示时间到,你还有什么想说的吗?");
//淡入动画效果
fadeInAnimation();
}
void SToast::fadeInAnimationFinished()
{
disconnect(animation, &QPropertyAnimation::finished, this, &SToast::fadeInAnimationFinished );
this->close();
}
void SToast::paintEvent(QPaintEvent *event)
{
//TODO: coding below
QWidget::paintEvent(event);
}
其中有些参数是设置固定的,可根据个人需求进行更改,比如,toast显示位置横向在屏幕中间,纵向在屏幕7/8的 位置。。。
接下来就是调用了,在调用函数中首先 要包含其类的头文件,然后调用代码如下
SingleTonSToast::getInstance().setMessageVDuration("自定义类模拟toast测试toast", 2200);
函数的第一个参数是想toast的内容,第二个参数是toast显示的时间2200ms,第一种方法介绍完毕,如果只是简单的应用,不用麻烦的去创建java文件,用此方法即可调用,尤其是可在桌面应用程序中效果更为显著,在Android应用中建议用第二种方式。
2.调用Android原生的toast方法,此种方法只限应用在Android上,在window上无法实现,如果未配置过java的继承类,要配置一下,对于新手来说也算是复杂了,下面详细介绍无到有的步骤。
首先打开一个未配置过的项目,可以看到other files内无AndroidManifest.xml和java文件,没有other files文件夹的朋友也不要慌,不用自己创建,我这个就当 是没有一样一会添加文件会自动有
放一个我的配置图
编译一下你的qt for Android程序,可以发现在工程目录下
有个android-build文件夹,其中有个AndroidManifest.xml文件是我们需要的。
在工程目录下新建一个文件夹叫aaa,把xml文件放进去,如下
在你的pro文件中添加以下代码,意思是生成apk时会调用aaa文件夹中的AndroidManifest.xml文件
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/aaa
右键你的工程,添加现有文件,选择aaa中的xml文件,就有了以下内容
可以看到AndroidManifest.xml添加进来了,双击xml可配置Android的一些内容,比如图标啊,程序名称啊,也可进入xml程序中配置
可以切换xml程序和此界面。
到此,步骤完成1/3,以后发帖再也不会介绍这个的创建了,因为这是qt for Android最基础的东西了,也是开启qt开发Android的第一步和大门,反反复复介绍也没有必要。
接下里到了qt调用Android原生资源的关键步骤。
在aaa文件夹下的src文件夹下创建一个com文件夹
返回程序,创建新文件
命名随意,看个人,路径选择刚建立的com文件夹下
建立完毕,弹出如下界面,现在界面是空的,没有任何程序,程序运行起来也不会执行到这里,要配置一下,才可以执行这里进而去调用Android原生的一些资源,开启了qt for Android的大门,是从这里进去的。
java文件中添加如下代码
package com.ZtActivity;
import android.content.Intent;
import android.widget.Toast;
import android.os.Handler;
import android.os.Message;
import org.qtproject.qt5.android.bindings.QtActivity;
public class ZtActivity extends org.qtproject.qt5.android.bindings.QtActivity{
private static ZtActivity m_instance;
private static Handler m_handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
Toast toast = Toast.makeText(m_instance,(String)msg.obj, Toast.LENGTH_SHORT);
toast.show();
break;
};
}
};
public ZtActivity(){
m_instance = this;
}
public static void makeToast(String s){
m_handler.sendMessage(m_handler.obtainMessage(1, s));
}
}
第一行的package是很重要的
接下来打开xml文件,选择代码模式,找到划横线的行
后面有句Android:name
将其修改为
配置基本完毕,接下来去配置调用的方式,在pro文件中添加红框中内容,是要调用Android的资源
然后在你想调用toast的函数加上头文件
#include
#include
#include
#include
#include
然后在你想调用的地方加上调用代码,我是在关闭界面closeevent地方加上,用来提示再次按退出按键才退出程序
void Home::closeEvent(QCloseEvent *event)//点击系统自带关闭按钮回调函数
{
QAndroidJniObject javaToast = QAndroidJniObject::fromString("原生Android测试toast");
QAndroidJniObject::callStaticMethod("com/ZtActivity/ZtActivity",
"makeToast",
"(Ljava/lang/String;)V",
javaToast.object());
// event->ignore();//失能关闭窗口功能,只能隐藏/显示
}
编译,到手机,很顺利的部署成功
安装到手机上,运行效果如下gif
好了,内容就到这里
附上我的例程源码链接https://download.csdn.net/download/qq_37603131/11149265
对了最后说明一下,实现这个效果的主要目的是可以在一些场合提示一些信息,主要是想在最后一层界面退出程序时,想连续退出两次才会退出程序,第一次退出 只会提示再次点击退出才会退出程序,至于这个效果,相信就很 简单了吧,怎么操作我目前还未写,各位小伙伴自行研究哦