實作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