在Android和Xamarin.forms上全局保持沉浸模式

3
我希望在使用Xamarin.forms的Android应用程序中保持全局沉浸式模式。我已经阅读了一些博客和文章。 这个链接可以实现,但只能在我点击输入文本框或滚动屏幕之前生效,我想避免这种情况。 这个问题讨论了我的问题,但我不理解解决方案,也许它已经过时了。我的Android设备运行7.1版本,以下是我的代码:.Android MainActivityvoid OnCreatevoid OnCreate
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity{
    protected override void OnCreate(Bundle savedInstanceState){
        Xamarin.Essentials.Platform.Init(this, savedInstanceState);
        global::Xamarin.Forms.Forms.Init(this, savedInstanceState);

        TabLayoutResource = Resource.Layout.Tabbar;
        ToolbarResource = Resource.Layout.Toolbar;
        base.OnCreate(savedInstanceState);
        LoadApplication(new App());

        ImmersiveMode();
    }

    public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults){
        Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

        base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    public void ImmersiveMode() {
        int uiOptions = (int)(Forms.Context as Activity).Window.DecorView.SystemUiVisibility;
        uiOptions |= (int)SystemUiFlags.Fullscreen;
        uiOptions |= (int)SystemUiFlags.HideNavigation;
        uiOptions |= (int)SystemUiFlags.ImmersiveSticky;
        (Forms.Context as Activity).Window.DecorView.SystemUiVisibility = (StatusBarVisibility)uiOptions;
    }
}

我该如何解决这个问题?你能具体指出我应该在哪里放置新代码吗? 我对Xamarin.Forms不熟悉,它看起来很棘手。谢谢。
编辑:这段代码:this.Window.AddFlags(WindowManagerFlags.Fullscreen);.AndroidMainActivity上隐藏了带有wifi信号、时间、蓝牙等的Android状态栏。是否有类似的命令隐藏这些安卓按钮? enter image description here
1个回答

6

Window.DecorView.SystemUiVisibilityAndroid R (11)被弃用。在此API版本中有一种新的方法来实现这个功能。

以下是我在我的一个应用程序中使用的代码。我不得不重写MainActivity类中的一堆方法。

using System;

using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.OS;
using Android.Views;

namespace SampleApp.Droid
{
    [Activity(Label = "SampleApp", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize )]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            Xamarin.Essentials.Platform.Init(this, savedInstanceState);
            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
            LoadApplication(new App());
            SetFullscreenFlags();
        }

        protected override void OnResume()
        {
            base.OnResume();
            SetFullscreenFlags();
        }

        public override void OnWindowFocusChanged(bool hasFocus)
        {
            base.OnWindowFocusChanged(hasFocus);
            SetFullscreenFlags();
        }

        protected void SetFullscreenFlags()
        {
            var attrs = Window.Attributes;
            attrs.Flags |= WindowManagerFlags.Fullscreen;
            Window.Attributes = attrs;

            // BuildVersionCodes has a wrong value for Android R (1000 instead of 30)
            // https://github.com/xamarin/xamarin-android/issues/5723
            // if (Build.VERSION.SdkInt >= BuildVersionCodes.R)
            if ((int)Build.VERSION.SdkInt >= 30)
            {
                Window.SetDecorFitsSystemWindows(false);

                if (Window.InsetsController != null)
                {
                    Window.InsetsController.Hide(WindowInsets.Type.NavigationBars());
                    Window.InsetsController.Hide(WindowInsets.Type.StatusBars());
                    Window.InsetsController.Hide(WindowInsets.Type.SystemBars());
                    Window.InsetsController.Show(WindowInsets.Type.Ime());
                }
            }
            else
            {
                var uiOptions = (int)Window.DecorView.SystemUiVisibility;
                var newUiOptions = (int)uiOptions;

                newUiOptions |=
                    (int)SystemUiFlags.LayoutStable |
                    (int)SystemUiFlags.LayoutHideNavigation |
                    (int)SystemUiFlags.LayoutFullscreen |
                    (int)SystemUiFlags.HideNavigation |
                    (int)SystemUiFlags.Fullscreen |
                    (int)SystemUiFlags.ImmersiveSticky;

                Window.DecorView.SystemUiVisibility = (StatusBarVisibility)newUiOptions;
            }
        }

        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
        {
            Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

            base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }

    }
}

之前我也实现了 View.IOnSystemUiVisibilityChangeListener 接口。但是它已经过时并将在未来版本中被移除:

public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, View.IOnSystemUiVisibilityChangeListener
{
    protected override void OnCreate(Bundle savedInstanceState)
    {
        // omitted code

        Window.DecorView.SetOnSystemUiVisibilityChangeListener(this);
    }

    public void OnSystemUiVisibilityChange([GeneratedEnum] StatusBarVisibility visibility)
    {
        SetFullscreenFlags();
    }
}

编辑:

如果您希望在用户将焦点放在屏幕上的某个输入控件后仍保持沉浸模式,可以实现 ViewTreeObserver.IOnGlobalFocusChangeListener 接口。这是我是如何实现的:

public class MainActivity : 
    global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, 
    ViewTreeObserver.IOnGlobalFocusChangeListener
{
    protected override void OnCreate(Bundle savedInstanceState)
    {
        // ommited code
    }

    public override void SetContentView(View view)
    {
        base.SetContentView(view);

        if (view?.ViewTreeObserver != null)
            view.ViewTreeObserver.AddOnGlobalFocusChangeListener(this);
    }

    public override void SetContentView(View view, ViewGroup.LayoutParams @params)
    {
        base.SetContentView(view, @params);

        if (view?.ViewTreeObserver != null)
            view.ViewTreeObserver.AddOnGlobalFocusChangeListener(this);
    }

    public void OnGlobalFocusChanged(View oldFocus, View newFocus)
    {
        SetFullscreenFlags();
    }
}

它不起作用。当我打开应用程序时,按钮不显示,但当我按下输入或发送弹出窗口时,它们会出现并粘在整个应用程序上。 - David Zomada
@DavidZarzosoMoreno,当输入控件失去焦点时,您需要更新全屏标志。我在答案中添加了更多详细信息,说明您如何在MainActivity类中实现ViewTreeObserver.IOnGlobalFocusChangeListener接口。 - Mateus Henrique
此外,如果您想在本地对话框中保持沉浸模式,我认为没有简单的方法可以实现,但也许您可以在这里找到更多信息:如何在对话框中保持沉浸模式 - Mateus Henrique
非常好的回答。感谢你的帮助。 - undefined

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