切换全屏模式

22

我需要一些帮助来切换全屏模式。我在偏好设置界面中有一个选项可以进入全屏模式。在我的主活动的onResume方法中,我有:

if(mFullscreen == true) {
                getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
                getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);

            } else
            {
                getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
                getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

            }

但是这似乎行不通,因为它需要在setContentView之前调用,对吧?

... 而且,我已经在setContentView之前使用了requestWindowFeature (Window.FEATURE_NO_TITLE);,它除去了标题栏和状态栏... 有人可以提供帮助吗?

---编辑--- 好的,我发现有个错误导致这个方法无法正常工作。所以它现在实际上可以用了。现在,我只需要知道如何切换标题栏。

6个回答

30
private void setFullscreen(boolean fullscreen)
{
    WindowManager.LayoutParams attrs = getWindow().getAttributes();
    if (fullscreen)
    {
        attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
    }
    else
    {
        attrs.flags &= ~WindowManager.LayoutParams.FLAG_FULLSCREEN;
    }
    getWindow().setAttributes(attrs);
}

9
/**
 * toggles fullscreen mode
 * <br/>
 * REQUIRE: android:configChanges="orientation|screenSize"
 * <pre>
 * sample:
 *     private boolean fullscreen;
 *     ................
 *     Activity activity = (Activity)context;
 *     toggleFullscreen(activity, !fullscreen);
 *     fullscreen = !fullscreen;
 * </pre>
 */
private void toggleFullscreen(Activity activity, boolean fullscreen) {
    if (Build.VERSION.SDK_INT >= 11) {
        // The UI options currently enabled are represented by a bitfield.
        // getSystemUiVisibility() gives us that bitfield.
        int uiOptions = activity.getWindow().getDecorView().getSystemUiVisibility();
        int newUiOptions = uiOptions;
        boolean isImmersiveModeEnabled =
                ((uiOptions | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) == uiOptions);
        if (isImmersiveModeEnabled) {
            Log.i(context.getPackageName(), "Turning immersive mode mode off. ");
        } else {
            Log.i(context.getPackageName(), "Turning immersive mode mode on.");
        }

        // Navigation bar hiding:  Backwards compatible to ICS.
        if (Build.VERSION.SDK_INT >= 14) {
            newUiOptions ^= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
        }

        // Status bar hiding: Backwards compatible to Jellybean
        if (Build.VERSION.SDK_INT >= 16) {
            newUiOptions ^= View.SYSTEM_UI_FLAG_FULLSCREEN;
        }

        // Immersive mode: Backward compatible to KitKat.
        // Note that this flag doesn't do anything by itself, it only augments the behavior
        // of HIDE_NAVIGATION and FLAG_FULLSCREEN.  For the purposes of this sample
        // all three flags are being toggled together.
        // Note that there are two immersive mode UI flags, one of which is referred to as "sticky".
        // Sticky immersive mode differs in that it makes the navigation and status bars
        // semi-transparent, and the UI flag does not get cleared when the user interacts with
        // the screen.
        if (Build.VERSION.SDK_INT >= 18) {
            newUiOptions ^= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
        }
        activity.getWindow().getDecorView().setSystemUiVisibility(newUiOptions);
    } else {
        // for android pre 11
        WindowManager.LayoutParams attrs = activity.getWindow().getAttributes();
        if (fullscreen) {
            attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
        } else {
            attrs.flags &= ~WindowManager.LayoutParams.FLAG_FULLSCREEN;
        }
        activity.getWindow().setAttributes(attrs);
    }

    try {
        // hide actionbar
        if (activity instanceof ActionBarActivity) {
            if (fullscreen) ((ActionBarActivity) activity).getSupportActionBar().hide();
            else ((ActionBarActivity) activity).getSupportActionBar().show();
        } else if (Build.VERSION.SDK_INT >= 11) {
            if (fullscreen) activity.getActionBar().hide();
            else activity.getActionBar().show();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

    // set landscape
   // if(fullscreen)  activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
   // else activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
}

我的代码在Android 2.3和4.4.2上运行良好。


2
很棒的最新更新方法!不过有两个问题:1)newUiOptions修改缺少非全屏“&= ~xxx”部分,2)最新的appcompat库使用AppCompatActivity而不是ActionBarActivity。 - Eric Chen

