说明

我的实现方法,与网上的常见的方法不同,我觉得网上常见的方法太挫了,一点都不酷,Qt的核心价值观就是酷,所以怎么能用那么挫的方法呢。

根据Qt5.7后的一个新函数,我研究出了我认为比较酷的方法。

 

普通方法

想要Qt实现App全屏,在网上一搜就有很多文章教你怎么实现。

主要过程有三步:

1.添加一个继承自QtActivity的Activity;

2.在这个Activity上添加全屏代码;

3.修改AndroidManifest.xml文件的Launch Activity为这个Activity。

不知道为什么我感觉这个方法不太好。

继承QtActivity以及修改AndroidManifest.xml总是让我感觉不太科学。

因此我一直想找到不需要这么做的方法。在看到Qt5.7版本后的一个新函数后,我终于找到了实现的新方法。

 

新方法

要实现全屏有三个要解决的点:

1.要执行Java的代码;

2.要提供当前Activity(也有一种说法叫上下文,context);

3.要在UI线程执行。

为什么要在UI线程执行呢,因为在Android系统,全部跟界面有关的操作都要在UI线程执行。

如果在非UI线程执行全屏代码,程序则会崩溃。

而Qt自5.7后,在QtAndroid类新增了一个静态函数:

void QtAndroid::runOnAndroidThread(const QtAndroid::Runnable &runnable)

这个静态函数就是关键。

 

步骤

1.写Android全屏的Java代码

Android的全屏模式共有三种——普通全屏,沉浸式全屏,粘性沉浸式全屏。

详细资料:https://developer.android.com/training/system-ui/immersive

为了后续方便,这里使用了一个单例。

JFullScreen.java (文件路径:android\src\org\qtproject\junj)

package org.qtproject.junj;import android.app.Activity;import android.content.Context;import android.util.Log;import android.view.View;public class JFullScreen {    static final private String TAG = "JFullScreen";    static private JFullScreen mInstance = new JFullScreen();    private Context mContext = null;    private JFullScreen() { }    static public JFullScreen instance() { return mInstance; }    public void setContext(Context context) {        Log.d(TAG, "context: " + context.toString());        mContext = context;    }    public void fullScreenLeanBack() {        Log.d(TAG, "fullScreenLeanBack");        Activity activity = (Activity) mContext;        View decorView = activity.getWindow().getDecorView();        decorView.setSystemUiVisibility(                View.SYSTEM_UI_FLAG_LAYOUT_STABLE                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION                        | View.SYSTEM_UI_FLAG_FULLSCREEN);    }    public void fullScreenImmersive() {        Log.d(TAG, "fullScreenImmersive");        Activity activity = (Activity) mContext;        View decorView = activity.getWindow().getDecorView();        decorView.setSystemUiVisibility(                View.SYSTEM_UI_FLAG_IMMERSIVE                        | View.SYSTEM_UI_FLAG_LAYOUT_STABLE                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION                        | View.SYSTEM_UI_FLAG_FULLSCREEN);    }    public void fullScreenStickyImmersive() {        Log.d(TAG, "fullScreenStickyImmersive");        Activity activity = (Activity) mContext;        View decorView = activity.getWindow().getDecorView();        decorView.setSystemUiVisibility(                View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY                        | View.SYSTEM_UI_FLAG_LAYOUT_STABLE                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION                        | View.SYSTEM_UI_FLAG_FULLSCREEN);    }    public int addTest(int value0, int value1) {        Log.d(TAG, "I'm a test.");        return value0 + value1;    }}

2.使用JNI写调用Java代码的C++类

这里主要使用QAndroidJniObject类来实现调用Java代码,并使用QtAndroid::runOnAndroidThread让代码执行在UI线程。

关于QAndroidJniObject的使用技巧以后再讲。

仔细查看代码,可以发现Java部分之所以要用单例是有原因的,主要就是为了QtAndroid::runOnAndroidThread用起来更方便,在Runnable的实现里直接调用instance获取实例,不必每次再重新创建并传递Context。

jfullscreen.h

#ifndef JFULLSCREEN_H#define JFULLSCREEN_H#include class JFullScreen{public:    JFullScreen();    void fullScreenLeanBack();    void fullScreenImmersive();    void fullScreenStickyImmersive();    int addTest(int value0, int value1);private:    QAndroidJniObject _javaClass;};#endif // JFULLSCREEN_H

jfullscreen.cpp

