实现Qt平台下,安卓系统状态栏的相关设置(全透明,半透明、全屏,设置状态栏颜色,修改程序图标,网上文章大多数提供多种方法,但是讲述的云里雾里,没有说清楚,以下是本人自己整理,希望大家相互交流学习)
实验环境:
Qt 5.12
编程语言:qml 和 c++
运行平台:android
正如文章标题所述:在Qt平台上运行安卓程序使得程序的转态栏为透明(默认不设置的话是黑色,巨丑)。设置透明运行结果如下:
图中红色箭头所指区域则是系统的转态栏,这个是在我的电脑模拟器上运行的,实际运行是一样的。
在开始讲解实现的方法之前,你先要了解一下相关的术语,如图:
具体的实现步骤如下:
一、Qt Android 版本之间的变革:
1.1、说道这里,就必须得说一说Qt Android的版本问题了,很多人在做实际的操作的时候,没有想自己的Qt版本,所以很多别人的方法自己不能成功也是理所应当的。
1.2、言归正传,如果我没有记错的话,Qt从5.8以后,就把Android平台的开发并入到了linux、windows、mac的开发环境中,以前的时候还需要去下载一个单独的 Qt for Android 的 Qt开发环境。所以,接下来我所使用的方法,低于5.9的Qt版本,对你们不会有作用的(应该)。
1.3、目前很多开发基本上都已经升级到了5.9,而我时刻保持着最新,目前使用的是Qt5.12的版本(截止本文代码编写完时)。
二、废话不多说,看看知识库:
2.1、正如你在Qt中配置Android开发环境一样,里面需要用到的是Java JDK、Android SDK、NDK,还有一个Ant。这些东西总结一句话的概括就是把你的c++代码通过其中的组件编译成为Android的产物,所以,接下来的操作我们就要想想办法在这里面去动动手脚,只是靠c++,可能是不得行的。
2.2、在你的Qt安装目录下,有很多的平台的开发文件,以及相关的工具,所以,你配置了Android环境自然而然也有相关的文件。如下所示:
对于各个不一样的平台都有特定的连接工具以及相对应的文件。
在这里,需要注意的是,android_x86 和 android_armv7 的区别是:同样运行安卓系统,只是对应设备的架构不一样,一个是x86,一个是arm,架构不一样,对应的指令集也就不一样。
2.3、Android软件的开发中,会有一个配置文件,叫做:AndroidManifest.xml,他的作用很多,后面用到了再说,请记住,这个文件真的很重要,多看几眼,免得你又不认识他了。
2.4、安卓系统的启动,或者说安卓系统的入口文件,入口函数是 **OnCreate()**方法,在后续的相关操作中,我们都将从中进行相关的修改。
2.5、问题来了,那么Qt程序的入口就应该和这个**OnCreate()**方法有着千丝万缕的关系了,那么,在Qt的源文件中,这个方法在哪里呢?让我来告诉你吧,在你安装Qt目录下的这个位置:
F:\SoftWareCatelogy\Qt\5.12.0\android_x86\src\android\java\src\org\qtproject\qt5\android\bindings
org\qtproject\qt5\android\bindings这个路径在AndroidManifest.xml文件中引用的格式为org.qtproject.qt5.android.bindings.XXXX
这个是我的Qt安卓路径,请自行对照自己的安卓路径。在这个文件夹内,有如下文件:
备注:图中红色区域需要格外注意。
三、一顿操作猛如虎,原来不是二百五:
好了,说了这么多,进入正题。
3.1、AndroidManifest.xml文件在哪里?
这个文件的作用不多说,默认的如果你自己不写,那么他会在你编译为安卓程序的时候,自动的在你的生成目录中,如下所示:
在你的工程目录下新建一个名为AndroidSource的文件夹,并复制一份这个文件到你的工程目录下,在你的工程里面(pro文件内),添加如下代码:ANDROID_PACKAGE_SOURCE_DIR = $$PWD/AndroidSource
如图所示:
接下来就是在你的资源文件中,把这个文件添加进来,添加好后如下所示:
接下来,双击这个文件,Qt就会以图形化的方式加载这个xml文件了,相关的描述已经写好自己看,修改程序的图标就在这里就可以进行修改了,但是需要把图片以资源的形式添加到项目中。内容如下:
3.2、修改程序为全屏模式,状态栏也相应的隐藏掉:
在3.1中,我们已经说了AndroidManifest.xml这个文件,接下来,我们使用文本方式打开这个文件。
内容如下:
这个是我截图一个大的,下面给出activity这个标签的截图,就是上图的红色框框内容;
在上面这个图里面,红色划线的地方实际上就是指明安卓的启动入口文件是那个。在第二节 2.5 的那个图的文件就是在这里被引用的。
当然了,修改为全屏只需要在这里添加这么一句代码即可:
android:theme = "@android:style/Theme.NoTitleBar.Fullscreen"
如下所示:
然后保存运行就可以实现全屏了。效果如下:
和本文的第一张图片很明显的可以看得出来,这里没有了系统状态栏了,程序设置成了全屏模式。
四、设置系统栏显示且透明悬浮于我们的程序上面,也叫沉浸式风格
如果你仅仅满足这一点需求,后面的内容你大可跳过,或者收藏一波,下次继续看。
4.1、根据上面的思路,我们总结一下,我们的所有功能设置都是在这个AndroidManifest.xml文件实现的,接下里,我们将进行一些高级的深入研究。
4.2、还记得3.2中有一个图里面我画了横向并且写了一个重点的图吗?就知道你懒,我又给你粘贴下来了。图片如下。
在这个图片里面,实际上这句划线的代码的意思就是说,启动安卓的入口文件在哪里。把这句话翻译一下,就应该是这样的:
\org\qtproject\qt5\android\bindings\QtActivity这个实际上就是我在 2.5 中所提到的OnCreate()方法,你打开 QtActivity.java这个文件,就能找到这个方法,内容如下:
接下来,我们要做的就是,重写这个入口函数,然后设置程序为全屏,并且状态栏悬浮在我们的程序上。
4.3、重写入口函数,设置相关信息
在2.5节的文件夹下,添加一个名为QtFullscreenActivity.java的文件。如下:
然后打开,并添加如下代码:
package an.qt.QtFullscreenActivityAPP;//指明文件包名
import android.content.Context;
import android.content.Intent;
import android.app.PendingIntent;
import android.util.Log;
import android.os.Bundle;
import android.view.WindowManager;
//继承 QtActivity 类
public class QtFullscreenActivity extends org.qtproject.qt5.android.bindings.QtActivity
{
private final static String TAG = "QtFullscreen";
@Override
// 重写 onCreate 方法
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 设置全屏并且状态栏悬浮程序之上
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().getDecorView().setFitsSystemWindows(true);
}
}
这个文件写好了,我们再打开AndroidManifest.xml,修改入口类方法为我们自己重写的方法QtFullscreenActivity,在这个文件中添加如下代码:android:name="an.qt.QtFullscreenActivityAPP.QtFullscreenActivity"
红色框框放大如下,需要删除这句配置:android:theme = "@android:style/Theme.NoTitleBar.Fullscreen
然后保存,运行结果如下,和本文的第一张图雷同了。
4.4、设置状态栏颜色
历经千辛万苦,终于实现了这个功能,但是你觉得这样还是不好看,给人一种背部被遮挡了感觉,所以,你想实现一个这样的效果,类似如下:
想要一个红色的状态栏,这样看起来更加协调一点,最起码对于我这种强迫症的人来说,我是非得需要这里有颜色,没有颜色我就卸载软件。
还好我实现了这个功能,不然这篇博客你就没得看了。骚操作如下:
以下部分是经过请假安卓开发人员才得以实现,掌握多门技术得多重要啊。
注意,以下的代码需要在安卓平台5.0以上貌似才可以,如果不得行,请自行找方法,只能帮你到这里了。
4.5、设置状态栏为全透明
实现上诉的效果可以直接设置状态栏为透明,然后在qml程序里面进行设置背景颜色,给人一种错觉就是设置的背景颜色,但是,实际效果不是很好,因为跨平台上,状态栏的高度不好把握。具体的步骤如下。
1)、在 QtFullscreenActivity.java 这个文件中,修改代码如下:
package an.qt.QtFullscreenActivityAPP;//指明文件包名
import android.content.Context;
import android.content.Intent;
import android.app.PendingIntent;
import android.util.Log;
import android.os.Bundle;
import android.os.Build;
import android.graphics.Color;
import android.view.WindowManager;
import android.view.View;
//继承 QtActivity 类
public class QtFullscreenActivity extends org.qtproject.qt5.android.bindings.QtActivity
{
private final static String TAG = "QtFullscreen";
private static Context context;
@Override
// 重写 onCreate 方法
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 获取程序句柄
context = getApplicationContext();
// 设置状态栏全透明
// this.setStatusBarFullTransparent();
}
//全局获取Context
public static Context getContext() {
return context;
}
//全透状态栏
private void setStatusBarFullTransparent()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);//透明状态栏
// 状态栏字体设置为深色,SYSTEM_UI_FLAG_LIGHT_STATUS_BAR 为SDK23增加
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
// 部分机型的statusbar会有半透明的黑色背景
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().setStatusBarColor(Color.TRANSPARENT);// SDK21
}
}
}
2)、然后重新进行编译,效果如下:
接下来就是在你的程序里面,把程序向下移动,使得状态栏不被我们自己内容混淆。整么修改,你就自己去试试好了,我不想试了。
4.6、设置状态栏颜色
什么?你觉得这样还是没有满足你内心的欲望,还想继续搞点花样出来,ok,没有问题的,看下面。
1)、老规矩,在 QtFullscreenActivity.java 这个文件中,修改代码如下,这一部分的代码是在上面代码的基础上进行增加的,内容如下:
package an.qt.QtFullscreenActivityAPP;//指明文件包名
import android.content.Context;
import android.content.Intent;
import android.app.PendingIntent;
import android.util.Log;
import android.os.Bundle;
import android.os.Build;
import android.graphics.Color;
import android.view.WindowManager;
import android.view.View;
//继承 QtActivity 类
public class QtFullscreenActivity extends org.qtproject.qt5.android.bindings.QtActivity
{
private final static String TAG = "QtFullscreen";
private static Context context;
@Override
// 重写 onCreate 方法
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 获取程序句柄
context = getApplicationContext();
// 设置状态栏颜色,需要安卓版本大于5.0
this.setStatusBarColor("#FF4040");
// 设置状态栏全透明
// this.setStatusBarFullTransparent();
}
//全局获取Context
public static Context getContext() {
return context;
}
//全透状态栏
private void setStatusBarFullTransparent()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);//透明状态栏
// 状态栏字体设置为深色,SYSTEM_UI_FLAG_LIGHT_STATUS_BAR 为SDK23增加
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
// 部分机型的statusbar会有半透明的黑色背景
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().setStatusBarColor(Color.TRANSPARENT);// SDK21
}
}
// 非全透,带颜色的状态栏,需要指定颜色
private void setStatusBarColor(String color){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// 需要安卓版本大于5.0以上
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
getWindow().setStatusBarColor(Color.parseColor(color));
}
}
}
2)、注意,需要安卓版本大于5.0,因为5.0以上的版本才有这个函数。运行结果如下:
哇塞,历尽千辛万苦,终于可以了,我想,没有人比我写的更加详细了吧。
最后提示一下:如果你有多个安卓平台,都需要将 QtFullscreenActivity.java 这个文件放在你Qt默认的入口文件进行一起编译,参考2.5小节。
实际上,在安卓里面还可以通过其他方式进行设置,只是相对于Qt Android来说,目前比较好用的方法就是这样。里面很多的机制实际上和安卓有区别的,但是又脱不开关系的。
小哥哥我第一次写这么长的文章,看到这里,你不给我点个赞,你说你好意思不???
当然了,可恶的我又想到了一个问题,要是在程序里面,不同的页面需要设置不同的状态栏颜色的时候,整么破???哇,自己给自己挖坑。等有时间再来填坑吧。
最后,你如果有更好的办法或者已经实现了不同的页面进行设置状态栏颜色,请留言告知。
我的QQ:543985125