7

自从Jellybean (4.1)版本起,有一种新的方法可以实现全屏,而不需要依赖WindowManager。相反,可以使用窗口的setSystemUiVisibility方法来实现,这比使用WindowManager标志位更加精细控制系统栏。以下是启用全屏的方法:

if (Build.VERSION.SDK_INT < 16) { //ye olde method
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                    WindowManager.LayoutParams.FLAG_FULLSCREEN);
} else { // Jellybean and up, new hotness
    View decorView = getWindow().getDecorView();
    // Hide the status bar.
    int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
    decorView.setSystemUiVisibility(uiOptions);
    // Remember that you should never show the action bar if the
    // status bar is hidden, so hide that too if necessary.
    ActionBar actionBar = getActionBar();
    actionBar.hide();
}

以下是如何还原上面的代码:

if (Build.VERSION.SDK_INT < 16) { //ye olde method
    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
} else { // Jellybean and up, new hotness
    View decorView = getWindow().getDecorView();
    // Hide the status bar.
    int uiOptions = View.SYSTEM_UI_FLAG_VISIBLE;
    decorView.setSystemUiVisibility(uiOptions);
    // Remember that you should never show the action bar if the
    // status bar is hidden, so hide that too if necessary.
    ActionBar actionBar = getActionBar();
    actionBar.show();
}

请注意,您可能需要调用 getSupportActionBar() 方法。 - Jake Lee
我使用了这种方法,在华为手机上状态栏已经隐藏,但是视图不能自动调整位置到屏幕顶部。 - Carl

5

有一种更短的全屏切换方法实现:

private void toggleFullscreen() {
    WindowManager.LayoutParams attrs = getWindow().getAttributes();
    attrs.flags ^= WindowManager.LayoutParams.FLAG_FULLSCREEN;
    getWindow().setAttributes(attrs);
}

它使用按位异或逻辑来切换FLAG_FULLSCREEN标志。

1
不隐藏底部导航栏。 - Shadow

3

我的解决方案结合了以下答案:

我将这些方法添加到了我的Activity中。要切换全屏,请使用setFullScreen(!isFullScreen())

public boolean isFullScreen() {

    return (getWindow().getAttributes().flags & 
        WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
}

@SuppressLint("NewApi")
public void setFullScreen(boolean full) {

    if (full == isFullScreen()) {
        return;
    }

    Window window = getWindow();
    if (full) {
        window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
    } else {
        window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }

    if (Build.VERSION.SDK_INT >= 11) {
        if (full) {
            getActionBar().hide();
        } else {
            getActionBar().show();
        }
    }
}

在我的情况下,我想要一个菜单按钮来进行切换。问题是:在没有硬件菜单按钮的设备上,隐藏操作栏也会隐藏从全屏返回的切换选项。因此,我添加了一些额外逻辑,仅在设备具有硬件菜单按钮时才隐藏操作栏。请注意,运行SDK 11-13的设备没有此按钮。
    if (Build.VERSION.SDK_INT >= 14 
        && ViewConfiguration.get(this).hasPermanentMenuKey()))) {

        if (full) {
            getActionBar().hide();
        } else {
            getActionBar().show();
        }
    }

旧设备(运行着Gingerbread或更早版本)使用的是标题栏而不是操作栏。以下代码将隐藏它,但请注意,一旦活动开始,标题栏就无法显示/隐藏。我在帮助菜单中为用户添加了一条消息,说明全屏模式的更改可能在旧设备上直到重新启动应用程序/活动后才能完全生效(这当然假定您保留了他们的选择并且只有在他们想要全屏时才执行此代码)。

    // call before setContentView()
    if (Build.VERSION.SDK_INT < 11) {
        requestWindowFeature(Window.FEATURE_NO_TITLE);
    }

1

Kotlin实现全屏的解决方案。

if (isFullscreen) {
    WindowInsetsControllerCompat(activity?.window!!, root).apply {
        hide(WindowInsetsCompat.Type.systemBars())
        systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
    }
} else {
    WindowInsetsControllerCompat(activity?.window!!, root)
        .show(WindowInsetsCompat.Type.systemBars())
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接