【问题标题】:Hiding the navigation bar in pure android native在纯android原生中隐藏导航栏
【发布时间】:2017-04-24 21:39:04
【问题描述】:

我看过关于通过java隐藏android应用程序导航栏的文章和文章。但是,我想知道的是如何通过纯 android c++ 本机活动应用程序为全屏应用程序(游戏)删除导航栏(根本没有 JAVA!)。 android manifest 中的全屏可以隐藏顶部栏,但导航栏保持可见。

这是我要删除的Navigation Bar

我没有运气搜索过书籍,没有关于本地活动的实际文档,谷歌搜索没有任何结果。一些头文件中只有 cmets,它们是很小的 cmets,甚至没有帮助。看来纯 c++ android 应用程序的话题是一个黑点,但市场上出现的很多游戏都是用 c++ 编写的。

我也试过设置:

AConfiguration_setNavHidden(m_app->config, ACONFIGURATION_NAVHIDDEN_YES);

但它似乎什么都不做,实际上所有的 AConfiguratin_setXXX 似乎什么都不做。也许我在错误的地方调用它?创建窗口后,我在 APP_CMD_INIT_WINDOW 期间一直在调用它。我应该在哪里调用这个函数?

【问题讨论】:

  • AFAIK,如果不调用 Java API,您将无法做到这一点。您可能必须使用 GetMethodIDrelated functions 从纯 C++ 代码通过 JNI 调用 java 方法。 AConfiguration 可能不是您所需要的——基于对文档的快速浏览,它用于编辑 Java Configuration 对象。您需要为您的Activity 获取jobject,获取JNIEnv 并使用它来调用您的任务所需的Java 方法。
  • 我今天刚去面试,提到了这个问题,显然他们也有同样的问题,但是用纯c++解决了。在我离开之前我忘了问他们是怎么做到的,但听起来这是可能的。如果我找不到答案,我最后的办法是像正常人一样部分使用 Java。不过感谢您的意见!
  • 使用 C++ 调用带有 JNI 的 Java 方法 “纯 C++”,因为您没有编写任何 Java 代码 — 只是使用 JVM C++ API 调用 Java 方法。
  • 是的,我知道“纯 c++”仍在使用 java 调用。我只需要隐藏导航的秘密成分。我知道有一个,必须有!我部分使用 java 作为最后手段的意思是隐藏 java 上的导航。

标签: android c++ native native-activity


【解决方案1】:

所以!如果有人好奇,我确实通过翻阅 Microsoft 的一个茶壶示例得出了答案。这就是我想出的:

public class NameOfActivity extends NativeActivity {

void setImmersiveSticky() {
    View decorView = getWindow().getDecorView();
    decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN
            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    setContentView(R.layout.activity_main);

    int SDK_INT = android.os.Build.VERSION.SDK_INT;
    if (SDK_INT >= 19) {
        setImmersiveSticky();

        View decorView = getWindow().getDecorView();
        decorView.setOnSystemUiVisibilityChangeListener
                (new View.OnSystemUiVisibilityChangeListener() {
                    @Override
                    public void onSystemUiVisibilityChange(int visibility) {
                        setImmersiveSticky();
                    }
                });
    }
    super.onCreate(savedInstanceState);
}

@Override
protected void onResume() {
    //Hide toolbar
    int SDK_INT = android.os.Build.VERSION.SDK_INT;
    if (SDK_INT >= 11 && SDK_INT < 14) {
        getWindow().getDecorView().setSystemUiVisibility(View.STATUS_BAR_HIDDEN);
    } else if (SDK_INT >= 14 && SDK_INT < 19) {
        getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LOW_PROFILE);
    } else if (SDK_INT >= 19) {
        setImmersiveSticky();
    }
    super.onResume();
}

}

纯c++ android 开发还是使用java,它是从android SDK 目录里面的源码中获取的。您可以做的是通过一些额外的调整来扩展 NativeActivity。在清单中,您所要做的就是:

    android:hasCode="true"

然后最重要的部分是更改活动名称

        android:name="android.app.NativeActivity"

        android:name="com.example.package.NameOfActivity"

它仍然会调用 android main 并像常规的原生活动一样对其进行设置,但现在它为您提供了一个完全全屏的功能。我希望这可以帮助那里的人。我花了几天时间寻找答案,这就是我能想到的!

祝你好运!

【讨论】:

【解决方案2】:

我发现这段代码有效(要求 API 级别 > 19)。只需调用 main() 开头的函数即可。

void AutoHideNavBar(struct android_app* state)
{
    JNIEnv* env{};
    state->activity->vm->AttachCurrentThread(&env, NULL);

    jclass activityClass = env->FindClass("android/app/NativeActivity");
    jmethodID getWindow = env->GetMethodID(activityClass, "getWindow", "()Landroid/view/Window;");

    jclass windowClass = env->FindClass("android/view/Window");
    jmethodID getDecorView = env->GetMethodID(windowClass, "getDecorView", "()Landroid/view/View;");

    jclass viewClass = env->FindClass("android/view/View");
    jmethodID setSystemUiVisibility = env->GetMethodID(viewClass, "setSystemUiVisibility", "(I)V");

    jobject window = env->CallObjectMethod(state->activity->clazz, getWindow);

    jobject decorView = env->CallObjectMethod(window, getDecorView);

    jfieldID flagFullscreenID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_FULLSCREEN", "I");
    jfieldID flagHideNavigationID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_HIDE_NAVIGATION", "I");
    jfieldID flagImmersiveStickyID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_IMMERSIVE_STICKY", "I");

    const int flagFullscreen = env->GetStaticIntField(viewClass, flagFullscreenID);
    const int flagHideNavigation = env->GetStaticIntField(viewClass, flagHideNavigationID);
    const int flagImmersiveSticky = env->GetStaticIntField(viewClass, flagImmersiveStickyID);
    const int flag = flagFullscreen | flagHideNavigation | flagImmersiveSticky;

    env->CallVoidMethod(decorView, setSystemUiVisibility, flag);

    state->activity->vm->DetachCurrentThread();
}

【讨论】:

  • 这对我很有用,并且不需要添加 JVM 代码。这应该是公认的答案!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-06
  • 1970-01-01
  • 2017-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多