#include "jfullscreen.h"#include <functional>#include <QtAndroid>// JFS: JFullScreen#define JFS_CLASSNAME "org/qtproject/junj/JFullScreen"#define JFS_SIGNTURE_INSTANCE "()Lorg/qtproject/junj/JFullScreen;"void realFullScreenLeanBackMethod() {    QAndroidJniObject javaCustomFunction = QAndroidJniObject::callStaticObjectMethod(JFS_CLASSNAME, "instance", JFS_SIGNTURE_INSTANCE);    javaCustomFunction.callMethod<void>("fullScreenLeanBack", "()V");}void realFullScreenImmersiveMethod() {    QAndroidJniObject javaCustomFunction = QAndroidJniObject::callStaticObjectMethod(JFS_CLASSNAME, "instance", JFS_SIGNTURE_INSTANCE);    javaCustomFunction.callMethod<void>("fullScreenImmersive", "()V");}void realFullScreenStickyImmersiveMethod() {    QAndroidJniObject javaCustomFunction = QAndroidJniObject::callStaticObjectMethod(JFS_CLASSNAME, "instance", JFS_SIGNTURE_INSTANCE);    javaCustomFunction.callMethod<void>("fullScreenStickyImmersive", "()V");}JFullScreen::JFullScreen(){    if(!QAndroidJniObject::isClassAvailable(JFS_CLASSNAME)) {        qDebug("JFullScreen is unavailable.");        return;    }    _javaClass = QAndroidJniObject::callStaticObjectMethod(JFS_CLASSNAME, "instance", JFS_SIGNTURE_INSTANCE);    if(!_javaClass.isValid()) {        qDebug(" JFullScreen instance is invalid.");    }    _javaClass.callMethod<void>("setContext", "(Landroid/content/Context;)V", QtAndroid::androidActivity().object<jobject>());}//use runOnAndroidThread() in order to run on android ui threadvoid JFullScreen::fullScreenLeanBack(){    QtAndroid::Runnable runnable = realFullScreenLeanBackMethod;    QtAndroid::runOnAndroidThread(runnable);}void JFullScreen::fullScreenImmersive(){    QtAndroid::Runnable runnable = realFullScreenImmersiveMethod;    QtAndroid::runOnAndroidThread(runnable);}void JFullScreen::fullScreenStickyImmersive(){    QtAndroid::Runnable runnable = realFullScreenStickyImmersiveMethod;    QtAndroid::runOnAndroidThread(runnable);}int JFullScreen::addTest(int value0, int value1){    jint sum = _javaClass.callMethod<jint>("addTest", "(II)I", value0, value1);    return sum;}

3.测试

创建一个JFullScreen进行测试。

    JFullScreen *pManager = new JFullScreen;    int sum = pManager->addTest(1, 2);    Q_ASSERT(sum == 3);//    pManager->fullScreenLeanBack();//    pManager->fullScreenImmersive();    pManager->fullScreenStickyImmersive();

总结

这样一来,我们整个代码的结构是非常简明的,感觉很清爽,不需要动那些不应该的动的东西,并且简单的复制到任何一个项目都可以直接使用,简直不能再棒了。

通过继承QtActivity并修改AndroidManifest.xml文件来实现的都没我酷,嗯。

Github

https://github.com/WingNan/QtAndroidFullScreen

效果

贴一下粘性沉浸模式的效果。


 

 

 

更多相关文章

  1. SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
  2. (转摘)Android腾讯微博客户端开发四:微博发送篇(QQ表情,@搜索)
  3. Android(安卓)App调用SDK 登录第一次总是失败的解决方法
  4. Android(安卓)弹无虚发之第四弹:你应该掌握的Notification(Notific
  5. 进程(一) 1.2 Android中异步处理大杀器——Handler(1)
  6. [置顶] android 程序开发的插件化 模块化方法 之二
  7. [置顶] Android(安卓)轻松实现网络交互模板
  8. 【Android(安卓)界面效果17】Android手机平板两不误,使用Fragment
  9. Android(安卓)IPC【Inter-Process Communication】机制二【Andro

随机推荐

  1. Android中的线程池与任务队列
  2. Android[中级教程]第十一章 Android异步
  3. Android面试系列文章2018之Android部分Bi
  4. android studio导入其他项目工程报错解决
  5. 基于Java Socket的自定义协议,实现Android
  6. 手机硬件形态
  7. Android apk 签名总结
  8. android的EditText里文字和图片混合编辑
  9. Android(安卓)studio无法连接识别检测各
  10. 《Android第一行代码》笔记